diff --git a/nether/common.lua b/nether/common.lua new file mode 100644 index 0000000..0ec5eb3 --- /dev/null +++ b/nether/common.lua @@ -0,0 +1,153 @@ + +dofile(nether.path .. "/settings.lua") + +-- vars +nether.v = {} +local v = nether.v + +--== EDITABLE OPTIONS ==-- + +-- Depth of the nether +v.nether_middle = -20000 + +-- forest bottom perlin multiplication +v.f_bottom_scale = 4 + +-- forest bottom height +v.f_h_min = v.nether_middle+10 + +-- forest top height +v.f_h_max = v.f_h_min+250 + +-- Frequency of trees in the nether forest (higher is less frequent) +v.tree_rarity = 200 + +-- Frequency of glowflowers in the nether forest (higher is less frequent) +v.glowflower_rarity = 120 + +-- Frequency of nether grass in the nether forest (higher is less frequent) +v.grass_rarity = 2 + +-- Frequency of nether mushrooms in the nether forest (higher is less frequent) +v.mushroom_rarity = 80 + +v.abm_tree_interval = 864 +v.abm_tree_chance = 100 + +-- height of the nether generation's end +v.nether_start = v.f_h_max+100 + +-- Height of the nether (bottom of the nether is nether_middle - NETHER_HEIGHT) +v.NETHER_HEIGHT = 30 + +-- bottom height of the nether. +v.nether_bottom = v.nether_middle - v.NETHER_HEIGHT - 100 + +-- Maximum amount of randomness in the map generation +v.NETHER_RANDOM = 2 + +-- Frequency of Glowstone on the "roof" of the Nether (higher is less frequent) +v.GLOWSTONE_FREQ_ROOF = 500 + +-- Frequency of lava (higher is less frequent) +v.LAVA_FREQ = 100 + +v.nether_structure_freq = 350 +v.NETHER_SHROOM_FREQ = 100 + +-- Maximum height of lava +--v.LAVA_HEIGHT = 2 +-- Frequency of Glowstone on lava (higher is less frequent) +--v.GLOWSTONE_FREQ_LAVA = 2 +-- Height of nether structures +--v.NETHER_TREESIZE = 2 +-- Frequency of apples in a nether structure (higher is less frequent) +--v.NETHER_APPLE_FREQ = 5 +-- Frequency of healing apples in a nether structure (higher is less frequent) +--v.NETHER_HEAL_APPLE_FREQ = 10 +-- Start position for the Throne of Hades (y is relative to the bottom of the +-- nether) +--v.HADES_THRONE_STARTPOS = {x=0, y=1, z=0} +-- Spawn pos for when the nether hasn't been loaded yet (i.e. no portal in the +-- nether) (y is relative to the bottom of the nether) +--v.NETHER_SPAWNPOS = {x=0, y=5, z=0} +-- Structure of the nether portal (all is relative to the nether portal creator +-- block) + +--== END OF EDITABLE OPTIONS ==-- + +-- Generated variables +v.NETHER_BOTTOM = (v.nether_middle - v.NETHER_HEIGHT) +v.nether_buildings = v.NETHER_BOTTOM+12 + +function nether.query_contents() + local c = { + ignore = minetest.get_content_id("ignore"), + air = minetest.get_content_id("air"), + lava = minetest.get_content_id("default:lava_source"), + gravel = minetest.get_content_id("default:gravel"), + coal = minetest.get_content_id("default:stone_with_coal"), + diamond = minetest.get_content_id("default:stone_with_diamond"), + mese = minetest.get_content_id("default:mese"), + + --https://github.com/Zeg9/minetest-glow + glowstone = minetest.get_content_id("glow:stone"), + + nether_shroom = minetest.get_content_id("riesenpilz:nether_shroom"), + + netherrack = minetest.get_content_id("nether:netherrack"), + netherrack_tiled = minetest.get_content_id("nether:netherrack_tiled"), + netherrack_black = minetest.get_content_id("nether:netherrack_black"), + netherrack_blue = minetest.get_content_id("nether:netherrack_blue"), + netherrack_brick = minetest.get_content_id("nether:netherrack_brick"), + white = minetest.get_content_id("nether:white"), + + nether_vine = minetest.get_content_id("nether:vine"), + blood = minetest.get_content_id("nether:blood"), + blood_top = minetest.get_content_id("nether:blood_top"), + blood_stem = minetest.get_content_id("nether:blood_stem"), + nether_apple = minetest.get_content_id("nether:apple"), + + nether_tree = minetest.get_content_id("nether:tree"), + nether_tree_corner = minetest.get_content_id("nether:tree_corner"), + nether_leaves = minetest.get_content_id("nether:leaves"), + nether_grass = { + minetest.get_content_id("nether:grass_small"), + minetest.get_content_id("nether:grass_middle"), + minetest.get_content_id("nether:grass_big") + }, + glowflower = minetest.get_content_id("nether:glowflower"), + nether_dirt = minetest.get_content_id("nether:dirt"), + nether_dirt_top = minetest.get_content_id("nether:dirt_top"), + nether_dirt_bottom = minetest.get_content_id("nether:dirt_bottom"), + } + local trn = {c.nether_tree, c.nether_tree_corner, c.nether_leaves, + c.nether_fruit} + local nether_tree_nodes = {} + for i = 1,#trn do + nether_tree_nodes[trn[i]] = true + end + + return c, nether_tree_nodes +end + +if nether.log_level >= 1 then + function nether:inform(msg, spam, t) + if spam <= self.log_level then + local info + if t then + info = "[nether] " .. msg .. (" after ca. %.3g s"):format( + (minetest.get_us_time() - t) / 1000000) + else + info = "[nether] " .. msg + end + print(info) + if self.log_to_chat then + minetest.chat_send_all(info) + end + end + end +else + function nether.inform() + end +end diff --git a/nether/guide.lua b/nether/guide.lua index 8183ba2..c550588 100644 --- a/nether/guide.lua +++ b/nether/guide.lua @@ -263,7 +263,7 @@ minetest.register_chatcommand("nether_help", { if not player then return false, "Something went wrong." end - if not nether.overworld_help and player:get_pos().y > nether.start then + if not nether.overworld_help and player:get_pos().y > nether.v.nether_start then return false, "Usually you don't neet this guide here. " .. "You can view it in the nether." end diff --git a/nether/init.lua b/nether/init.lua index 0e78bb1..c02f39a 100644 --- a/nether/init.lua +++ b/nether/init.lua @@ -17,145 +17,16 @@ if not rawget(_G, "nether") then nether = {} end ---== EDITABLE OPTIONS ==-- +nether.path = minetest.get_modpath"nether" +local path = nether.path --- Depth of the nether -local nether_middle = -20000 +dofile(path .. "/common.lua") --- forest bottom perlin multiplication -local f_bottom_scale = 4 - --- forest bottom height -local f_h_min = nether_middle+10 - --- forest top height -local f_h_max = f_h_min+250 - --- Frequency of trees in the nether forest (higher is less frequent) -local tree_rarity = 200 - --- Frequency of glowflowers in the nether forest (higher is less frequent) -local glowflower_rarity = 120 - --- Frequency of nether grass in the nether forest (higher is less frequent) -local grass_rarity = 2 - --- Frequency of nether mushrooms in the nether forest (higher is less frequent) -local mushroom_rarity = 80 - -local abm_tree_interval = 864 -local abm_tree_chance = 100 - --- height of the nether generation's end -nether.start = f_h_max+100 - --- Height of the nether (bottom of the nether is nether_middle - NETHER_HEIGHT) -local NETHER_HEIGHT = 30 - --- bottom height of the nether. -nether.bottom = nether_middle - NETHER_HEIGHT - 100 - --- Maximum amount of randomness in the map generation -local NETHER_RANDOM = 2 - --- Frequency of Glowstone on the "roof" of the Nether (higher is less frequent) -local GLOWSTONE_FREQ_ROOF = 500 - --- Frequency of lava (higher is less frequent) -local LAVA_FREQ = 100 - -local nether_structure_freq = 350 -local NETHER_SHROOM_FREQ = 100 - --- Maximum height of lava ---LAVA_HEIGHT = 2 --- Frequency of Glowstone on lava (higher is less frequent) ---GLOWSTONE_FREQ_LAVA = 2 --- Height of nether structures ---NETHER_TREESIZE = 2 --- Frequency of apples in a nether structure (higher is less frequent) ---NETHER_APPLE_FREQ = 5 --- Frequency of healing apples in a nether structure (higher is less frequent) ---NETHER_HEAL_APPLE_FREQ = 10 --- Start position for the Throne of Hades (y is relative to the bottom of the --- nether) ---HADES_THRONE_STARTPOS = {x=0, y=1, z=0} --- Spawn pos for when the nether hasn't been loaded yet (i.e. no portal in the --- nether) (y is relative to the bottom of the nether) ---NETHER_SPAWNPOS = {x=0, y=5, z=0} --- Structure of the nether portal (all is relative to the nether portal creator --- block) - ---== END OF EDITABLE OPTIONS ==-- - -local path = minetest.get_modpath"nether" -dofile(path .. "/settings.lua") -local nether_weird_noise = dofile(path .. "/weird_mapgen_noise.lua") dofile(path .. "/items.lua") --dofile(path .. "/furnace.lua") dofile(path .. "/pearl.lua") -if nether.log_level >= 1 then - function nether:inform(msg, spam, t) - if spam <= self.log_level then - local info - if t then - info = "[nether] " .. msg .. (" after ca. %.3g s"):format( - (minetest.get_us_time() - t) / 1000000) - else - info = "[nether] " .. msg - end - print(info) - if self.log_to_chat then - minetest.chat_send_all(info) - end - end - end -else - function nether.inform() - end -end - - --- Weierstrass function stuff from https://github.com/slemonide/gen -local SIZE = 1000 -local ssize = math.ceil(math.abs(SIZE)) -local function do_ws_func(depth, a, x) - local n = math.pi * x / (16 * SIZE) - local y = 0 - for k=1,depth do - y = y + math.sin(k^a * n) / k^a - end - return SIZE * y / math.pi -end - -local chunksize = minetest.settings:get"chunksize" or 5 -local ws_lists = {} -local function get_ws_list(a,x) - ws_lists[a] = ws_lists[a] or {} - local v = ws_lists[a][x] - if v then - return v - end - v = {} - for x=x,x + (chunksize*16 - 1) do - local y = do_ws_func(ssize, a, x) - v[x] = y - end - ws_lists[a][x] = v - return v -end - - -local function dif(z1, z2) - return math.abs(z1-z2) -end - -local function pymg(x1, x2, z1, z2) - return math.max(dif(x1, x2), dif(z1, z2)) -end - local function r_area(manip, width, height, pos) local emerged_pos1, emerged_pos2 = manip:read_from_map( {x=pos.x-width, y=pos.y, z=pos.z-width}, @@ -171,477 +42,20 @@ local function set_vm_data(manip, nodes, pos, t1, name, generated) generated and 3 or 2, t1) end --- Generated variables -local NETHER_BOTTOM = (nether_middle - NETHER_HEIGHT) -nether.buildings = NETHER_BOTTOM+12 ---~ local NETHER_ROOF_ABS = (nether_middle - NETHER_RANDOM) -local f_yscale_top = (f_h_max-f_h_min)/2 -local f_yscale_bottom = f_yscale_top/2 ---HADES_THRONE_STARTPOS_ABS = {x=HADES_THRONE_STARTPOS.x, y=(NETHER_BOTTOM + ---HADES_THRONE_STARTPOS.y), z=HADES_THRONE_STARTPOS.z} ---LAVA_Y = (NETHER_BOTTOM + LAVA_HEIGHT) ---HADES_THRONE_ABS = {} ---HADES_THRONE_ENDPOS_ABS = {} ---HADES_THRONE_GENERATED = minetest.get_worldpath() .. "/netherhadesthrone.txt" ---NETHER_SPAWNPOS_ABS = {x=NETHER_SPAWNPOS.x, y=(NETHER_BOTTOM + ---NETHER_SPAWNPOS.y), z=NETHER_SPAWNPOS.z} ---[[for i,v in ipairs(HADES_THRONE) do - v.pos.x = v.pos.x + HADES_THRONE_STARTPOS_ABS.x - v.pos.y = v.pos.y + HADES_THRONE_STARTPOS_ABS.y - v.pos.z = v.pos.z + HADES_THRONE_STARTPOS_ABS.z - HADES_THRONE_ABS[i] = v -end -local htx = 0 -local hty = 0 -local htz = 0 -for i,v in ipairs(HADES_THRONE_ABS) do - if v.pos.x > htx then - htx = v.pos.x - end - if v.pos.y > hty then - hty = v.pos.y - end - if v.pos.z > htz then - htz = v.pos.z - end -end -HADES_THRONE_ENDPOS_ABS = {x=htx, y=hty, z=htz}]] - -local c, nether_tree_nodes +local c, contents_defined local function define_contents() - c = { - ignore = minetest.get_content_id("ignore"), - air = minetest.get_content_id("air"), - lava = minetest.get_content_id("default:lava_source"), - gravel = minetest.get_content_id("default:gravel"), - coal = minetest.get_content_id("default:stone_with_coal"), - diamond = minetest.get_content_id("default:stone_with_diamond"), - mese = minetest.get_content_id("default:mese"), - - --https://github.com/Zeg9/minetest-glow - glowstone = minetest.get_content_id("glow:stone"), - - nether_shroom = minetest.get_content_id("riesenpilz:nether_shroom"), - - netherrack = minetest.get_content_id("nether:netherrack"), - netherrack_tiled = minetest.get_content_id("nether:netherrack_tiled"), - netherrack_black = minetest.get_content_id("nether:netherrack_black"), - netherrack_blue = minetest.get_content_id("nether:netherrack_blue"), - netherrack_brick = minetest.get_content_id("nether:netherrack_brick"), - white = minetest.get_content_id("nether:white"), - - nether_vine = minetest.get_content_id("nether:vine"), - blood = minetest.get_content_id("nether:blood"), - blood_top = minetest.get_content_id("nether:blood_top"), - blood_stem = minetest.get_content_id("nether:blood_stem"), - nether_apple = minetest.get_content_id("nether:apple"), - - nether_tree = minetest.get_content_id("nether:tree"), - nether_tree_corner = minetest.get_content_id("nether:tree_corner"), - nether_leaves = minetest.get_content_id("nether:leaves"), - nether_grass = { - minetest.get_content_id("nether:grass_small"), - minetest.get_content_id("nether:grass_middle"), - minetest.get_content_id("nether:grass_big") - }, - glowflower = minetest.get_content_id("nether:glowflower"), - nether_dirt = minetest.get_content_id("nether:dirt"), - nether_dirt_top = minetest.get_content_id("nether:dirt_top"), - nether_dirt_bottom = minetest.get_content_id("nether:dirt_bottom"), - } - local trn = {c.nether_tree, c.nether_tree_corner, c.nether_leaves, - c.nether_fruit} - nether_tree_nodes = {} - for i = 1,#trn do - nether_tree_nodes[trn[i]] = true - end -end - -local pr, contents_defined - -local function return_nether_ore(id, glowstone) - if glowstone - and pr:next(0,GLOWSTONE_FREQ_ROOF) == 1 then - return c.glowstone - end - if id == c.coal then - return c.netherrack_tiled - end - if id == c.gravel then - return c.netherrack_black - end - if id == c.diamond then - return c.netherrack_blue - end - if id == c.mese then - return c.white - end - return c.netherrack -end - -local f_perlins = {} - --- abs(v) < 1-(persistance^octaves))/(1-persistance) = amp ---local perlin1 = minetest.get_perlin(13,3, 0.5, 50) --Get map specific perlin --- local perlin2 = minetest.get_perlin(133,3, 0.5, 10) --- local perlin3 = minetest.get_perlin(112,3, 0.5, 5) -local tmp = f_yscale_top*4 -local tmp2 = tmp/f_bottom_scale -local perlins = { - { -- amp 1.75 - seed = 13, - octaves = 3, - persist = 0.5, - spread = {x=50, y=50, z=50}, - scale = 1, - offset = 0, - }, - {-- amp 1.75 - seed = 133, - octaves = 3, - persist = 0.5, - spread = {x=10, y=10, z=10}, - scale = 1, - offset = 0, - }, - {-- amp 1.75 - seed = 112, - octaves = 3, - persist = 0.5, - spread = {x=5, y=5, z=5}, - scale = 1, - offset = 0, - }, - --[[forest_bottom = { - seed = 11, - octaves = 3, - persist = 0.8, - spread = {x=tmp2, y=tmp2, z=tmp2}, - scale = 1, - offset = 0, - },]] - forest_top = {-- amp 2.44 - seed = 21, - octaves = 3, - persist = 0.8, - spread = {x=tmp, y=tmp, z=tmp}, - scale = 1, - offset = 0, - }, -} - --- buffers, see https://forum.minetest.net/viewtopic.php?f=18&t=16043 -local pelin_maps -local pmap1 = {} -local pmap2 = {} -local pmap3 = {} -local pmap_f_top = {} -local data = {} - -local structures_enabled = true -local vine_maxlength = math.floor(NETHER_HEIGHT/4+0.5) --- Create the Nether -minetest.register_on_generated(function(minp, maxp, seed) - --avoid big map generation - if not (maxp.y >= NETHER_BOTTOM-100 and minp.y <= nether.start) then - return - end - - local t1 = minetest.get_us_time() - nether:inform("generates at: x=["..minp.x.."; "..maxp.x.."]; y=[" .. - minp.y.."; "..maxp.y.."]; z=["..minp.z.."; "..maxp.z.."]", 2) - if not contents_defined then - define_contents() + c = nether.query_contents() contents_defined = true end +end - local buildings = 0 - if maxp.y <= NETHER_BOTTOM then - buildings = 1 - elseif minp.y <= nether.buildings then - buildings = 2 - end - - local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") - vm:get_data(data) - local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} - - pr = PseudoRandom(seed+33) - local tab,num = {},1 - local trees,num_trees = {},1 - - --local perlin1 = minetest.get_perlin(13,3, 0.5, 50) - --local perlin2 = minetest.get_perlin(133,3, 0.5, 10) - --local perlin3 = minetest.get_perlin(112,3, 0.5, 5) - - local side_length = maxp.x - minp.x + 1 - local map_lengths_xyz = {x=side_length, y=side_length, z=side_length} - - if not pelin_maps then - pelin_maps = { - a = minetest.get_perlin_map(perlins[1], map_lengths_xyz), - b = minetest.get_perlin_map(perlins[2], map_lengths_xyz), - c = minetest.get_perlin_map(perlins[3], map_lengths_xyz), - forest_top = minetest.get_perlin_map(perlins.forest_top, - map_lengths_xyz), - } - end - pelin_maps.a:get_2d_map_flat({x=minp.x, y=minp.z}, pmap1) - pelin_maps.b:get_2d_map_flat({x=minp.x, y=minp.z}, pmap2) - pelin_maps.c:get_2d_map_flat({x=minp.x, y=minp.z}, pmap3) - - local forest_possible = maxp.y > f_h_min and minp.y < f_h_max - - --local pmap_f_bottom = minetest.get_perlin_map(perlins.forest_bottom, - -- map_lengths_xyz):get_2d_map_flat({x=minp.x, y=minp.z}) - local perlin_f_bottom, strassx, strassz - if forest_possible then - perlin_f_bottom = minetest.get_perlin(11, 3, 0.8, tmp2) - pelin_maps.forest_top:get_2d_map_flat({x=minp.x, y=minp.z}, pmap_f_top) - strassx = get_ws_list(2, minp.x) - strassz = get_ws_list(2, minp.z) - end - - local num2, tab2 - if buildings >= 1 then - num2 = 1 - tab2 = nether_weird_noise({x=minp.x, y=nether.buildings-79, z=minp.z}, - pymg, 200, 8, 10, side_length-1) - end - - local count = 0 - for z=minp.z, maxp.z do - for x=minp.x, maxp.x do - - count = count+1 - - local test = pmap1[count]+1 - local test2 = pmap2[count] - local test3 = math.abs(pmap3[count]) - - local t = math.floor(test*3+0.5) - - local h - if test2 < 0 then - h = math.floor(test2*3+0.5)-1 - else - h = 3+t+pr:next(0,NETHER_RANDOM) - end - - local generate_vine = false - if test3 >= 0.72+pr:next(0,NETHER_RANDOM)/10 - and pr:next(0,NETHER_RANDOM) == 1 then - generate_vine = true - end - - local bottom = NETHER_BOTTOM+h - local top = nether_middle-pr:next(0,NETHER_RANDOM)+t - - local py_h = 0 - local difn, noisp, py_h_g - if buildings >= 1 then - py_h = tab2[num2].y - num2 = num2+1 - - difn = nether.buildings-py_h - if difn == 5 then - noisp = 1 - elseif difn < 5 then - noisp = 2 - end - py_h_g = nether.buildings-7 - end - - local vi = area:index(x, minp.y, z) - if buildings == 1 - and noisp then - if noisp == 1 then - for _ = 1,side_length do - data[vi] = c.netherrack_brick - vi = vi + area.ystride - end - else - for _ = 1,side_length do - data[vi] = c.lava - vi = vi + area.ystride - end - end - else - - local r_structure = pr:next(1,nether_structure_freq) - local r_shroom = pr:next(1,NETHER_SHROOM_FREQ) - local r_glowstone = pr:next(0,GLOWSTONE_FREQ_ROOF) - local r_vine_length = pr:next(1,vine_maxlength) - - local f_bottom, f_top, is_forest, f_h_dirt - if forest_possible then - local p = {x=math.floor(x/f_bottom_scale), - z=math.floor(z/f_bottom_scale)} - local pstr = p.x.." "..p.z - if not f_perlins[pstr] then - f_perlins[pstr] = math.floor(f_h_min + (math.abs( - perlin_f_bottom:get_2d{x=p.x, y=p.z} + 1)) - * f_yscale_bottom + 0.5) - end - local top_noise = pmap_f_top[count]+1 - if top_noise < 0 then - top_noise = -top_noise/10 - --nether:inform("ERROR: (perlin noise) ".. - -- pmap_f_top[count].." is not inside [-1; 1]", 1) - end - f_top = math.floor(f_h_max - top_noise*f_yscale_top + 0.5) - f_bottom = f_perlins[pstr]+pr:next(0,f_bottom_scale-1) - is_forest = f_bottom < f_top - f_h_dirt = f_bottom-pr:next(0,1) - end - - for y=minp.y, maxp.y do - local d_p_addp = data[vi] - --if py_h >= maxp.y-4 then - if y <= py_h - and noisp then - if noisp == 1 then - data[vi] = c.netherrack_brick - elseif noisp == 2 then - if y == py_h then - data[vi] = c.netherrack_brick - elseif y == py_h_g - and pr:next(1,3) <= 2 then - data[vi] = c.netherrack - elseif y <= py_h_g then - data[vi] = c.lava - else - data[vi] = c.air - end - end - elseif d_p_addp ~= c.air then - - if is_forest - and y == f_bottom then - data[vi] = c.nether_dirt_top - elseif is_forest - and y < f_bottom - and y >= f_h_dirt then - data[vi] = c.nether_dirt - elseif is_forest - and y == f_h_dirt-1 then - data[vi] = c.nether_dirt_bottom - elseif is_forest - and y == f_h_dirt+1 then - if pr:next(1,tree_rarity) == 1 then - trees[num_trees] = {x=x, y=y, z=z} - num_trees = num_trees+1 - elseif pr:next(1,mushroom_rarity) == 1 then - data[vi] = c.nether_shroom - elseif pr:next(1,glowflower_rarity) == 1 then - data[vi] = c.glowflower - elseif pr:next(1,grass_rarity) == 1 then - data[vi] = c.nether_grass[pr:next(1,3)] - else - data[vi] = c.air - end - elseif is_forest - and y > f_bottom - and y < f_top then - if not nether_tree_nodes[d_p_addp] then - data[vi] = c.air - end - elseif is_forest - and y == f_top then - local sel = math.floor(strassx[x]+strassz[z]+0.5)%10 - if sel <= 5 then - data[vi] = return_nether_ore(d_p_addp, true) - elseif sel == 6 then - data[vi] = c.netherrack_black - elseif sel == 7 then - data[vi] = c.glowstone - else - data[vi] = c.air - end - - elseif y <= NETHER_BOTTOM then - if y <= bottom then - data[vi] = return_nether_ore(d_p_addp, true) - else - data[vi] = c.lava - end - elseif r_structure == 1 - and y == bottom then - tab[num] = {x=x, y=y-1, z=z} - num = num+1 - elseif y <= bottom then - if pr:next(1,LAVA_FREQ) == 1 then - data[vi] = c.lava - else - data[vi] = return_nether_ore(d_p_addp, false) - end - elseif r_shroom == 1 - and r_structure ~= 1 - and y == bottom+1 then - data[vi] = c.nether_shroom - elseif (y == top and r_glowstone == 1) then - data[vi] = c.glowstone - elseif y >= top then - data[vi] = return_nether_ore(d_p_addp, true) - elseif y <= top-1 - and generate_vine - and y >= top-r_vine_length then - data[vi] = c.nether_vine - else - data[vi] = c.air - end - end - vi = vi + area.ystride - end - end - end - end - vm:set_data(data) --- vm:set_lighting(12) --- vm:calc_lighting() --- vm:update_liquids() - vm:write_to_map(false) - - nether:inform("nodes set", 2, t1) - - local t2 = minetest.get_us_time() - local tr_bl_cnt = 0 - - if structures_enabled then -- Blood netherstructures - tr_bl_cnt = #tab - for i = 1,tr_bl_cnt do - nether.grow_netherstructure(tab[i], true) - end - end - - if forest_possible then -- Forest trees - tr_bl_cnt = tr_bl_cnt + #trees - for i = 1,#trees do - nether.grow_tree(trees[i], true) - end - end - - if tr_bl_cnt > 0 then - nether:inform(tr_bl_cnt .. " trees and blood structures set", 2, t2) - end - - t2 = minetest.get_us_time() - minetest.fix_light(minp, maxp) - - nether:inform("light fixed", 2, t2) - - nether:inform("done", 1, t1) -end) - +dofile(path .. "/mapgen.lua") function nether.grow_netherstructure(pos, generated) local t1 = minetest.get_us_time() - if not contents_defined then - define_contents() - contents_defined = true - end + define_contents() if not pos.x then print(dump(pos)) nether:inform("Error: "..dump(pos), 1) @@ -736,10 +150,7 @@ local h_trunk_max = h_max-h_arm_max function nether.grow_tree(pos, generated) local t1 = minetest.get_us_time() - if not contents_defined then - define_contents() - contents_defined = true - end + define_contents() local min = vector.new(pos) local max = vector.new(pos) @@ -926,8 +337,8 @@ minetest.register_abm({ minetest.register_abm({ nodenames = {"nether:tree_sapling"}, neighbors = {"group:nether_dirt"}, - interval = abm_tree_interval, - chance = abm_tree_chance, + interval = nether.v.abm_tree_interval, + chance = nether.v.abm_tree_chance, action = function(pos) if minetest.get_node({x=pos.x, y=pos.y+2, z=pos.z}).name == "air" and minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name == "air" then diff --git a/nether/mapgen.lua b/nether/mapgen.lua new file mode 100644 index 0000000..96dbcc2 --- /dev/null +++ b/nether/mapgen.lua @@ -0,0 +1,480 @@ + +local path = nether.path + +-- vars +local v = nether.v +local nether_middle = v.nether_middle +local f_bottom_scale = v.f_bottom_scale +local f_h_min = v.f_h_min +local f_h_max = v.f_h_max +local tree_rarity = v.tree_rarity +local glowflower_rarity = v.glowflower_rarity +local grass_rarity = v.grass_rarity +local mushroom_rarity = v.mushroom_rarity +local nether_start = v.nether_start +local NETHER_HEIGHT = v.NETHER_HEIGHT +local NETHER_RANDOM = v.NETHER_RANDOM +local GLOWSTONE_FREQ_ROOF = v.GLOWSTONE_FREQ_ROOF +local LAVA_FREQ = v.LAVA_FREQ +local nether_structure_freq = v.nether_structure_freq +local NETHER_SHROOM_FREQ = v.NETHER_SHROOM_FREQ +local NETHER_BOTTOM = v.NETHER_BOTTOM +local nether_buildings = v.nether_buildings + +local nether_weird_noise = dofile(path .. "/weird_mapgen_noise.lua") + +-- Weierstrass function stuff from https://github.com/slemonide/gen +local get_ws_list +do + local SIZE = 1000 + local ssize = math.ceil(math.abs(SIZE)) + local function do_ws_func(depth, a, x) + local n = math.pi * x / (16 * SIZE) + local y = 0 + for k=1,depth do + y = y + math.sin(k^a * n) / k^a + end + return SIZE * y / math.pi + end + + local chunksize = minetest.settings:get"chunksize" or 5 + local ws_lists = {} + get_ws_list = function(a,x) + ws_lists[a] = ws_lists[a] or {} + local v = ws_lists[a][x] + if v then + return v + end + v = {} + for x=x,x + (chunksize*16 - 1) do + local y = do_ws_func(ssize, a, x) + v[x] = y + end + ws_lists[a][x] = v + return v + end +end + +local function dif(z1, z2) + return math.abs(z1-z2) +end + +local function pymg(x1, x2, z1, z2) + return math.max(dif(x1, x2), dif(z1, z2)) +end + +-- Generated variables +--~ local NETHER_ROOF_ABS = (nether_middle - NETHER_RANDOM) +local f_yscale_top = (f_h_max-f_h_min)/2 +local f_yscale_bottom = f_yscale_top/2 +--HADES_THRONE_STARTPOS_ABS = {x=HADES_THRONE_STARTPOS.x, y=(NETHER_BOTTOM + +--HADES_THRONE_STARTPOS.y), z=HADES_THRONE_STARTPOS.z} +--LAVA_Y = (NETHER_BOTTOM + LAVA_HEIGHT) +--HADES_THRONE_ABS = {} +--HADES_THRONE_ENDPOS_ABS = {} +--HADES_THRONE_GENERATED = minetest.get_worldpath() .. "/netherhadesthrone.txt" +--NETHER_SPAWNPOS_ABS = {x=NETHER_SPAWNPOS.x, y=(NETHER_BOTTOM + +--NETHER_SPAWNPOS.y), z=NETHER_SPAWNPOS.z} +--[[for i,v in ipairs(HADES_THRONE) do + v.pos.x = v.pos.x + HADES_THRONE_STARTPOS_ABS.x + v.pos.y = v.pos.y + HADES_THRONE_STARTPOS_ABS.y + v.pos.z = v.pos.z + HADES_THRONE_STARTPOS_ABS.z + HADES_THRONE_ABS[i] = v +end +local htx = 0 +local hty = 0 +local htz = 0 +for i,v in ipairs(HADES_THRONE_ABS) do + if v.pos.x > htx then + htx = v.pos.x + end + if v.pos.y > hty then + hty = v.pos.y + end + if v.pos.z > htz then + htz = v.pos.z + end +end +HADES_THRONE_ENDPOS_ABS = {x=htx, y=hty, z=htz}]] + +local c, nether_tree_nodes, contents_defined +local function define_contents() + if not contents_defined then + c, nether_tree_nodes = nether.query_contents() + contents_defined = true + end +end + +local pr + +local function return_nether_ore(id, glowstone) + if glowstone + and pr:next(0,GLOWSTONE_FREQ_ROOF) == 1 then + return c.glowstone + end + if id == c.coal then + return c.netherrack_tiled + end + if id == c.gravel then + return c.netherrack_black + end + if id == c.diamond then + return c.netherrack_blue + end + if id == c.mese then + return c.white + end + return c.netherrack +end + +local f_perlins = {} + +-- abs(v) < 1-(persistance^octaves))/(1-persistance) = amp +--local perlin1 = minetest.get_perlin(13,3, 0.5, 50) --Get map specific perlin +-- local perlin2 = minetest.get_perlin(133,3, 0.5, 10) +-- local perlin3 = minetest.get_perlin(112,3, 0.5, 5) +local tmp = f_yscale_top*4 +local tmp2 = tmp/f_bottom_scale +local perlins = { + { -- amp 1.75 + seed = 13, + octaves = 3, + persist = 0.5, + spread = {x=50, y=50, z=50}, + scale = 1, + offset = 0, + }, + {-- amp 1.75 + seed = 133, + octaves = 3, + persist = 0.5, + spread = {x=10, y=10, z=10}, + scale = 1, + offset = 0, + }, + {-- amp 1.75 + seed = 112, + octaves = 3, + persist = 0.5, + spread = {x=5, y=5, z=5}, + scale = 1, + offset = 0, + }, + --[[forest_bottom = { + seed = 11, + octaves = 3, + persist = 0.8, + spread = {x=tmp2, y=tmp2, z=tmp2}, + scale = 1, + offset = 0, + },]] + forest_top = {-- amp 2.44 + seed = 21, + octaves = 3, + persist = 0.8, + spread = {x=tmp, y=tmp, z=tmp}, + scale = 1, + offset = 0, + }, +} + +-- buffers, see https://forum.minetest.net/viewtopic.php?f=18&t=16043 +local pelin_maps +local pmap1 = {} +local pmap2 = {} +local pmap3 = {} +local pmap_f_top = {} +local data = {} + +local structures_enabled = true +local vine_maxlength = math.floor(NETHER_HEIGHT/4+0.5) +-- Create the Nether +minetest.register_on_generated(function(minp, maxp, seed) + --avoid big map generation + if not (maxp.y >= NETHER_BOTTOM-100 and minp.y <= nether_start) then + return + end + + local t1 = minetest.get_us_time() + nether:inform("generates at: x=["..minp.x.."; "..maxp.x.."]; y=[" .. + minp.y.."; "..maxp.y.."]; z=["..minp.z.."; "..maxp.z.."]", 2) + + define_contents() + + local buildings = 0 + if maxp.y <= NETHER_BOTTOM then + buildings = 1 + elseif minp.y <= nether_buildings then + buildings = 2 + end + + local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") + vm:get_data(data) + local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax} + + pr = PseudoRandom(seed+33) + local tab,num = {},1 + local trees,num_trees = {},1 + + --local perlin1 = minetest.get_perlin(13,3, 0.5, 50) + --local perlin2 = minetest.get_perlin(133,3, 0.5, 10) + --local perlin3 = minetest.get_perlin(112,3, 0.5, 5) + + local side_length = maxp.x - minp.x + 1 + local map_lengths_xyz = {x=side_length, y=side_length, z=side_length} + + if not pelin_maps then + pelin_maps = { + a = minetest.get_perlin_map(perlins[1], map_lengths_xyz), + b = minetest.get_perlin_map(perlins[2], map_lengths_xyz), + c = minetest.get_perlin_map(perlins[3], map_lengths_xyz), + forest_top = minetest.get_perlin_map(perlins.forest_top, + map_lengths_xyz), + } + end + pelin_maps.a:get_2d_map_flat({x=minp.x, y=minp.z}, pmap1) + pelin_maps.b:get_2d_map_flat({x=minp.x, y=minp.z}, pmap2) + pelin_maps.c:get_2d_map_flat({x=minp.x, y=minp.z}, pmap3) + + local forest_possible = maxp.y > f_h_min and minp.y < f_h_max + + --local pmap_f_bottom = minetest.get_perlin_map(perlins.forest_bottom, + -- map_lengths_xyz):get_2d_map_flat({x=minp.x, y=minp.z}) + local perlin_f_bottom, strassx, strassz + if forest_possible then + perlin_f_bottom = minetest.get_perlin(11, 3, 0.8, tmp2) + pelin_maps.forest_top:get_2d_map_flat({x=minp.x, y=minp.z}, pmap_f_top) + strassx = get_ws_list(2, minp.x) + strassz = get_ws_list(2, minp.z) + end + + local num2, tab2 + if buildings >= 1 then + num2 = 1 + tab2 = nether_weird_noise({x=minp.x, y=nether_buildings-79, z=minp.z}, + pymg, 200, 8, 10, side_length-1) + end + + local count = 0 + for z=minp.z, maxp.z do + for x=minp.x, maxp.x do + + count = count+1 + + local test = pmap1[count]+1 + local test2 = pmap2[count] + local test3 = math.abs(pmap3[count]) + + local t = math.floor(test*3+0.5) + + local h + if test2 < 0 then + h = math.floor(test2*3+0.5)-1 + else + h = 3+t+pr:next(0,NETHER_RANDOM) + end + + local generate_vine = false + if test3 >= 0.72+pr:next(0,NETHER_RANDOM)/10 + and pr:next(0,NETHER_RANDOM) == 1 then + generate_vine = true + end + + local bottom = NETHER_BOTTOM+h + local top = nether_middle-pr:next(0,NETHER_RANDOM)+t + + local py_h = 0 + local difn, noisp, py_h_g + if buildings >= 1 then + py_h = tab2[num2].y + num2 = num2+1 + + difn = nether_buildings-py_h + if difn == 5 then + noisp = 1 + elseif difn < 5 then + noisp = 2 + end + py_h_g = nether_buildings-7 + end + + local vi = area:index(x, minp.y, z) + if buildings == 1 + and noisp then + if noisp == 1 then + for _ = 1,side_length do + data[vi] = c.netherrack_brick + vi = vi + area.ystride + end + else + for _ = 1,side_length do + data[vi] = c.lava + vi = vi + area.ystride + end + end + else + + local r_structure = pr:next(1,nether_structure_freq) + local r_shroom = pr:next(1,NETHER_SHROOM_FREQ) + local r_glowstone = pr:next(0,GLOWSTONE_FREQ_ROOF) + local r_vine_length = pr:next(1,vine_maxlength) + + local f_bottom, f_top, is_forest, f_h_dirt + if forest_possible then + local p = {x=math.floor(x/f_bottom_scale), + z=math.floor(z/f_bottom_scale)} + local pstr = p.x.." "..p.z + if not f_perlins[pstr] then + f_perlins[pstr] = math.floor(f_h_min + (math.abs( + perlin_f_bottom:get_2d{x=p.x, y=p.z} + 1)) + * f_yscale_bottom + 0.5) + end + local top_noise = pmap_f_top[count]+1 + if top_noise < 0 then + top_noise = -top_noise/10 + --nether:inform("ERROR: (perlin noise) ".. + -- pmap_f_top[count].." is not inside [-1; 1]", 1) + end + f_top = math.floor(f_h_max - top_noise*f_yscale_top + 0.5) + f_bottom = f_perlins[pstr]+pr:next(0,f_bottom_scale-1) + is_forest = f_bottom < f_top + f_h_dirt = f_bottom-pr:next(0,1) + end + + for y=minp.y, maxp.y do + local d_p_addp = data[vi] + --if py_h >= maxp.y-4 then + if y <= py_h + and noisp then + if noisp == 1 then + data[vi] = c.netherrack_brick + elseif noisp == 2 then + if y == py_h then + data[vi] = c.netherrack_brick + elseif y == py_h_g + and pr:next(1,3) <= 2 then + data[vi] = c.netherrack + elseif y <= py_h_g then + data[vi] = c.lava + else + data[vi] = c.air + end + end + elseif d_p_addp ~= c.air then + + if is_forest + and y == f_bottom then + data[vi] = c.nether_dirt_top + elseif is_forest + and y < f_bottom + and y >= f_h_dirt then + data[vi] = c.nether_dirt + elseif is_forest + and y == f_h_dirt-1 then + data[vi] = c.nether_dirt_bottom + elseif is_forest + and y == f_h_dirt+1 then + if pr:next(1,tree_rarity) == 1 then + trees[num_trees] = {x=x, y=y, z=z} + num_trees = num_trees+1 + elseif pr:next(1,mushroom_rarity) == 1 then + data[vi] = c.nether_shroom + elseif pr:next(1,glowflower_rarity) == 1 then + data[vi] = c.glowflower + elseif pr:next(1,grass_rarity) == 1 then + data[vi] = c.nether_grass[pr:next(1,3)] + else + data[vi] = c.air + end + elseif is_forest + and y > f_bottom + and y < f_top then + if not nether_tree_nodes[d_p_addp] then + data[vi] = c.air + end + elseif is_forest + and y == f_top then + local sel = math.floor(strassx[x]+strassz[z]+0.5)%10 + if sel <= 5 then + data[vi] = return_nether_ore(d_p_addp, true) + elseif sel == 6 then + data[vi] = c.netherrack_black + elseif sel == 7 then + data[vi] = c.glowstone + else + data[vi] = c.air + end + + elseif y <= NETHER_BOTTOM then + if y <= bottom then + data[vi] = return_nether_ore(d_p_addp, true) + else + data[vi] = c.lava + end + elseif r_structure == 1 + and y == bottom then + tab[num] = {x=x, y=y-1, z=z} + num = num+1 + elseif y <= bottom then + if pr:next(1,LAVA_FREQ) == 1 then + data[vi] = c.lava + else + data[vi] = return_nether_ore(d_p_addp, false) + end + elseif r_shroom == 1 + and r_structure ~= 1 + and y == bottom+1 then + data[vi] = c.nether_shroom + elseif (y == top and r_glowstone == 1) then + data[vi] = c.glowstone + elseif y >= top then + data[vi] = return_nether_ore(d_p_addp, true) + elseif y <= top-1 + and generate_vine + and y >= top-r_vine_length then + data[vi] = c.nether_vine + else + data[vi] = c.air + end + end + vi = vi + area.ystride + end + end + end + end + vm:set_data(data) +-- vm:set_lighting(12) +-- vm:calc_lighting() +-- vm:update_liquids() + vm:write_to_map(false) + + nether:inform("nodes set", 2, t1) + + local t2 = minetest.get_us_time() + local tr_bl_cnt = 0 + + if structures_enabled then -- Blood netherstructures + tr_bl_cnt = #tab + for i = 1,tr_bl_cnt do + nether.grow_netherstructure(tab[i], true) + end + end + + if forest_possible then -- Forest trees + tr_bl_cnt = tr_bl_cnt + #trees + for i = 1,#trees do + nether.grow_tree(trees[i], true) + end + end + + if tr_bl_cnt > 0 then + nether:inform(tr_bl_cnt .. " trees and blood structures set", 2, t2) + end + + t2 = minetest.get_us_time() + minetest.fix_light(minp, maxp) + + nether:inform("light fixed", 2, t2) + + nether:inform("done", 1, t1) +end) diff --git a/nether/portal.lua b/nether/portal.lua index d8b325b..d3240ed 100644 --- a/nether/portal.lua +++ b/nether/portal.lua @@ -1,7 +1,11 @@ --code copied from Pilzadam's nether mod and edited +local nether_start = nether.v.nether_start +local nether_bottom = nether.v.nether_bottom +local nether_buildings = nether.v.nether_buildings + -- kills the player if he uses PilzAdam portal -local portal_target = nether.buildings+1 +local portal_target = nether_buildings+1 local damage_enabled = minetest.settings:get_bool"enable_damage" local mclike_portal = false @@ -44,7 +48,7 @@ end -- Nether aware mods will need to know if a player is in the nether. function nether.is_player_in_nether(player) local pos = player:get_pos() - return (pos.y < nether.start) and (pos.y >= nether.bottom) + return (pos.y < nether_start) and (pos.y >= nether_bottom) end -- For testing nether trap state tracking. @@ -73,7 +77,7 @@ function nether.external_nether_teleport(player, pos) player:set_pos(pos) return end - local destination_in_nether = (pos.y < nether.start) and (pos.y >= nether.bottom) + local destination_in_nether = (pos.y < nether_start) and (pos.y >= nether_bottom) update_background(player, destination_in_nether) local pname = player:get_player_name() players_trapped_in_nether[pname] = destination_in_nether or nil @@ -84,7 +88,7 @@ end -- Has nether.trap_players been disabled? function nether.registry_update(player) local pos = player:get_pos() - local in_nether = (pos.y < nether.start) and (pos.y >= nether.bottom) + local in_nether = (pos.y < nether_start) and (pos.y >= nether_bottom) local pname = player:get_player_name() if nether.trap_players then players_trapped_in_nether[pname] = in_nether or nil @@ -334,7 +338,7 @@ if nether.trap_players then local in_nether = players_trapped_in_nether[pname] == true -- test if the target is valid - if pos.y < nether.start then + if pos.y < nether_start then if in_nether then return true end @@ -344,7 +348,7 @@ if nether.trap_players then -- test if the current position is valid local current_pos = player:get_pos() - local now_in_nether = current_pos.y < nether.start + local now_in_nether = current_pos.y < nether_start if now_in_nether ~= in_nether then if in_nether then minetest.log("action", "Player \"" .. pname .. @@ -372,7 +376,7 @@ if nether.trap_players then local metatable_overridden minetest.register_on_joinplayer(function(player) -- set the background when the player joins - if player:get_pos().y < nether.start then + if player:get_pos().y < nether_start then update_background(player, true) end @@ -559,7 +563,7 @@ local function make_portal(pos) return false end - local in_nether = p1.y < nether.start + local in_nether = p1.y < nether_start if in_nether and not mclike_portal then @@ -788,7 +792,7 @@ function nether.teleport_player(player) end minetest.sound_play("nether_teleporter", {pos=pos}) local meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z}) - if pos.y < nether.start then + if pos.y < nether_start then set_portal(known_portals_d, pos.z,pos.x, pos.y) local my = tonumber(meta:get_string("y")) diff --git a/nether/settings.lua b/nether/settings.lua index f0f97db..5b836ca 100644 --- a/nether/settings.lua +++ b/nether/settings.lua @@ -5,7 +5,7 @@ local default_settings = { overworld_help = true, } -nether.settings = {} +nether.settings = {} -- FIXME: unused field. store settings in here? for name,dv in pairs(default_settings) do local setting