5 local print2
=function(text
)
6 minetest
.log("info","rocks/gen/ "..text
)
10 rocksl
.GetNextSeed
=function()
11 rocksl
.seedseq
=rocksl
.seedseq
+20
12 print2("seed "..rocksl
.seedseq
)
18 rocks
.layer_initialize
=function(layer
)
19 layer
.stats
={ count
=0, total
=0, node
={}, totalnodes
=0 }
20 table.insert(layers
,layer
)
23 rocksl
.register_stratus
=function(layer
,name
,param
)
24 table.insert(layer
.localized
,{
26 spread
=(param
.spread
or 20),
27 height
=(param
.height
or 15),
28 treshold
=(param
.treshold
or 0.85),
29 secondary
=param
.secondary
,
30 seed
=(rocksl
.GetNextSeed()),
32 layer
.stats
.node
[name
]=0
37 rocks
.register_vein
=function(name
,param
)
40 wherein
=param
.wherein
,
41 miny
=param
.miny
, maxy
=param
.maxy
,
42 radius
={ average
=param
.radius
.average
, amplitude
=param
.radius
.amplitude
, frequency
=param
.radius
.frequency
},
43 density
=(param
.density
or 1),
45 secondary
=(param
.ores
or {}),
50 -- TODO: rewrite above function to register normal minetest ore, with
51 -- special params, so the below func is not necesary. The mt oregen runs in
52 -- separate therad (emerge) and it does not block server.
53 -- params: type=scatter scacrity=1 size=3 ores=27 : full chance of spawning, only limited by noise thr
54 -- EDIT: Need to edit mg_ore.cpp and Add following ore_types: layer, blob, region.
55 -- layer=2Dheightmap style layer with specific thickness
56 -- blob= 3D noise deformed sphere
57 -- region= 3D noise / treshold ore placement.
59 rocksl
.layergen
=function(layer
, minp
, maxp
, seed
)
60 if ( (layer
.top
.offset
+layer
.top
.scale
)>minp
.y
)
61 and ( (layer
.bot
.offset
-layer
.bot
.scale
)<maxp
.y
)
63 local stone_ctx
= minetest
.get_content_id("default:stone")
64 local air_ctx
= minetest
.get_content_id("air")
65 local dirt_ctx
= minetest
.get_content_id("default:dirt")
66 if layer
.debugging
then
67 layer
.primary
.ctx
= air_ctx
69 layer
.primary
.ctx
= minetest
.get_content_id(layer
.primary
.name
)
71 local timebefore
=os
.clock();
72 local manipulator
, emin
, emax
= minetest
.get_mapgen_object("voxelmanip")
73 local nodes
= manipulator
:get_data()
74 local area
= VoxelArea
:new
{MinEdge
=emin
, MaxEdge
=emax
}
75 local side_length
= (maxp
.x
- minp
.x
) + 1
76 local map_lengths_xyz
= {x
=side_length
, y
=side_length
, z
=side_length
}
78 local bottom
=minetest
.get_perlin_map(layer
.bot
,map_lengths_xyz
):get2dMap_flat({x
=minp
.x
, y
=minp
.z
})
80 for _
,loc
in ipairs(layer
.localized
) do
81 --defaults and overrides
82 local np
={ offset
= 0, scale
= 1, octaves
= 1, persist
= 0.7,
83 spread
= {x
=loc
.spread
, y
=loc
.height
, z
=loc
.spread
}, seed
=loc
.seed
}
84 --get noise and content ids
85 table.insert(localized
,
87 noise
=minetest
.get_perlin_map(np
,map_lengths_xyz
):get3dMap_flat(minp
),
88 treshold
=loc
.treshold
,
89 ctx
= minetest
.get_content_id(loc
.primary
),
95 print2("after noise: "..(os
.clock()-timebefore
))
96 for z
=minp
.z
,maxp
.z
,1 do
97 for y
=minp
.y
,maxp
.y
,1 do
98 for x
=minp
.x
,maxp
.x
,1 do
99 local pos
= area
:index(x
, y
, z
)
100 if (y
>bottom
[noise2d_ix
]) and (y
<layer
.top
.offset
)
101 and ( (nodes
[pos
]==stone_ctx
) or (nodes
[pos
]==dirt_ctx
) )
103 layer
.stats
.totalnodes
=layer
.stats
.totalnodes
+1
104 if nodes
[pos
]==stone_ctx
then nodes
[pos
] = layer
.primary
.ctx
end
105 for k
,loc
in pairs(localized
) do
106 if ( loc
.noise
[noise3d_ix
] > loc
.treshold
) then
108 layer
.stats
.node
[loc
.ndn
]=layer
.stats
.node
[loc
.ndn
]+1
113 noise2d_ix
=noise2d_ix
+1
114 noise3d_ix
=noise3d_ix
+1
116 noise2d_ix
=noise2d_ix
-side_length
118 noise2d_ix
=noise2d_ix
+side_length
120 print2("after loop: "..(os
.clock()-timebefore
))
121 manipulator
:set_data(nodes
)
122 --manipulator:calc_lighting()
123 --manipulator:update_liquids()
124 if layer
.debugging
then
125 manipulator
:set_lighting({day
=15,night
=15})
127 manipulator
:write_to_map()
128 print2("after commit: "..(os
.clock()-timebefore
))
129 layer
.stats
.count
=layer
.stats
.count
+1
130 layer
.stats
.total
=layer
.stats
.total
+(os
.clock()-timebefore
)
131 layer
.stats
.side
=side_length
135 local ignore_wherein
=nil
137 rocksl
.veingen
=function(veins
,minp
,maxp
,seed
)
138 local side_length
=(maxp
.y
-minp
.y
)
139 local random=PseudoRandom(seed
-79)
140 local timebefore
=os
.clock();
141 local manipulator
, emin
, emax
= minetest
.get_mapgen_object("voxelmanip")
142 local nodes
= manipulator
:get_data()
143 local area
= VoxelArea
:new
{MinEdge
=emin
, MaxEdge
=emax
}
144 local did_generate
=nil
145 for _
,vein
in ipairs(veins
) do
146 if (minp
.y
<vein
.maxy
) and (maxp
.y
>vein
.maxy
) then
147 local vr2
=vein
.radius
.average^
2
148 local vrm
=vein
.radius
.average
+vein
.radius
.amplitude
149 local noise_map
=minetest
.get_perlin_map(
152 scale
=vein
.radius
.amplitude
,
153 offset
=0, octaves
=1, persist
=0.7,
154 spread
={x
=vein
.radius
.frequency
, y
=vein
.radius
.frequency
, z
=vein
.radius
.frequency
}
155 },{x
=(vrm
*2)+1, y
=(vrm
*2)+1, z
=(vrm
*2)+1}
157 local iterations_count
= (vein
.rarity
*side_length
)^
3
158 -- Resolve node names to id's
159 iterations_count
=iterations_count
+(random:next(0,100)/100)
160 local primary_ctx
=minetest
.get_content_id(vein
.primary
)
161 for _
,sec
in pairs(vein
.secondary
) do sec
.ctx
=minetest
.get_content_id(sec
.ore
) end
162 --old:local wherein_ctx=minetest.get_content_id(vein.wherein)
164 for _
,wi
in pairs(vein
.wherein
) do wherein_set
[minetest
.get_content_id(wi
)]=true end
165 --print("vein "..vein.primary.." ic="..iterations_count.." p="..primary_ctx)
166 for iteration
=1, iterations_count
do
167 local x0
=minp
.x
+ random:next(0,side_length
)
168 local y0
=minp
.y
+ random:next(0,side_length
)
169 local z0
=minp
.z
+ random:next(0,side_length
)
170 local noise
=noise_map
:get3dMap_flat({x
=x0
-vrm
, y
=y0
-vrm
, z
=z0
-vrm
})
172 local posi
= area
:index(x0
, y0
, z0
)
173 if ignore_wherein
or wherein_set
[nodes
[posi]]
then
174 print("vein "..vein
.primary
.." @ "..x0
..","..y0
..","..z0
.." vrm="..vrm
)
179 local posc
= {x
=x
+x0
,y
=y
+y0
,z
=z
+z0
}
180 posi
= area
:index(posc
.x
, posc
.y
, posc
.z
)
181 local nv
=noise
[noise_ix
]
182 if (ignore_wherein
or wherein_set
[nodes
[posi]]
) and (((x^
2)+(y^
2)+(z^
2))<((vein
.radius
.average
+nv
)^
2)) then
183 nodes
[posi
]=primary_ctx
184 local luck
=random:next(0,99)
185 for _
,sec
in pairs(vein
.secondary
) do
186 luck
=luck
-sec
.percent
196 --print("vein "..vein.primary.." bad environmnent -"..minetest.get_node({x0,y0,z0}).name.."="..nodes[posi])
202 manipulator
:set_data(nodes
)
203 --manipulator:calc_lighting()
204 manipulator
:write_to_map()
205 print("end veingen "..(os
.clock()-timebefore
))
207 --print("end veingen (nothin generated)")
211 minetest
.register_on_generated(function(minp
, maxp
, seed
)
212 for _
,layer
in pairs(layers
) do rocksl
.layergen(layer
,minp
,maxp
,seed
) end
213 rocksl
.veingen(veins
,minp
,maxp
,seed
)
216 minetest
.register_on_shutdown(function()
217 for _
,ign
in pairs(layers
) do
218 print("[rocks] Stats for layer "..ign
.name
)
219 if (ign
.stats
.count
==0) then
220 print("[rocks] |- stats not available, no chunks generated")
222 print("[rocks] |- generated total "..ign
.stats
.count
.." chunks in "..ign
.stats
.total
.." seconds ("..(ign
.stats
.total
/ign
.stats
.count
).." seconds per "..ign
.stats
.side
.."^3 chunk)")
223 for name
,total
in pairs(ign
.stats
.node
) do
224 print("[rocks] |- "..name
..": "..total
.." nodes placed ("..(total
*100)/(ign
.stats
.totalnodes
).." %)")