Add api for veins and ores. New api for layers.
[rocks.git] / init.lua
blobd78d30d344565bba797ed7ce874b772b9fe3b559
1 -- Load translation library if intllib is installed
3 local S
4 if (minetest.get_modpath("intllib")) then
5 dofile(minetest.get_modpath("intllib").."/intllib.lua")
6 S = intllib.Getter(minetest.get_current_modname())
7 else
8 S = function ( s ) return s end
9 end
11 rocks = {}
13 rocks.layers = {}
14 rocks.veins = {}
15 rocks.ores = {}
17 rocks.noiseparams_layers = {
18 offset = 0,
19 scale = 1,
20 spread = {x=300, y=300, z=300},
21 octaves = 3,
22 persist = 0.63
25 rocks.register_layer=function(name,params,rock)
26 assert(name)
27 assert(params)
28 assert(params.gain)
29 assert(params.height)
30 local maxheight
31 for ln,ld in pairs(rocks.layers) do
32 if (ld.height<params.height)and ((not ld.maxheight) or (ld.maxheight>params.height)) then ld.maxheight=params.height end
33 if (ld.height>params.height)and((not maxheight) or (maxheight>ld.height)) then maxheight=ld.height end
34 end
35 rocks.layers[name]= {
36 gain=params.gain,
37 height=params.height,
38 maxheight=maxheight,
39 limit=params.limit,
40 seed=params.seed,
41 rock={ block=rock },
42 veins={}
44 print("[rocks] layer "..name)
45 end
47 rocks.register_vein=function(name,params)
48 assert(name)
49 assert(params)
50 assert(not rocks.veins[name])
51 rocks.veins[name]={
52 np={
53 offset=0, scale=1, octaves=1, presist=0.8,
54 spread=params.spread, seed=params.seed
56 treshold=params.treshold,
57 hmin=params.hmin, hmax=params.hmax,
58 layers=params.layers,
59 ores={}
61 for ln,ld in pairs(rocks.layers) do
62 ld.veins[name]=rocks.veins[name]
63 end
64 print("[rocks] vein "..name)
65 end
67 rocks.register_ore=function( vein, node, params )
68 -- params= {treshold=0, chance=1 }
69 ore={ node=node }
70 if params.treshold and (params.treshold>rocks.veins[vein].treshold) then
71 ore.treshold=params.treshold
72 end
73 if params.chance and (params.chance<1) then
74 ore.chance=params.chance
75 end
76 table.insert(rocks.veins[vein].ores, ore)
77 print("[rocks] ore "..node.." in "..vein.." chance="..(ore.chance or "1").." treshold="..(ore.treshold or rocks.veins[vein].treshold))
78 end
81 -- test layer
84 rocks.register_layer("test1",{ gain=40, height=70, limit=2, seed=1 },"rocks:black_granite")
86 -- uhlie ako vrstva je kokotina.
88 rocks.register_layer("test3",{ gain=40, height=65, limit=2, seed=3 },"rocks:pink_granite")
90 rocks.register_layer("test4",{ gain=40, height=90, limit=2, seed=4 },"rocks:white_granite")
93 -- test vein
96 rocks.register_vein("testvein1",{
97 spread = {x=5, y=90, z=5}, -- tall, narrow
98 -- larger values -> larger and less frequent vein
99 treshold=0.5, -- betveen -2 and +2, mapgen will use this or per-ore treshold if it is larger
100 -- 2 never generate
101 -- 1 extremly rare
102 -- 0 50% chance
103 -- less than 0 = SPAM
104 seed = 9, -- random seed
105 hmin=65, -- set to nil to generate everywhere
106 hmax=90,
107 layers={ "test3" }, -- only occur in layers
109 rocks.register_ore( "testvein1", "default:dirt" , {treshold=0, chance=1 } )
110 -- treshold=0 chance=1 ... generate everywhere
111 rocks.register_ore( "testvein1", "default:wood" , {treshold=0, chance=0.2} )
112 -- chance<1 ... vein contains chance*100% of the material, evenly randomly distributed
113 rocks.register_ore( "testvein1", "default:lava_source", {treshold=0.8, chance=1 } )
114 -- treshold>0 ... generate in the center, larger value -> narrower
115 -- 20% wood, lava in center, dirt the rest
116 -- ore with smallest chance and highest treshold is selected
119 for ln,ld in pairs(rocks.layers) do
120 -- print("[rocks] debug: "..ln..": "..minetest.serialize(ld))
124 -- layer generator
127 local function mknoises(layers,minp,maxp)
128 local nm={}
129 for ln,ld in pairs(rocks.layers) do
130 if (ld.height-ld.gain<maxp.y)and((not ld.maxheight)or(ld.maxheight+ld.gain>minp.y)) then
131 local np=rocks.noiseparams_layers
132 np.seed=ld.seed
133 local side_length = maxp.x - minp.x + 1
134 ld.nmap=minetest.get_perlin_map(np,{x=side_length, y=side_length, z=side_length}):get2dMap({x=minp.x, y=minp.z})
135 table.insert(nm,ld)
138 return nm
141 local function mkheightmap(layers,x,z,minp,maxp)
142 local hm={}
143 for ln,ld in pairs(layers) do
144 local noise=ld.nmap[z-minp.z+1][x-minp.x+1]
145 if math.abs(noise)<ld.limit then
146 ld.nh = (noise*ld.gain)+ld.height
147 -- if (ld.nh<maxy)and(ld.nh>miny)
148 table.insert(hm,ld)
151 return hm
154 local stonectx=nil
156 minetest.register_on_generated(function(minp, maxp, seed)
157 if not stonectx then stonectx= minetest.get_content_id("default:stone") end
158 -- noise values range (-1;+1) (1 octave)
159 -- 3 octaves it is like 1.7 max
160 -- 4 octaves with 0.8 presist = 2.125 max !!
161 -- if ...
162 local timebefore=os.clock();
163 local manipulator, emin, emax = minetest.get_mapgen_object("voxelmanip")
164 local nodes = manipulator:get_data()
165 local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
166 -- initialize noises and sort out unused layers
167 local availlayers=mknoises(rocks.layers,minp,maxp)
169 for x=minp.x,maxp.x,1 do
170 for z=minp.z,maxp.z,1 do
171 --* initialize layers hmap
172 local layers=mkheightmap(availlayers,x,z,minp,maxp)
173 if (minp.x>0)and(minp.x<200) then layers=nil end --< debug
174 if layers then for y=minp.y,maxp.y,1 do
176 --* select layer
177 local layer
178 for ln,ld in pairs(layers) do
179 if (ld)and
180 (ld.nh<y)and
181 ((not layer)or(ld.height>layer.height))
182 then
183 layer=ld
187 --* select vein
188 local vein=nil
189 if layer then
190 -- vein=todo... iterate vein's noises and select one above it's treshold
193 --* select rock
194 local rock=nil
195 if vein then
196 rock=nil -- todo... --> based on pseudorandom, no pattern, just random
197 elseif layer then
198 rock=layer.rock -- not in vein > select base rock
201 --* place rocks
202 if rock then
203 if not rock.ctx then
204 rock.ctx=minetest.get_content_id(rock.block)
206 local p_pos = area:index(x, y, z)
207 nodes[p_pos] = rock.ctx
210 end end
213 manipulator:set_data(nodes)
214 -- manipulator:calc_lighting()
215 -- manipulator:update_liquids()
216 manipulator:write_to_map()
217 print("[rocks] gen "..os.clock()-timebefore)
219 end)
222 --Bedrock
225 minetest.register_node( "rocks:pink_granite", {
226 description = "Pink Granite",
227 tiles = { "rocks_pgr.png" },
228 is_ground_content = true,
229 groups = {cracky=3, stone=1},
230 sounds = default.node_sound_stone_defaults(),
233 minetest.register_ore({
234 ore_type = "sheet",
235 ore = "rocks:pink_granite",
236 wherein = "do_not_generate",
237 clust_scarcity = 1,
238 clust_num_ores = 1,
239 clust_size = 60,
240 height_min = -31000,
241 height_max = -46,
242 noise_threshhold = 0.2,
243 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=31, octaves=11, persist=0.0000000001}
246 minetest.register_node( "rocks:black_granite", {
247 description = "Black Granite",
248 tiles = { "rocks_blkgr.png" },
249 is_ground_content = true,
250 groups = {cracky=3, stone=1},
251 sounds = default.node_sound_stone_defaults(),
254 minetest.register_ore({
255 ore_type = "sheet",
256 ore = "rocks:black_granite",
257 wherein = "do_not_generate",
258 clust_scarcity = 1,
259 clust_num_ores = 1,
260 clust_size = 60,
261 height_min = -31000,
262 height_max = -46,
263 noise_threshhold = 0.2,
264 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=32, octaves=11, persist=0.0000000001}
267 minetest.register_node( "rocks:white_granite", {
268 description = "White Granite",
269 tiles = { "rocks_wgr.png" },
270 is_ground_content = true,
271 groups = {cracky=3, stone=1},
272 sounds = default.node_sound_stone_defaults(),
275 minetest.register_ore({
276 ore_type = "sheet",
277 ore = "rocks:white_granite",
278 wherein = "do_not_generate",
279 clust_scarcity = 1,
280 clust_num_ores = 1,
281 clust_size = 60,
282 height_min = -31000,
283 height_max = -46,
284 noise_threshhold = 0.2,
285 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=33, octaves=11, persist=0.0000000001}
288 minetest.register_node( "rocks:brown_granite", {
289 description = "Brown Granite",
290 tiles = { "rocks_brgr.png" },
291 is_ground_content = true,
292 groups = {cracky=3, stone=1},
293 sounds = default.node_sound_stone_defaults(),
296 minetest.register_ore({
297 ore_type = "sheet",
298 ore = "rocks:brown_granite",
299 wherein = "do_not_generate",
300 clust_scarcity = 1,
301 clust_num_ores = 1,
302 clust_size = 60,
303 height_min = -31000,
304 height_max = -46,
305 noise_threshhold = 0.2,
306 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=34, octaves=11, persist=0.0000000001}
309 minetest.register_node( "rocks:red_sandstone", {
310 description = "Red Sandstone",
311 tiles = { "rocks_rss.png" },
312 is_ground_content = true,
313 groups = {cracky=3, stone=1},
314 sounds = default.node_sound_stone_defaults(),
317 minetest.register_ore({
318 ore_type = "sheet",
319 ore = "rocks:red_sandstone",
320 wherein = "do_not_generate",
321 clust_scarcity = 1,
322 clust_num_ores = 1,
323 clust_size = 60,
324 height_min = -31000,
325 height_max = -46,
326 noise_threshhold = 0.2,
327 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=35, octaves=11, persist=0.0000000001}
330 minetest.register_node( "rocks:yellow_sandstone", {
331 description = "Yellow Sandstone",
332 tiles = { "rocks_yss.png" },
333 is_ground_content = true,
334 groups = {cracky=3, stone=1},
335 sounds = default.node_sound_stone_defaults(),
338 minetest.register_ore({
339 ore_type = "sheet",
340 ore = "rocks:yellow_sandstone",
341 wherein = "do_not_generate",
342 clust_scarcity = 1,
343 clust_num_ores = 1,
344 clust_size = 60,
345 height_min = -31000,
346 height_max = -46,
347 noise_threshhold = 0.2,
348 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=36, octaves=11, persist=0.0000000001}
351 minetest.register_node( "rocks:white_marble", {
352 description = "White Marble",
353 tiles = { "rocks_wm.png" },
354 is_ground_content = true,
355 groups = {cracky=3, stone=1},
356 sounds = default.node_sound_stone_defaults(),
359 minetest.register_ore({
360 ore_type = "sheet",
361 ore = "rocks:white_marble",
362 wherein = "do_not_generate",
363 clust_scarcity = 1,
364 clust_num_ores = 1,
365 clust_size = 60,
366 height_min = -31000,
367 height_max = -46,
368 noise_threshhold = 0.2,
369 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=37, octaves=11, persist=0.0000000001}
372 minetest.register_node( "rocks:black_basalt", {
373 description = "Black Basalt",
374 tiles = { "rocks_bb.png" },
375 is_ground_content = true,
376 groups = {cracky=3, stone=1},
377 sounds = default.node_sound_stone_defaults(),
380 minetest.register_ore({
381 ore_type = "sheet",
382 ore = "rocks:black_basalt",
383 wherein = "do_not_generate",
384 clust_scarcity = 1,
385 clust_num_ores = 1,
386 clust_size = 60,
387 height_min = -31000,
388 height_max = -46,
389 noise_threshhold = 0.2,
390 noise_params = {offset=0, scale=80, spread={x=4350, y=4350, z=4350}, seed=38, octaves=11, persist=0.0000000001}
393 minetest.register_ore({
394 ore_type = "sheet",
395 ore = "default:clay",
396 wherein = "do_not_generate",
397 clust_scarcity = 1,
398 clust_num_ores = 1,
399 clust_size = 6,
400 height_min = -31000,
401 height_max = 15,
402 noise_threshhold = 0.5,
403 noise_params = {offset=0, scale=15, spread={x=25, y=20, z=30}, seed=15, octaves=3, persist=0.10}
406 print("[rocks] loaded.")