diff --git a/a.txt b/a.txt index 9f04512..0c66864 100644 --- a/a.txt +++ b/a.txt @@ -4,6 +4,8 @@ Geological layer generator for [Minetest] "rocks" Aim of this mod is to replace all generic stone (default:stone) and generate underground layers of different rocks. +Currently everithing generated above ground, in air. This is for debugging. + Features -------- @@ -20,4 +22,89 @@ Screenshots * Layers: ![sample of layers](layers0.png) * Coal pane: ![large coal deposit](coal-pane0.png) +* Vein: ![sample of generated vein](vein0.png) +Documentation +------------- + +How the underground is generated: *todo*. + +Underground is divided into horizontal layers. Bottom of each layer is at +fixed height and moved up or down by 2d perlin noise. + +In every layer there can be multiple veins. Veins are blob-shaped volumes +of different rocks. Borders of vein are defined by 3d perlin noise. Veins +often contain ores. + +In every vein, ores are distributed randomly. Some ores +may occur in specific areas of the vein (where noise is higher than +treshold) or distributed randomly in specific amount (chance based on +pseudorandom number) or combination of both. + +There is 1 2d perlin noise per layer, 1 3d perlin noise per vein and 1 +pseudorandom number generator per ore. + +Modding Interface +----------------- + +"Rocks" exposes api to add new ores, veins and layers. The api is defined +in [register](register.lua). + +### Register layer + + rocks.register_layer=function(name,params,rock) + + +This function registers a layer. Layer is identified by unique string name. +Location of layer is specified in params and node, the layer should be +composed of is defined by rock. + +Field "params.gain" sets how height of the layer should vary. Field +"params.height" sets height of bottom of the layer. Field "params.limit" is +value of noise above which the layer is not generated. Set to 2 to disable +this feature. Last field "params.seed" is offset to world seed to seed the +noise. + +### Register vein + + rocks.register_vein=function(name,params) + +This function registers a vein with name "name" to be generated according +to params. + +Field "params.spread" {x,y,z} defines how the vein should look like. X +shoudd be equal to z. If y=x=z then the vein is equal in all directions. To +make the vein taller, set y to higher value. Larger values make larger and +less frequent veins. + +Field "params.treshold" specifies rarity of the vein. It should be betveen +-2 and +2, mapgen will use this or per-ore treshold if per-ore treshold is +larger. + +- 2 never generate +- 1 extremly rare +- 0 50% chance +- less than 0 = SPAM + +Field "params.seed" is added to world seed to form seed for noise function. + +Depths, where the wein should generate can be controlled by fields hmin and +hmax. They can be set to nil to generate everywhere. + +Layers, where the vein should generate in must be listed in Field +"params.layer". + +## Register ore + + rocks.register_ore=function( vein, node, params ) + +This function registers ore or rock to be generated in vein "vein". Node to +be generated is "node". Params specify parameters, where the rock should +spawn. + +If noise is larger than Params.treshold, the ore is spawned (set to 2 to +spawn everywhere in the vein, 0.8=only in middle). Params.chance specify +the chance (/100%) of ore being spawned (0=never 1=always 0.5=50%). + +If multiple ores pass the treshhold and chance tests, ore with highest +treshold and smallest chance is spawned. diff --git a/geologica.lua b/geologica.lua new file mode 100644 index 0000000..d627623 --- /dev/null +++ b/geologica.lua @@ -0,0 +1,124 @@ +local CcHard=3 +local CcStrong=3 +local CcMed=3 +local CcSoft=3 + +-- +-- Main rocks (top to bottom) +-- + +-- Granite In/Felsic hard Very common, below sed on land +minetest.register_node( "rocks:granite", { + description = S("Granite"), + tiles = { "rocks_Granite.png" }, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), + groups = {cracky=CcStrong, stone=1}, +}) +rocks.register_layer( "granite",{ gain=20, height=-55, limit=2, seed=1 }, "rocks:granite") + +-- Diorite In/Inter vhard Below granite +minetest.register_node( "rocks:diorite", { + description = S("Diorite"), + tiles = { "rocks_Diorite.png" }, + groups = {cracky=CcHard, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "diorite",{ gain=20, height=-80, limit=2, seed=2 }, "rocks:diorite") + +-- Basalt Ex/Mafic hard same as diorite, byt limit=0.5 +minetest.register_node( "rocks:basalt", { + description = S("Basalt"), + tiles = { "rocks_Basalt.png" }, + groups = {cracky=CcStrong, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "basalt",{ gain=20, height=-75, limit=-0.7, seed=2 }, "rocks:basalt") + +-- Gabbro In/Mafic vhard Below basalt/diorite (mtns, ocean) +minetest.register_node( "rocks:gabbro", { + description = S("Gabbro"), + tiles = { "rocks_Gabbro.png" }, + groups = {cracky=CcHard, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "gabbro",{ gain=20, height=-120, limit=2, seed=3 }, "rocks:gabbro") + +-- Peridotite In/UMafic vhard Rarely under gabbro +minetest.register_node( "rocks:peridotite", { + description = S("Peridotite"), + tiles = { "rocks_Peridotite.png" }, + groups = {cracky=CcStrong, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "peridotite",{ gain=20, height=-130, limit=-0.8, seed=4 }, "rocks:peridotite") + +-- Komatiite Ex/UMafic - Too deep +minetest.register_node( "rocks:komatiite", { + description = S("Komatiite"), + tiles = { "default_stone.png" }, -- no texture, yet + groups = {cracky=CcHard, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "komatiite",{ gain=20, height=-200, limit=2, seed=5 }, "rocks:komatiite") + +-- +-- top sedimentary rocks +-- + +-- Mudstone Sed soft Ocean, beach, river, glaciers +minetest.register_node( "rocks:mudstone", { + description = S("Mudstone"), + tiles = { "rocks_Mudstone.png" }, + groups = {cracky=CcSoft, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "mudstone",{ gain=10, height=-13, limit=2, seed=4 }, "rocks:mudstone") + +-- Slate MM/barro med Under mud/clay/siltstone +minetest.register_node( "rocks:slate", { + description = S("slate"), + tiles = { "rocks_Slate.png" }, + groups = {cracky=CcMed, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "slate",{ gain=10, height=-15, limit=2, seed=5 }, "rocks:slate") + +-- Schist MM/barro med Under slate, sometimes igneous +minetest.register_node( "rocks:schist", { + description = S("schist"), + tiles = { "rocks_Schist.png" }, + groups = {cracky=CcMed, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "schist",{ gain=10, height=-18, limit=2, seed=5 }, "rocks:schist") + +-- Gneiss MM/barro hard Under schist, sometimes igneous +minetest.register_node( "rocks:gneiss", { + description = S("gneiss"), + tiles = { "rocks_Gneiss.png" }, + groups = {cracky=CcStrong, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "gneiss",{ gain=10, height=-21, limit=2, seed=6 }, "rocks:gneiss") + +-- +-- peak rocks +-- + +-- Rhyolite Ex/Felsic hard Mountains, top +minetest.register_node( "rocks:rhyolite", { + description = S("Rhyolite"), + tiles = { "rocks_Rhyolite.png" }, + groups = {cracky=CcHard, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "rhyolite",{ gain=8, height=22, limit=2, seed=4 }, "rocks:rhyolite") + +-- Andesite Ex/Inter hard Mountains, below rhyolite +minetest.register_node( "rocks:andesite", { + description = S("Andesite"), + tiles = { "rocks_Andesite.png" }, + groups = {cracky=CcHard, stone=1}, + is_ground_content = true, sounds = default.node_sound_stone_defaults(), +}) +rocks.register_layer( "andesite",{ gain=8, height=10, limit=2, seed=4 }, "rocks:andesite") diff --git a/geologica_nv.lua b/geologica_nv.lua new file mode 100644 index 0000000..6238147 --- /dev/null +++ b/geologica_nv.lua @@ -0,0 +1,37 @@ +local CcHard=3 +local CcStrong=3 +local CcMed=3 +local CcSoft=3 + +-- +-- nonvein vein +-- + +-- Claystone Sed soft in mudstone +rocks.register_vein("clay",{ + spread = {x=30, y=10, z=30}, + treshold=0.2, -- clay should be plenty + seed = 9, + hmin=-8, hmax=nil, + layers={ "mudstone" }, +}) +rocks.register_ore( "clay", "default:clay", {treshold=0, chance=85 } ) +rocks.register_ore( "clay", "default:torch", {treshold=0, chance=15 } ) + +-- Breccia Mixture soft in mudstone +-- Conglomerate Sed soft in mudstone +-- Skarn MM/contact med in mudstone in mountains +-- Hornfels MM/contact vhard in mudstone in mountains +-- Marble MM/contact hard in mudstone in mountains +-- Limestone Sed med in Rhyolite, Andesite in mountains +rocks.register_vein("limestone",{ + spread = {x=10, y=10, z=10}, + treshold=0.75, + seed = 10, + hmin=nil, hmax=nil, + layers={ "mudstone" }, +}) +-- Dolomite Sed med in Rhyolite, Andesite in mountains +-- Quartzite MM/contact vhard sandstone + + diff --git a/init.lua b/init.lua index 95aa15d..2e9477e 100644 --- a/init.lua +++ b/init.lua @@ -1,6 +1,5 @@ -- Load translation library if intllib is installed -local S if (minetest.get_modpath("intllib")) then dofile(minetest.get_modpath("intllib").."/intllib.lua") S = intllib.Getter(minetest.get_current_modname()) @@ -8,363 +7,32 @@ if (minetest.get_modpath("intllib")) then S = function ( s ) return s end end -rocks = {} +local modpath=minetest.get_modpath(minetest.get_current_modname()) -rocks.layers = {} -rocks.veins = {} -rocks.ores = {} +dofile(modpath.."/register.lua") rocks.noiseparams_layers = { offset = 0, scale = 1, - spread = {x=300, y=300, z=300}, - octaves = 3, - persist = 0.63 + spread = {x=80, y=80, z=80}, + octaves = 2, + persist = 0.7 } -rocks.register_layer=function(name,params,rock) - assert(name) - assert(params) - assert(params.gain) - assert(params.height) - local maxheight - for ln,ld in pairs(rocks.layers) do - if (ld.heightparams.height)) then ld.maxheight=params.height end - if (ld.height>params.height)and((not maxheight) or (maxheight>ld.height)) then maxheight=ld.height end - end - rocks.layers[name]= { - gain=params.gain, - height=params.height, - maxheight=maxheight, - limit=params.limit, - seed=params.seed, - rock={ block=rock }, - veins={} - } - print("[rocks] register layer "..name) -end +dofile(modpath.."/mapgen.lua") +--dofile(modpath.."/testing.lua") +dofile(modpath.."/geologica.lua") +dofile(modpath.."/geologica_nv.lua") -rocks.register_rock=function(layer,block,amount) - assert(layer) - assert(block) - assert(amount) - assert(rocks.layers[layer]) - table.insert(rocks.layers[layer].rocks, { block=block, amount=amount}) - rocks.layers[layer].sum=rocks.layers[layer].sum+amount - print("[rocks] register rock "..block.." in "..layer.." amount="..amount.." cur sum="..rocks.layers[layer].sum) -end +print("[rocks] sorting layers") --- --- test layer --- - -rocks.register_layer("test1",{ gain=40, height=70, limit=2, seed=1 },"rocks:black_granite") - --- uhlie ako vrstva je kokotina. - -rocks.register_layer("test3",{ gain=40, height=65, limit=2, seed=3 },"rocks:pink_granite") - -rocks.register_layer("test4",{ gain=40, height=90, limit=2, seed=4 },"rocks:white_granite") - - -for ln,ld in pairs(rocks.layers) do - print("[rocks] debug: "..ln..": "..minetest.serialize(ld)) -end - --- --- layer generator --- - -local function mknoises(layers,minp,maxp) - local nm={} - for ln,ld in pairs(rocks.layers) do - if (ld.height-ld.gainminp.y)) then - local np=rocks.noiseparams_layers - np.seed=ld.seed - local side_length = maxp.x - minp.x + 1 - ld.nmap=minetest.get_perlin_map(np,{x=side_length, y=side_length, z=side_length}):get2dMap({x=minp.x, y=minp.z}) - table.insert(nm,ld) - end - end - return nm -end - -local function mkheightmap(layers,x,z,minp,maxp) - local hm={} - for ln,ld in pairs(layers) do - local noise=ld.nmap[z-minp.z+1][x-minp.x+1] - if math.abs(noise)miny) - table.insert(hm,ld) - end - end - return hm -end - -local stonectx=nil - -minetest.register_on_generated(function(minp, maxp, seed) - if not stonectx then stonectx= minetest.get_content_id("default:stone") end - -- noise values range (-1;+1) (1 octave) - -- 3 octaves it is like 1.7 max - -- 4 octaves with 0.8 presist = 2.125 max !! - -- if ... - local timebefore=os.clock(); - local manipulator, emin, emax = minetest.get_mapgen_object("voxelmanip") - local nodes = manipulator:get_data() - local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} - -- initialize noises and sort out unused layers - local availlayers=mknoises(rocks.layers,minp,maxp) - -- - for x=minp.x,maxp.x,1 do - for z=minp.z,maxp.z,1 do - --* initialize layers hmap - local layers=mkheightmap(availlayers,x,z,minp,maxp) - if (minp.x>0)and(minp.x<200) then layers=nil end --< debug - if layers then for y=minp.y,maxp.y,1 do - - --* select layer - local layer - for ln,ld in pairs(layers) do - if (ld)and - (ld.nhlayer.height)) - then - layer=ld - end - end - - --* select vein - local vein=nil - if layer then - -- vein=todo... iterate vein's noises and select one above it's treshold - end - - --* select rock - local rock=nil - if vein then - rock=nil -- todo... --> based on pseudorandom, no pattern, just random - elseif layer then - rock=layer.rock -- not in vein > select base rock - end - - --* place rocks - if rock then - if not rock.ctx then - rock.ctx=minetest.get_content_id(rock.block) - end - local p_pos = area:index(x, y, z) - nodes[p_pos] = rock.ctx - end - - end end - end - end - manipulator:set_data(nodes) - -- manipulator:calc_lighting() - -- manipulator:update_liquids() - manipulator:write_to_map() - print("[rocks] gen "..os.clock()-timebefore) - +for i,d in pairs(rocks.layers_name) do table.insert(rocks.layers,d) end +table.sort(rocks.layers,function(a,b) + return a.height=minp.y then -- ak je to mimo zdola tak ju vyhodime + -- urobime sum pre vrstvu + local np=rocks.noiseparams_layers + np.seed=d.seed + np.scale=d.gain + np.offset=d.height + d.nmap=minetest.get_perlin_map(np,map_lengths_xyz):get2dMap_flat({x=minp.x, y=minp.z}) + -- contene_id kamenov + d.rock.ctx=d.rock.ctx or minetest.get_content_id(d.rock.node) + -- veiny + local veinstodo={} + for veinname,vd in pairs(d.veins) do + -- todo: do not generate noise for blocks outside the layer + veinstodo[veinname]=vd + end + for veinname,vd in pairs(veinstodo) do + -- noise pre vein + np=vd.np + vd.nmap=minetest.get_perlin_map(np,map_lengths_xyz):get3dMap_flat(minp) + vd.prng=PseudoRandom(np.seed) + vd.sum=0 + for i,ore in pairs(vd.ores) do + -- contntid pre rudu + ore.ctx=ore.ctx or minetest.get_content_id(ore.node) + -- sum sanci pre vein + vd.sum=vd.sum+ore.chance + end + end + table.insert(avl,d) -- pridame vrstvu + if (d.height-d.gain)>maxp.y then break end -- ak je mimo zhora tak uz dalsie nehladaj + else + --print(" no higher "..d.height.." than "..minp.y) + end + end + + -- + print("[rocks] gen2 "..os.clock()-timebefore.." #layers="..#avl.." minp.y="..minp.y.." maxp.y"..maxp.y) + for lh,ld in ipairs(avl) do + print(" "..lh.."->"..ld.name.." top="..ld.height) + for vn,vd in pairs(ld.veins) do + print(" "..vn.."->"..#vd.ores) + end + end + + local noise2d_ix = 1 + local noise3d_ix = 1 + + for z=minp.z,maxp.z,1 do + for y=minp.y,maxp.y,1 do + for x=minp.x,maxp.x,1 do + local p_pos = area:index(x, y, z) + local layer,vein + local rock + + --* select layer + for lh,ld in ipairs(avl) do + if (yvd.treshold then + vein=vd + --rock not changed + end + end + end + + if vein then + --* select ore + local chance=vein.prng:next(0,vein.sum) + for i,ore in pairs(vein.ores) do + chance=chance-ore.chance + if chance<=0 then + rock=ore + break + end + end + end + + --* place rocks + if (rock) and(nodes[p_pos]==stone_ctx) then + nodes[p_pos] = rock.ctx + end + + noise3d_ix =noise3d_ix+1 + noise2d_ix = noise2d_ix+1 + end + noise2d_ix = noise2d_ix-side_length + end + end + manipulator:set_data(nodes) + --manipulator:calc_lighting() + --manipulator:set_lighting({day=15,night=15}) + --manipulator:update_liquids() + manipulator:write_to_map() + print("[rocks] gen0 "..os.clock()-timebefore) +end) + diff --git a/register.lua b/register.lua new file mode 100644 index 0000000..b6b5860 --- /dev/null +++ b/register.lua @@ -0,0 +1,61 @@ +-- global table and register_* functions + +rocks = {} + +rocks.layers = {} +rocks.layers_name = {} +rocks.veins = {} +rocks.ores = {} + +rocks.register_layer=function(name,params,rock) + assert(name) + assert(params) + assert(rock) + assert(params.gain) + assert(params.height) + local maxheight + + local ld= { + gain=params.gain, + height=params.height, + maxheight=maxheight, + limit=((params.limit or 2)*params.gain)+params.height, + seed=params.seed or 0, + rock={ node=rock }, + veins={}, + name=name + } + rocks.layers_name[name]= ld + print("[rocks] layer "..ld.name) +end + +rocks.register_vein=function(name,params) + assert(name) + assert(params) + assert(not rocks.veins[name]) + rocks.veins[name]={ + np={ + offset=0, scale=1, octaves=1, presist=0.8, + spread={x=params.spread.x, y=params.spread.y, z=params.spread.z}, + -- swapped, becouse we generate by horizontal layers + seed=params.seed + }, + treshold=params.treshold, + hmin=params.hmin, hmax=params.hmax, + layers=params.layers, + ores={} + } + for i,layername in pairs(params.layers) do + rocks.layers_name[layername].veins[name]=rocks.veins[name] + end + print("[rocks] vein "..name) +end + +rocks.register_ore=function( vein, node, params ) + -- params= {treshold=0, chance=1 } + ore={ node=node } + ore.treshold=(params.treshold or rocks.veins[vein].treshold) + ore.chance= (params.chance or 1) + table.insert(rocks.veins[vein].ores, ore) + print("[rocks] ore "..node.." in "..vein.." chance="..ore.chance.." treshold="..ore.treshold) +end diff --git a/textures/decoblocks.txt b/textures/decoblocks.txt new file mode 100644 index 0000000..d2cb401 --- /dev/null +++ b/textures/decoblocks.txt @@ -0,0 +1,17 @@ +Theese files were copied from minetest decoblocks mod. Original files were +in "default/textures" and with "default_" prefix instead of "rocks_". + +rocks_bb.png +rocks_blkgr.png +rocks_brgr.png +rocks_gls.png +rocks_mrbrownstone.png +rocks_obs.png +rocks_pgr.png +rocks_rss.png +rocks_serp.png +rocks_sod.png +rocks_trav.png +rocks_wgr.png +rocks_wm.png +rocks_yss.png diff --git a/textures/geologica.txt b/textures/geologica.txt new file mode 100644 index 0000000..dfb4d28 --- /dev/null +++ b/textures/geologica.txt @@ -0,0 +1,13 @@ +Theese files were copied from minecraft PFAA Geologica mod. + +rocks_Andesite.png +rocks_Basalt.png +rocks_Diorite.png +rocks_Gabbro.png +rocks_Gneiss.png +rocks_Granite.png +rocks_Mudstone.png +rocks_Peridotite.png +rocks_Rhyolite.png +rocks_Schist.png +rocks_Slate.png diff --git a/textures/rocks_Andesite.png b/textures/rocks_Andesite.png new file mode 100644 index 0000000..5e3015b Binary files /dev/null and b/textures/rocks_Andesite.png differ diff --git a/textures/rocks_Basalt.png b/textures/rocks_Basalt.png new file mode 100644 index 0000000..a76f512 Binary files /dev/null and b/textures/rocks_Basalt.png differ diff --git a/textures/rocks_Diorite.png b/textures/rocks_Diorite.png new file mode 100644 index 0000000..b39a45a Binary files /dev/null and b/textures/rocks_Diorite.png differ diff --git a/textures/rocks_Gabbro.png b/textures/rocks_Gabbro.png new file mode 100644 index 0000000..e615c3a Binary files /dev/null and b/textures/rocks_Gabbro.png differ diff --git a/textures/rocks_Gneiss.png b/textures/rocks_Gneiss.png new file mode 100644 index 0000000..b7ce641 Binary files /dev/null and b/textures/rocks_Gneiss.png differ diff --git a/textures/rocks_Granite.png b/textures/rocks_Granite.png new file mode 100644 index 0000000..eae5d37 Binary files /dev/null and b/textures/rocks_Granite.png differ diff --git a/textures/rocks_Mudstone.png b/textures/rocks_Mudstone.png new file mode 100644 index 0000000..2528b84 Binary files /dev/null and b/textures/rocks_Mudstone.png differ diff --git a/textures/rocks_Peridotite.png b/textures/rocks_Peridotite.png new file mode 100644 index 0000000..a0d0ad0 Binary files /dev/null and b/textures/rocks_Peridotite.png differ diff --git a/textures/rocks_Rhyolite.png b/textures/rocks_Rhyolite.png new file mode 100644 index 0000000..b3b3dc4 Binary files /dev/null and b/textures/rocks_Rhyolite.png differ diff --git a/textures/rocks_Schist.png b/textures/rocks_Schist.png new file mode 100644 index 0000000..6b33b72 Binary files /dev/null and b/textures/rocks_Schist.png differ diff --git a/textures/rocks_Slate.png b/textures/rocks_Slate.png new file mode 100644 index 0000000..7baea1d Binary files /dev/null and b/textures/rocks_Slate.png differ diff --git a/vein0.png b/vein0.png new file mode 100644 index 0000000..fe61ff0 Binary files /dev/null and b/vein0.png differ