Update game screenshot
[Pixture/pixture_revival.git] / mods / rp_jewels / mapgen.lua
blobc9ba9bd63a5b445af35f59fe50c09fcb79bed2e7
1 -- Generate jewel ore.
3 -- Jewel ore generated in birch tree nodes in the giga tree decorations
4 -- in the Deep Forest biome.
5 -- The algorithm uses LVM to imitate Minetest's scatter ores,
6 -- since ores in Minetest are generated after decorations.
8 -- Fields of the original ore definition:
9 local clust_scarcity = 11*11*11
10 local clust_num_ores = 3
11 local clust_size = 6
12 local y_min = 0
14 -- Helper variables
15 local gigatree_decoration_id = minetest.get_decoration_id("rp_default:gigatree")
16 local biome_y
17 local biome_exists
18 if minetest.registered_biomes["Deep Forest"] then
19 biome_y = minetest.registered_biomes["Deep Forest"].y_min
20 biome_exists = true
21 else
22 biome_y = tonumber(minetest.get_mapgen_setting("water_level")) or 1
23 biome_exists = false
24 end
26 local lvm_buffer = {}
28 local c_birch = minetest.get_content_id("rp_default:tree_birch")
29 local c_jewel_ore = minetest.get_content_id("rp_jewels:jewel_ore")
31 -- Generation algorithm:
34 -- Helper function to find a random minimum/maxium range of length clust_size.
35 -- Returned numbers are offsets.
36 local rnd_minmax = function(pr)
37 local min = pr:next(- clust_size + 1, 0)
38 local max = min + (clust_size - 1)
39 return min, max
40 end
42 minetest.set_gen_notify({decoration=true}, {gigatree_decoration_id})
43 minetest.register_on_generated(function(minp, maxp, blockseed)
44 if maxp.y < y_min then
45 return
46 end
47 local ores_in_mapblock = {}
48 local pr = PseudoRandom(blockseed)
49 local deco_ok = true
50 if gigatree_decoration_id then
51 -- Was a giga tree was found anywhere in generated area?
52 local mgobj = minetest.get_mapgen_object("gennotify")
53 local deco = mgobj["decoration#"..gigatree_decoration_id]
54 deco_ok = deco and #deco > 0
55 end
56 if deco_ok then
57 -- This code tries to imitate scatter ores in Minetest
58 local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
59 local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
60 local data = vm:get_data(lvm_buffer)
61 -- Interate through all nodes and place jewel ore in birch tree nodes
62 -- with a low chance (1/clust_scarcity)
63 for z=minp.z, maxp.z do
64 for y=math.max(y_min, minp.y), maxp.y do
65 for x=minp.x, maxp.x do
66 local p_pos = area:index(x,y,z)
67 if data[p_pos] == c_birch then
68 local bdata, bname
69 if biome_exists then
70 bdata = minetest.get_biome_data({x=x,y=math.max(y, biome_y),z=z})
71 bname = minetest.get_biome_name(bdata.biome)
72 end
73 if ((not biome_exists) or (bname == "Deep Forest")) and pr:next(1, clust_scarcity) == 1 then
74 data[p_pos] = c_jewel_ore
75 table.insert(ores_in_mapblock, {x=x,y=y,z=z})
76 end
77 end
78 end
79 end
80 end
81 -- If jewel ore was placed in the first phase, also place additional near the initial ore
82 for o=1, #ores_in_mapblock do
83 local start_ore = ores_in_mapblock[o]
84 for n=1, clust_num_ores do
85 local ore = {}
86 local axes = {"z","y","x"}
87 for a=1, #axes do
88 local ax = axes[a]
89 -- New ores are placed within a randomly positioned bounding box
90 -- of size clust_size^3 around the initial ore
91 ore[ax] = start_ore[ax] + pr:next(rnd_minmax(pr))
92 -- Make sure we stay within minp, maxp
93 if ore[ax] < minp[ax] then
94 ore[ax] = minp[ax]
95 elseif ore[ax] > maxp[ax] then
96 ore[ax] = maxp[ax]
97 end
98 end
99 local p_pos = area:index(ore.x, ore.y, ore.z)
100 -- The new random pos must also be a birch tree to generate a jewel ore
101 if data[p_pos] == c_birch then
102 data[p_pos] = c_jewel_ore
106 -- Only write back to map when any ore was actually placed
107 if #ores_in_mapblock > 0 then
108 vm:set_data(data)
109 vm:write_to_map()
112 end)