From 660500c1be26159cdaabe54ed7a40bed15c9bda6 Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Thu, 12 Sep 2019 15:29:57 +0200 Subject: [PATCH] Make jewel ore generation functional again --- mods/default/mapgen.lua | 1 + mods/jewels/init.lua | 15 +----- mods/jewels/mapgen.lua | 100 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 14 deletions(-) create mode 100644 mods/jewels/mapgen.lua diff --git a/mods/default/mapgen.lua b/mods/default/mapgen.lua index 483ebcf..f0b2206 100644 --- a/mods/default/mapgen.lua +++ b/mods/default/mapgen.lua @@ -448,6 +448,7 @@ minetest.register_decoration( minetest.register_decoration( { + name = "default:gigatree", deco_type = "schematic", place_on = {"default:dirt_with_grass"}, sidelen = 16, diff --git a/mods/jewels/init.lua b/mods/jewels/init.lua index 227dc51..c67720d 100644 --- a/mods/jewels/init.lua +++ b/mods/jewels/init.lua @@ -243,20 +243,6 @@ minetest.register_node( sounds = default.node_sound_wood_defaults(), }) --- Ore - -minetest.register_ore( - { - ore_type = "scatter", - ore = "jewels:jewel_ore", - wherein = "default:tree_birch", - clust_scarcity = 11*11*11, - clust_num_ores = 3, - clust_size = 6, - y_min = 0, - y_max = 31000, -}) - crafting.register_craft( { output = "jewels:bench", @@ -288,5 +274,6 @@ achievements.register_achievement( -- The tool jewel definitions dofile(minetest.get_modpath("jewels").."/jewels.lua") +dofile(minetest.get_modpath("jewels").."/mapgen.lua") default.log("mod:jewels", "loaded") diff --git a/mods/jewels/mapgen.lua b/mods/jewels/mapgen.lua new file mode 100644 index 0000000..403f253 --- /dev/null +++ b/mods/jewels/mapgen.lua @@ -0,0 +1,100 @@ +-- Generate jewel ore. + +-- Jewel ore generated in birch tree nodes in the giga tree decorations +-- in the Deep Forest biome. +-- The algorithm uses LVM to imitate Minetest's scatter ores, +-- since ores in Minetest are generated after decorations. + +-- Fields of the original ore definition: +local clust_scarcity = 11*11*11 +local clust_num_ores = 3 +local clust_size = 6 +local y_min = 0 + +-- Helper variables +local gigatree_decoration_id = minetest.get_decoration_id("default:gigatree") +local biome_y = minetest.registered_biomes["Deep Forest"].y_min + +local lvm_buffer = {} + +local c_birch = minetest.get_content_id("default:tree_birch") +local c_jewel_ore = minetest.get_content_id("jewels:jewel_ore") + +-- Generation algorithm: +if gigatree_decoration_id then + + -- Helper function to find a random minimum/maxium range of length clust_size. + -- Returned numbers are offsets. + local rnd_minmax = function(pr) + local min = pr:next(- clust_size + 1, 0) + max = min + (clust_size - 1) + return min, max + end + + minetest.set_gen_notify({decoration=true}, {gigatree_decoration_id}) + minetest.register_on_generated(function(minp, maxp, blockseed) + if maxp.y < y_min then + return + end + local ores_in_mapblock = {} + local pr = PseudoRandom(blockseed) + local mgobj = minetest.get_mapgen_object("gennotify") + local deco = mgobj["decoration#"..gigatree_decoration_id] + -- If a giga tree was found anywhere in generated area, activate generation + if deco and #deco > 0 then + -- This code tries to imitate scatter ores in Minetest + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax}) + local data = vm:get_data(lvm_buffer) + -- Interate through all nodes and place jewel ore in birch tree nodes + -- with a low chance (1/clust_scarcity) + for z=minp.z, maxp.z do + for y=math.max(y_min, minp.y), maxp.y do + for x=minp.x, maxp.x do + local p_pos = area:index(x,y,z) + if data[p_pos] == c_birch then + local bdata = minetest.get_biome_data({x=x,y=math.max(y, biome_y),z=z}) + local bname = minetest.get_biome_name(bdata.biome) + if bname == "Deep Forest" and pr:next(1, clust_scarcity) == 1 then + data[p_pos] = c_jewel_ore + table.insert(ores_in_mapblock, {x=x,y=y,z=z}) + end + end + end + end + end + -- If jewel ore was placed in the first phase, also place additional near the initial ore + for o=1, #ores_in_mapblock do + local start_ore = ores_in_mapblock[o] + for n=1, clust_num_ores do + local ore = {} + local axes = {"z","y","x"} + for a=1, #axes do + local ax = axes[a] + -- New ores are placed within a randomly positioned bounding box + -- of size clust_size^3 around the initial ore + ore[ax] = start_ore[ax] + pr:next(rnd_minmax(pr)) + -- Make sure we stay within minp, maxp + if ore[ax] < minp[ax] then + ore[ax] = minp[ax] + elseif ore[ax] > maxp[ax] then + ore[ax] = maxp[ax] + end + end + local p_pos = area:index(ore.x, ore.y, ore.z) + -- The new random pos must also be a birch tree to generate a jewel ore + if data[p_pos] == c_birch then + data[p_pos] = c_jewel_ore + end + end + end + -- Only write back to map when any ore was actually placed + if #ores_in_mapblock > 0 then + vm:set_data(data) + vm:write_to_map() + end + end + end) +else + minetest.log("error", "[jewels] Decoration ID for gigatree not found!") +end