1
0
mirror of https://github.com/HybridDog/nether-pack.git synced 2024-11-16 15:30:20 +01:00
nether-pack/nether/init.lua

1033 lines
26 KiB
Lua
Raw Normal View History

2012-04-19 21:55:39 +02:00
-- Nether Mod (based on Nyanland by Jeija, Catapult by XYZ, and Livehouse by neko259)
-- lkjoel (main developer, code, ideas, textures)
-- == CONTRIBUTERS ==
-- jordan4ibanez (code, ideas, textures)
-- Gilli (code, ideas, textures, mainly for the Glowstone)
-- Death Dealer (code, ideas, textures)
-- LolManKuba (ideas, textures)
-- IPushButton2653 (ideas, textures)
-- Menche (textures)
-- sdzen (ideas)
-- godkiller447 (ideas)
-- If I didn't list you, please let me know!
2012-04-16 23:27:29 +02:00
2015-08-05 10:35:32 +02:00
local load_time_start = os.clock()
2015-02-18 18:34:03 +01:00
if not rawget(_G, "nether") then
nether = {}
end
2012-04-16 23:27:29 +02:00
--== EDITABLE OPTIONS ==--
2015-02-18 18:34:03 +01:00
--says some information.
nether.info = true
-- tell everyone about the generation
nether.inform_all = minetest.is_singleplayer()
--1:<a bit of information> 2:<acceptable amount of information> 3:<lots of text>
nether.max_spam = 2
2012-04-16 23:27:29 +02:00
-- Depth of the nether
2015-02-18 18:34:03 +01:00
local nether_middle = -20000
-- 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
2015-02-18 18:34:03 +01:00
-- 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
2012-04-19 00:11:38 +02:00
-- Maximum amount of randomness in the map generation
NETHER_RANDOM = 2
2015-02-18 18:34:03 +01:00
2012-04-19 21:55:39 +02:00
-- Frequency of Glowstone on the "roof" of the Nether (higher is less frequent)
2015-02-18 18:34:03 +01:00
local GLOWSTONE_FREQ_ROOF = 500
2012-04-16 23:27:29 +02:00
-- Frequency of lava (higher is less frequent)
2015-02-18 18:34:03 +01:00
local LAVA_FREQ = 100
local nether_structure_freq = 350
local NETHER_SHROOM_FREQ = 100
2012-04-16 23:27:29 +02:00
-- Maximum height of lava
2015-02-18 18:34:03 +01:00
--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)
2015-02-18 18:34:03 +01:00
--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)
2015-02-18 18:34:03 +01:00
--NETHER_SPAWNPOS = {x=0, y=5, z=0}
2012-04-19 00:11:38 +02:00
-- Structure of the nether portal (all is relative to the nether portal creator block)
2012-04-16 23:27:29 +02:00
--== END OF EDITABLE OPTIONS ==--
2015-02-18 18:34:03 +01:00
if nether.info then
function nether:inform(msg, spam, t)
if spam <= self.max_spam then
local info
if t then
info = string.format("[nether] "..msg.." after ca. %.2fs", os.clock() - t)
else
info = "[nether] "..msg
end
print(info)
if self.inform_all then
minetest.chat_send_all(info)
end
end
end
else
function nether.inform()
2015-02-18 18:34:03 +01:00
end
end
2014-04-18 22:02:24 +02:00
local path = minetest.get_modpath("nether")
dofile(path.."/weird_mapgen_noise.lua")
2015-02-18 18:34:03 +01:00
dofile(path.."/items.lua")
2015-07-05 21:01:13 +02:00
--dofile(path.."/furnace.lua")
2015-02-18 18:34:03 +01:00
dofile(path.."/pearl.lua")
local function table_contains(t, v)
for _,i in pairs(t) do
if i == v then
return true
end
end
return false
end
2014-04-18 22:02:24 +02:00
-- 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)
2016-05-04 17:43:37 +02:00
local n = math.pi * x / (16 * SIZE)
local y = 0
for k=1,depth do
2016-05-04 17:43:37 +02:00
y = y + math.sin(k^a * n) / k^a
end
2016-05-04 18:42:45 +02:00
return SIZE * y / math.pi
end
2017-07-05 18:52:46 +02:00
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
2014-04-18 22:02:24 +02:00
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
2013-11-17 21:04:15 +01:00
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},
{x=pos.x+width, y=pos.y+height, z=pos.z+width}
)
return VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
end
2015-02-18 18:34:03 +01:00
local function set_vm_data(manip, nodes, pos, t1, name, generated)
manip:set_data(nodes)
manip:write_to_map()
local spam = 2
if generated then
spam = 3
end
nether:inform(name.." grew at ("..pos.x.."|"..pos.y.."|"..pos.z..")", spam, t1)
if not generated then
local t1 = os.clock()
manip:update_map()
nether:inform("map updated", spam, t1)
end
end
local function fix_light(minp, maxp)
local manip = minetest.get_voxel_manip()
local emerged_pos1, emerged_pos2 = manip:read_from_map(minp, maxp)
area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
nodes = manip:get_data()
2013-11-17 21:04:15 +01:00
manip:set_data(nodes)
manip:write_to_map()
manip:update_map()
end
2012-04-16 23:27:29 +02:00
-- Generated variables
2015-02-18 18:34:03 +01:00
local NETHER_BOTTOM = (nether_middle - NETHER_HEIGHT)
nether.buildings = NETHER_BOTTOM+12
--~ local NETHER_ROOF_ABS = (nether_middle - NETHER_RANDOM)
2015-02-18 18:34:03 +01:00
local f_yscale_top = (f_h_max-f_h_min)/2
local f_yscale_bottom = f_yscale_top/2
2014-04-17 11:20:20 +02:00
--HADES_THRONE_STARTPOS_ABS = {x=HADES_THRONE_STARTPOS.x, y=(NETHER_BOTTOM + HADES_THRONE_STARTPOS.y), z=HADES_THRONE_STARTPOS.z}
2015-02-18 18:34:03 +01:00
--LAVA_Y = (NETHER_BOTTOM + LAVA_HEIGHT)
2014-04-17 11:20:20 +02:00
--HADES_THRONE_ABS = {}
--HADES_THRONE_ENDPOS_ABS = {}
--HADES_THRONE_GENERATED = minetest.get_worldpath() .. "/netherhadesthrone.txt"
2015-02-18 18:34:03 +01:00
--NETHER_SPAWNPOS_ABS = {x=NETHER_SPAWNPOS.x, y=(NETHER_BOTTOM + NETHER_SPAWNPOS.y), z=NETHER_SPAWNPOS.z}
2014-04-17 11:20:20 +02:00
--[[for i,v in ipairs(HADES_THRONE) do
2012-04-16 23:27:29 +02:00
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
2012-04-19 00:11:38 +02:00
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
2014-04-17 11:20:20 +02:00
HADES_THRONE_ENDPOS_ABS = {x=htx, y=hty, z=htz}]]
2012-04-19 00:11:38 +02:00
2015-02-18 18:34:03 +01:00
local c
local function define_contents()
c = {
ignore = minetest.get_content_id("ignore"),
2015-02-18 18:34:03 +01:00
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"),
glowstone = minetest.get_content_id("glow:stone"), --https://github.com/Zeg9/minetest-glow
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"),
}
2012-04-19 01:42:46 +02:00
end
2015-02-18 18:34:03 +01:00
local pr, contents_defined
2012-04-19 01:42:46 +02:00
2015-02-18 18:34:03 +01:00
local function return_nether_ore(id, glowstone)
if glowstone
and pr:next(0,GLOWSTONE_FREQ_ROOF) == 1 then
return c.glowstone
2012-04-19 00:11:38 +02:00
end
2015-02-18 18:34:03 +01:00
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
2012-04-19 00:11:38 +02:00
end
2015-02-18 18:34:03 +01:00
local f_perlins = {}
2016-05-26 12:17:06 +02:00
-- abs(v) < 1-(persistance^octaves))/(1-persistance) = amp
2015-02-18 18:34:03 +01:00
--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 = {
2016-05-26 12:17:06 +02:00
{ -- amp 1.75
2015-02-18 18:34:03 +01:00
seed = 13,
octaves = 3,
persist = 0.5,
spread = {x=50, y=50, z=50},
scale = 1,
offset = 0,
},
2016-05-26 12:17:06 +02:00
{-- amp 1.75
2015-02-18 18:34:03 +01:00
seed = 133,
octaves = 3,
persist = 0.5,
spread = {x=10, y=10, z=10},
scale = 1,
offset = 0,
},
2016-05-26 12:17:06 +02:00
{-- amp 1.75
2015-02-18 18:34:03 +01:00
seed = 112,
octaves = 3,
persist = 0.5,
spread = {x=5, y=5, z=5},
scale = 1,
offset = 0,
2012-04-16 23:27:29 +02:00
},
2015-02-18 18:34:03 +01:00
--[[forest_bottom = {
seed = 11,
octaves = 3,
persist = 0.8,
spread = {x=tmp2, y=tmp2, z=tmp2},
scale = 1,
offset = 0,
},]]
2016-05-26 12:17:06 +02:00
forest_top = {-- amp 2.44
2015-02-18 18:34:03 +01:00
seed = 21,
octaves = 3,
persist = 0.8,
spread = {x=tmp, y=tmp, z=tmp},
scale = 1,
offset = 0,
},
}
2014-04-17 11:20:20 +02:00
2015-02-18 18:34:03 +01:00
local structures_enabled = true
2013-08-15 01:06:30 +02:00
local vine_maxlength = math.floor(NETHER_HEIGHT/4+0.5)
2012-04-16 23:27:29 +02:00
-- Create the Nether
2013-08-12 18:14:29 +02:00
minetest.register_on_generated(function(minp, maxp, seed)
2015-02-18 18:34:03 +01:00
if not (maxp.y >= NETHER_BOTTOM-100 and minp.y <= nether.start) then --avoid big map generation
2013-08-12 18:14:29 +02:00
return
end
2015-02-18 18:34:03 +01:00
local t1 = os.clock()
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()
contents_defined = true
end
local buildings = 0
if maxp.y <= NETHER_BOTTOM then
buildings = 1
elseif minp.y <= nether.buildings then
buildings = 2
2013-08-12 18:14:29 +02:00
end
2013-08-15 01:06:30 +02:00
2013-08-12 18:14:29 +02:00
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
2014-04-17 11:20:20 +02:00
pr = PseudoRandom(seed+33)
2014-04-18 22:02:24 +02:00
local tab,num = {},1
2015-02-18 18:34:03 +01:00
local trees,num_trees = {},1
--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)
2016-03-10 20:47:16 +01:00
local side_length = maxp.x - minp.x + 1
2015-02-18 18:34:03 +01:00
local map_lengths_xyz = {x=side_length, y=side_length, z=side_length}
2013-08-12 18:14:29 +02:00
local pmap1 = minetest.get_perlin_map(perlins[1], map_lengths_xyz):get2dMap_flat({x=minp.x, y=minp.z})
local pmap2 = minetest.get_perlin_map(perlins[2], map_lengths_xyz):get2dMap_flat({x=minp.x, y=minp.z})
local pmap3 = minetest.get_perlin_map(perlins[3], map_lengths_xyz):get2dMap_flat({x=minp.x, y=minp.z})
2013-08-15 01:06:30 +02:00
2015-02-18 18:34:03 +01:00
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):get2dMap_flat({x=minp.x, y=minp.z})
local perlin_f_bottom, pmap_f_top, strassx, strassz
2015-02-18 18:34:03 +01:00
if forest_possible then
perlin_f_bottom = minetest.get_perlin(11, 3, 0.8, tmp2)
pmap_f_top = minetest.get_perlin_map(perlins.forest_top, map_lengths_xyz):get2dMap_flat({x=minp.x, y=minp.z})
strassx = get_ws_list(2, minp.x)
strassz = get_ws_list(2, minp.z)
2015-02-18 18:34:03 +01:00
end
local num2, tab2
if buildings >= 1 then
num2 = 1
2016-03-10 20:47:16 +01:00
tab2 = nether_weird_noise({x=minp.x, y=nether.buildings-79, z=minp.z}, pymg, 200, 8, 10, side_length-1)
2015-02-18 18:34:03 +01:00
end
local count = 0
2014-04-18 22:02:24 +02:00
for z=minp.z, maxp.z do
for x=minp.x, maxp.x do
2013-08-15 01:06:30 +02:00
2015-02-18 18:34:03 +01:00
count = count+1
2013-08-15 01:06:30 +02:00
2015-02-18 18:34:03 +01:00
local test = pmap1[count]+1
local test2 = pmap2[count]
local test3 = math.abs(pmap3[count])
2013-08-15 01:06:30 +02:00
local t = math.floor(test*3+0.5)
2015-03-19 16:13:24 +01:00
local h
2013-08-15 01:06:30 +02:00
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
2015-02-18 18:34:03 +01:00
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)
2015-02-18 18:34:03 +01:00
if buildings == 1
and noisp then
if noisp == 1 then
for _ = 1,side_length do
data[vi] = c.netherrack_brick
vi = vi + area.ystride
2015-02-18 18:34:03 +01:00
end
else
for _ = 1,side_length do
data[vi] = c.lava
vi = vi + area.ystride
2015-02-18 18:34:03 +01:00
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:get2d({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)
2015-02-18 18:34:03 +01:00
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]
2015-02-18 18:34:03 +01:00
--if py_h >= maxp.y-4 then
if y <= py_h
and noisp then
if noisp == 1 then
data[vi] = c.netherrack_brick
2015-02-18 18:34:03 +01:00
elseif noisp == 2 then
if y == py_h then
data[vi] = c.netherrack_brick
2015-02-18 18:34:03 +01:00
elseif y == py_h_g
and pr:next(1,3) <= 2 then
data[vi] = c.netherrack
2015-02-18 18:34:03 +01:00
elseif y <= py_h_g then
data[vi] = c.lava
2015-02-18 18:34:03 +01:00
else
data[vi] = c.air
2015-02-18 18:34:03 +01:00
end
2014-04-17 11:20:20 +02:00
end
2015-02-18 18:34:03 +01:00
elseif d_p_addp ~= c.air then
if is_forest
and y == f_bottom then
data[vi] = c.nether_dirt_top
2015-02-18 18:34:03 +01:00
elseif is_forest
and y < f_bottom
and y >= f_h_dirt then
data[vi] = c.nether_dirt
2015-02-18 18:34:03 +01:00
elseif is_forest
and y == f_h_dirt-1 then
data[vi] = c.nether_dirt_bottom
2015-02-18 18:34:03 +01:00
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
2015-02-18 18:34:03 +01:00
elseif pr:next(1,glowflower_rarity) == 1 then
data[vi] = c.glowflower
2015-02-18 18:34:03 +01:00
elseif pr:next(1,grass_rarity) == 1 then
data[vi] = c.nether_grass[pr:next(1,3)]
2015-02-18 18:34:03 +01:00
else
data[vi] = c.air
2015-02-18 18:34:03 +01:00
end
elseif is_forest
and y > f_bottom
and y < f_top then
if not table_contains(
{c.nether_tree, c.nether_tree_corner, c.nether_leaves, c.nether_fruit},
d_p_addp
) then
data[vi] = c.air
2015-02-18 18:34:03 +01:00
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
2015-02-18 18:34:03 +01:00
elseif y <= NETHER_BOTTOM then
if y <= bottom then
data[vi] = return_nether_ore(d_p_addp, true)
2015-02-18 18:34:03 +01:00
else
data[vi] = c.lava
2015-02-18 18:34:03 +01:00
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
2015-02-18 18:34:03 +01:00
else
data[vi] = return_nether_ore(d_p_addp, false)
2015-02-18 18:34:03 +01:00
end
elseif r_shroom == 1
and r_structure ~= 1
and y == bottom+1 then
data[vi] = c.nether_shroom
2015-02-18 18:34:03 +01:00
elseif (y == top and r_glowstone == 1) then
data[vi] = c.glowstone
2015-02-18 18:34:03 +01:00
elseif y >= top then
data[vi] = return_nether_ore(d_p_addp, true)
2015-02-18 18:34:03 +01:00
elseif y <= top-1
and generate_vine
and y >= top-r_vine_length then
data[vi] = c.nether_vine
2014-04-17 11:20:20 +02:00
else
data[vi] = c.air
2014-04-17 11:20:20 +02:00
end
2013-08-15 01:06:30 +02:00
end
vi = vi + area.ystride
2013-08-12 18:14:29 +02:00
end
2012-04-16 23:27:29 +02:00
end
end
2013-08-12 18:14:29 +02:00
end
vm:set_data(data)
2014-04-17 11:20:20 +02:00
-- vm:set_lighting(12)
2015-02-18 18:34:03 +01:00
-- vm:calc_lighting()
-- vm:update_liquids()
2013-08-12 18:14:29 +02:00
vm:write_to_map()
2015-02-18 18:34:03 +01:00
nether:inform("nodes set", 2, t1)
local t2 = os.clock()
if structures_enabled then --Trees:
2013-08-12 18:14:29 +02:00
for _,v in ipairs(tab) do
2015-02-18 18:34:03 +01:00
nether.grow_netherstructure(v, true)
2013-08-12 18:14:29 +02:00
end
end
2015-02-18 18:34:03 +01:00
if forest_possible then --Trees:
for _,v in ipairs(trees) do
nether.grow_tree(v, true)
2012-04-16 23:27:29 +02:00
end
end
2015-02-18 18:34:03 +01:00
nether:inform("trees set", 2, t2)
2013-08-15 01:06:30 +02:00
2015-02-18 18:34:03 +01:00
t2 = os.clock()
fix_light(minp, maxp)
2013-08-15 01:06:30 +02:00
2015-02-18 18:34:03 +01:00
nether:inform("map updated", 2, t2)
2013-08-15 01:06:30 +02:00
2015-02-18 18:34:03 +01:00
nether:inform("done", 1, t1)
end)
2013-08-15 01:06:30 +02:00
2012-04-19 21:55:39 +02:00
2015-02-18 18:34:03 +01:00
function nether.grow_netherstructure(pos, generated)
local t1 = os.clock()
2012-04-19 21:55:39 +02:00
2015-02-18 18:34:03 +01:00
if not contents_defined then
define_contents()
contents_defined = true
2012-04-19 21:55:39 +02:00
end
2015-02-18 18:34:03 +01:00
if not pos.x then print(dump(pos))
nether:inform("Error: "..dump(pos), 1)
return
end
2013-11-17 21:04:15 +01:00
local height = 6
local manip = minetest.get_voxel_manip()
local area = r_area(manip, 2, height, pos)
local nodes = manip:get_data()
local vi = area:indexp(pos)
for _ = 0, height-1 do
nodes[vi] = c.blood_stem
vi = vi + area.ystride
2013-11-17 21:04:15 +01:00
end
for i = -1,1 do
for j = -1,1 do
2015-02-18 18:34:03 +01:00
nodes[area:index(pos.x+i, pos.y+height, pos.z+j)] = c.blood_top
2013-11-17 21:04:15 +01:00
end
end
for k = -1, 1, 2 do
for l = -2+1, 2 do
local p1 = {pos.x+2*k, pos.y+height, pos.z-l*k}
local p2 = {pos.x+l*k, pos.y+height, pos.z+2*k}
2015-02-18 18:34:03 +01:00
local udat = c.blood_top
2013-11-17 21:04:15 +01:00
if math.random(2) == 1 then
2015-02-18 18:34:03 +01:00
nodes[area:index(p1[1], p1[2], p1[3])] = c.blood_top
nodes[area:index(p2[1], p2[2], p2[3])] = c.blood_top
udat = c.blood
2013-11-17 21:04:15 +01:00
end
nodes[area:index(p1[1], p1[2]-1, p1[3])] = udat
nodes[area:index(p2[1], p2[2]-1, p2[3])] = udat
end
for l = 0, 1 do
for _,p in ipairs({
{pos.x+k, pos.y+height-1, pos.z-l*k},
{pos.x+l*k, pos.y+height-1, pos.z+k},
}) do
if math.random(2) == 1 then
2015-02-18 18:34:03 +01:00
nodes[area:index(p[1], p[2], p[3])] = c.nether_apple
--elseif math.random(10) == 1 then
-- nodes[area:index(p[1], p[2], p[3])] = c.apple
2013-11-17 21:04:15 +01:00
end
end
end
end
2015-02-18 18:34:03 +01:00
set_vm_data(manip, nodes, pos, t1, "blood", generated)
2013-11-17 21:04:15 +01:00
end
2015-02-18 18:34:03 +01:00
2017-12-25 21:22:32 +01:00
local poshash = minetest.hash_node_position
local pos_from_hash = minetest.get_position_from_hash
local function soft_node(id)
return id == c.air or id == c.ignore
end
2015-02-18 18:34:03 +01:00
local function update_minmax(min, max, p)
min.x = math.min(min.x, p.x)
max.x = math.max(max.x, p.x)
min.z = math.min(min.z, p.z)
max.z = math.max(max.z, p.z)
end
local fruit_chances = {}
for y = -2,1 do --like a hyperbola
fruit_chances[y] = math.floor(-4/(y-2)+0.5)
end
local dirs = {
{-1, 0, 12, 19},
{1, 0, 12, 13},
{0, 1, 4},
{0, -1, 4, 10},
}
local h_max = 26
local h_stem_min = 3
local h_stem_max = 7
local h_arm_min = 2
local h_arm_max = 6
local r_arm_min = 1
local r_arm_max = 5
local fruit_rarity = 25 --a bigger number results in less fruits
local leaf_thickness = 3 --a bigger number results in more blank trees
local h_trunk_max = h_max-h_arm_max
function nether.grow_tree(pos, generated)
local t1 = os.clock()
if not contents_defined then
define_contents()
contents_defined = true
end
local min = vector.new(pos)
local max = vector.new(pos)
min.y = min.y-1
max.y = max.y+h_max
local trunks = {}
local trunk_corners = {}
local h_stem = math.random(h_stem_min, h_stem_max)
local todo,n = {{x=pos.x, y=pos.y+h_stem, z=pos.z}},1
while n do
local p = todo[n]
todo[n] = nil
n = next(todo)
local used_dirs,u = {},1
for _,dir in pairs(dirs) do
if math.random(1,2) == 1 then
used_dirs[u] = dir
u = u+1
2012-04-16 23:27:29 +02:00
end
end
if not used_dirs[1] then
local dir1 = math.random(4)
local dir2 = math.random(3)
if dir1 <= dir2 then
dir2 = dir2+1
2015-02-18 18:34:03 +01:00
end
used_dirs[1] = dirs[dir1]
used_dirs[2] = dirs[dir2]
end
for _,dir in pairs(used_dirs) do
local p = vector.new(p)
local r = math.random(r_arm_min, r_arm_max)
for j = 1,r do
local x = p.x+j*dir[1]
local z = p.z+j*dir[2]
2017-12-25 21:22:32 +01:00
trunks[poshash{x=x, y=p.y, z=z}] = dir[3]
2015-02-18 18:34:03 +01:00
end
r = r+1
p.x = p.x+r*dir[1]
p.z = p.z+r*dir[2]
2017-12-25 21:22:32 +01:00
trunk_corners[poshash(p)] = dir[4] or dir[3]
local h = math.random(h_arm_min, h_arm_max)
for i = 1,h do
2017-12-25 21:22:32 +01:00
p.y = p.y + i
trunks[poshash(p)] = true
p.y = p.y - i
2015-02-18 18:34:03 +01:00
end
p.y = p.y+h
--n = #todo+1 -- caused small trees
todo[#todo+1] = p
2012-04-16 23:27:29 +02:00
end
if p.y > pos.y+h_trunk_max then
break
end
n = n or next(todo)
2012-04-16 23:27:29 +02:00
end
2015-02-18 18:34:03 +01:00
local leaves = {}
local fruits = {}
local trunk_ps = {}
local count = 0
2017-12-25 21:22:32 +01:00
local ps = {}
local trunk_count = 0
for i,par2 in pairs(trunks) do
local pos = pos_from_hash(i)
update_minmax(min, max, pos)
local z,y,x = pos.z, pos.y, pos.x
trunk_count = trunk_count+1
ps[trunk_count] = {z,y,x, par2}
end
for _,d in pairs(ps) do
if d[4] == true then
d[4] = nil
2015-02-18 18:34:03 +01:00
end
trunk_ps[#trunk_ps+1] = d
local pz, py, px = unpack(d)
2015-02-18 18:34:03 +01:00
count = count+1
if count > leaf_thickness then
count = 0
for y = -2,2 do
local fruit_chance = fruit_chances[y]
for z = -2,2 do
for x = -2,2 do
local distq = x*x+y*y+z*z
if distq ~= 0
and math.random(1, math.sqrt(distq)) == 1 then
local x = x+px
local y = y+py
local z = z+pz
2017-12-25 21:22:32 +01:00
local vi = poshash{x=x, y=y, z=z}
if not trunks[vi] then
if fruit_chance
and math.random(1, fruit_rarity) == 1
2015-02-18 18:34:03 +01:00
and math.random(1, fruit_chance) == 1 then
2017-12-25 21:22:32 +01:00
fruits[vi] = true
2015-02-18 18:34:03 +01:00
else
2017-12-25 21:22:32 +01:00
leaves[vi] = true
2015-02-18 18:34:03 +01:00
end
update_minmax(min, max, {x=x, z=z})
2015-02-18 18:34:03 +01:00
end
end
end
end
end
2012-04-19 01:42:46 +02:00
end
2012-04-19 00:11:38 +02:00
end
2016-02-06 12:04:17 +01:00
--ps = nil
--collectgarbage()
2015-02-18 18:34:03 +01:00
for i = -1,h_stem+1 do
trunk_ps[#trunk_ps+1] = {pos.z, pos.y+i, pos.x, 0} -- par 0 because of leaves
2012-04-19 00:11:38 +02:00
end
2015-02-18 18:34:03 +01:00
local manip = minetest.get_voxel_manip()
local emerged_pos1, emerged_pos2 = manip:read_from_map(min, max)
local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
local nodes = manip:get_data()
2015-05-29 12:08:27 +02:00
local param2s = manip:get_param2_data()
2015-02-18 18:34:03 +01:00
2017-12-25 21:22:32 +01:00
for i in pairs(leaves) do
local p = area:indexp(pos_from_hash(i))
if soft_node(nodes[p]) then
2015-02-18 18:34:03 +01:00
nodes[p] = c.nether_leaves
param2s[p] = math.random(0,179)
--param2s[p] = math.random(0,44)
end
2012-04-19 00:11:38 +02:00
end
2017-12-25 21:22:32 +01:00
for i in pairs(fruits) do
local p = area:indexp(pos_from_hash(i))
if soft_node(nodes[p]) then
2015-02-18 18:34:03 +01:00
nodes[p] = c.nether_apple
end
2012-04-19 00:11:38 +02:00
end
2017-12-25 21:22:32 +01:00
for i = 1,#trunk_ps do
local p = trunk_ps[i]
local par = p[4]
p = area:index(p[3], p[2], p[1])
2015-02-18 18:34:03 +01:00
if par then
param2s[p] = par
end
2015-02-18 18:34:03 +01:00
nodes[p] = c.nether_tree
end
2017-12-25 21:22:32 +01:00
for i,par2 in pairs(trunk_corners) do
local vi = area:indexp(pos_from_hash(i))
nodes[vi] = c.nether_tree_corner
2017-12-25 21:22:32 +01:00
param2s[vi] = par2
2015-02-18 18:34:03 +01:00
end
manip:set_data(nodes)
manip:set_param2_data(param2s)
manip:write_to_map()
local spam = 2
if generated then
spam = 3
end
nether:inform("a nether tree with "..trunk_count.." branch trunk nodes grew at ("..pos.x.."|"..pos.y.."|"..pos.z..")", spam, t1)
2015-02-18 18:34:03 +01:00
if not generated then
local t1 = os.clock()
manip:update_map()
nether:inform("map updated", spam, t1)
2012-04-19 01:42:46 +02:00
end
2012-04-19 00:11:38 +02:00
end
2015-02-18 18:34:03 +01:00
--abms
minetest.register_abm({
nodenames = {"nether:sapling"},
neighbors = {"nether:blood_top"},
interval = 20,
chance = 8,
action = function(pos)
local under = {x=pos.x, y=pos.y-1, z=pos.z}
if minetest.get_node_light(pos) < 4
and minetest.get_node({x=pos.x, y=pos.y+1, z=pos.z}).name == "air"
and minetest.get_node(under).name == "nether:blood_top" then
nether.grow_netherstructure(under)
2012-04-19 00:11:38 +02:00
end
end
2015-02-18 18:34:03 +01:00
})
2012-04-19 00:11:38 +02:00
2015-02-18 18:34:03 +01:00
minetest.register_abm({
nodenames = {"nether:tree_sapling"},
neighbors = {"group:nether_dirt"},
interval = abm_tree_interval,
chance = abm_tree_chance,
2015-02-18 18:34:03 +01:00
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
local udata = minetest.registered_nodes[minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z}).name]
if udata
and udata.groups
and udata.groups.nether_dirt then
nether.grow_tree(pos)
2012-04-19 00:11:38 +02:00
end
end
end
2015-02-18 18:34:03 +01:00
})
2012-04-19 00:11:38 +02:00
2015-02-18 18:34:03 +01:00
minetest.register_abm({
nodenames = {"nether:netherrack_soil"},
neighbors = {"air"},
interval = 20,
chance = 20,
action = function(pos, node)
local par2 = node.param2
if par2 == 0 then
return
2012-04-19 00:11:38 +02:00
end
2015-02-18 18:34:03 +01:00
pos.y = pos.y+1
if (minetest.get_node_light(pos) or 16) > 7 then --mushrooms grow at dark places
return
2012-04-19 00:11:38 +02:00
end
2015-02-18 18:34:03 +01:00
if minetest.get_node(pos).name == "air" then
minetest.set_node(pos, {name="riesenpilz:nether_shroom"})
pos.y = pos.y-1
minetest.set_node(pos, {name="nether:netherrack_soil", param2=par2-1})
2012-04-19 00:11:38 +02:00
end
end
2015-02-18 18:34:03 +01:00
})
2012-04-19 00:11:38 +02:00
2015-02-18 18:34:03 +01:00
local function grass_allowed(pos)
local nd = minetest.get_node(pos).name
if nd == "air" then
return true
end
if nd == "ignore" then
return 0
end
local data = minetest.registered_nodes[nd]
local drawtype = data.drawtype
if drawtype
and drawtype ~= "normal"
and drawtype ~= "liquid"
and drawtype ~= "flowingliquid" then
return true
end
local light = data.light_source
if light
and light > 0 then
return true
end
2015-02-18 18:34:03 +01:00
return false
end
2015-02-18 18:34:03 +01:00
minetest.register_abm({
nodenames = {"nether:dirt"},
interval = 20,
chance = 9,
action = function(pos)
local allowed = grass_allowed({x=pos.x, y=pos.y+1, z=pos.z})
if allowed == 0 then
return
end
if allowed then
minetest.set_node(pos, {name="nether:dirt_top"})
end
end
2015-02-18 18:34:03 +01:00
})
2012-04-19 00:11:38 +02:00
minetest.register_abm({
2015-02-18 18:34:03 +01:00
nodenames = {"nether:dirt_top"},
interval = 30,
chance = 9,
action = function(pos)
2015-02-18 18:34:03 +01:00
local allowed = grass_allowed({x=pos.x, y=pos.y+1, z=pos.z})
if allowed == 0 then
return
end
if not allowed then
minetest.set_node(pos, {name="nether:dirt"})
end
2012-04-19 00:11:38 +02:00
end
})
2015-02-18 18:34:03 +01:00
minetest.register_privilege("nether", "Allows sending players to nether and extracting them")
2012-04-19 00:11:38 +02:00
2015-02-18 18:34:03 +01:00
dofile(path.."/crafting.lua")
dofile(path.."/portal.lua")
dofile(path.."/guide.lua")
2015-08-05 10:35:32 +02:00
local time = math.floor(tonumber(os.clock()-load_time_start)*100+0.5)/100
local msg = "[nether] loaded after ca. "..time
if time > 0.05 then
print(msg)
else
minetest.log("info", msg)
end