nether-pack/nether/init.lua
2014-04-18 22:02:24 +02:00

1059 lines
30 KiB
Lua

-- 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!
--== EDITABLE OPTIONS ==--
-- Depth of the nether
NETHER_DEPTH = -20000
-- Height of the nether (bottom of the nether is NETHER_DEPTH - NETHER_HEIGHT)
NETHER_HEIGHT = 30
-- Maximum amount of randomness in the map generation
NETHER_RANDOM = 2
-- Frequency of Glowstone on the "roof" of the Nether (higher is less frequent)
GLOWSTONE_FREQ_ROOF = 500
-- Frequency of Glowstone on lava (higher is less frequent)
GLOWSTONE_FREQ_LAVA = 2
-- Frequency of lava (higher is less frequent)
LAVA_FREQ = 100
-- Maximum height of lava
LAVA_HEIGHT = 2
NETHER_TREE_FREQ = 350
NETHER_SHROOM_FREQ = 100
-- Height of nether trees
NETHER_TREESIZE = 2
-- Frequency of apples in a nether tree (higher is less frequent)
NETHER_APPLE_FREQ = 5
-- Frequency of healing apples in a nether tree (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)
NETHER_PORTAL = {
-- Floor 1
{pos={x=0,y=0,z=0}, block="default:obsidian"},
{pos={x=1,y=0,z=0}, block="default:obsidian"},
{pos={x=2,y=0,z=0}, block="default:obsidian"},
{pos={x=3,y=0,z=0}, block="default:obsidian"},
{pos={x=0,y=0,z=1}, block="default:obsidian"},
{pos={x=1,y=0,z=1}, block="default:obsidian"},
{pos={x=2,y=0,z=1}, block="default:obsidian"},
{pos={x=3,y=0,z=1}, block="default:obsidian"},
{pos={x=0,y=0,z=-1}, block="default:obsidian"},
{pos={x=1,y=0,z=-1}, block="default:obsidian"},
{pos={x=2,y=0,z=-1}, block="default:obsidian"},
{pos={x=3,y=0,z=-1}, block="default:obsidian"},
-- Floor 2
{pos={x=0,y=1,z=0}, block="default:obsidian"},
{pos={x=1,y=1,z=0}, block="nether:portal"},
{pos={x=2,y=1,z=0}, block="nether:portal"},
{pos={x=3,y=1,z=0}, block="default:obsidian"},
{pos={x=0,y=1,z=1}, block="default:obsidian"},
{pos={x=3,y=1,z=1}, block="default:obsidian"},
{pos={x=0,y=1,z=-1}, block="default:obsidian"},
{pos={x=3,y=1,z=-1}, block="default:obsidian"},
-- Floor 3
{pos={x=0,y=2,z=0}, block="default:obsidian"},
{pos={x=1,y=2,z=0}, block="nether:portal"},
{pos={x=2,y=2,z=0}, block="nether:portal"},
{pos={x=3,y=2,z=0}, block="default:obsidian"},
{pos={x=0,y=2,z=1}, block="default:obsidian"},
{pos={x=3,y=2,z=1}, block="default:obsidian"},
{pos={x=0,y=2,z=-1}, block="default:obsidian"},
{pos={x=3,y=2,z=-1}, block="default:obsidian"},
-- Floor 4
{pos={x=0,y=3,z=0}, block="default:obsidian"},
{pos={x=1,y=3,z=0}, block="nether:portal"},
{pos={x=2,y=3,z=0}, block="nether:portal"},
{pos={x=3,y=3,z=0}, block="default:obsidian"},
{pos={x=0,y=3,z=1}, block="default:obsidian"},
{pos={x=3,y=3,z=1}, block="default:obsidian"},
{pos={x=0,y=3,z=-1}, block="default:obsidian"},
{pos={x=3,y=3,z=-1}, block="default:obsidian"},
-- Floor 5
{pos={x=0,y=4,z=0}, block="default:obsidian"},
{pos={x=1,y=4,z=0}, block="default:obsidian"},
{pos={x=2,y=4,z=0}, block="default:obsidian"},
{pos={x=3,y=4,z=0}, block="default:obsidian"},
{pos={x=0,y=4,z=1}, block="default:obsidian"},
{pos={x=1,y=4,z=1}, block="default:obsidian"},
{pos={x=2,y=4,z=1}, block="default:obsidian"},
{pos={x=3,y=4,z=1}, block="default:obsidian"},
{pos={x=0,y=4,z=-1}, block="default:obsidian"},
{pos={x=1,y=4,z=-1}, block="default:obsidian"},
{pos={x=2,y=4,z=-1}, block="default:obsidian"},
{pos={x=3,y=4,z=-1}, block="default:obsidian"},
}
--== END OF EDITABLE OPTIONS ==--
local path = minetest.get_modpath("nether")
dofile(path.."/weird_mapgen_noise.lua")
local function dif(z1, z2)
if z1 < 0
and z2 < 0 then
z1,z2 = -z1,-z2
end
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},
{x=pos.x+width, y=pos.y+height, z=pos.z+width}
)
return VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
end
local function set_vm_data(manip, nodes, pos, t1, name)
manip:set_data(nodes)
manip:write_to_map()
print(string.format("[nether] "..name.." grew at ("..pos.x.."|"..pos.y.."|"..pos.z..") after ca. %.2fs", os.clock() - t1))
local t1 = os.clock()
manip:update_map()
print(string.format("[nether] map updated after ca. %.2fs", os.clock() - t1))
end
-- Generated variables
NETHER_BOTTOM = (NETHER_DEPTH - NETHER_HEIGHT)
NETHER_ROOF_ABS = (NETHER_DEPTH - NETHER_RANDOM)
--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 nether = {}
-- == General Utility Functions ==
-- Check if file exists
function nether:fileexists(file)
file = io.open(file, "r")
if file ~= nil then
file:close()
return true
else
return false
end
end
-- Simple "touch" function
function nether:touch(file)
if nether:fileexists(file) ~= true then
file = io.open(file, "w")
if file ~= nil then
file:write("")
file:close()
end
end
end
-- Print a message
function nether:printm(message)
print("[Nether] " .. message)
end
-- Print an error message
function nether:printerror(message)
nether:printm("Error! " .. message)
end
-- == Nether related stuff ==
-- Find if a position is inside the Nether
function nether:inside_nether(pos)
if pos.y >= NETHER_BOTTOM and pos.y <= NETHER_DEPTH then
return true
end
return false
end
--[[ Nether Lava
minetest.register_node("nether:lava_flowing", {
description = "Nether Lava (flowing)",
inventory_image = minetest.inventorycube("default_lava.png"),
drawtype = "flowingliquid",
tiles = {"default_lava.png"},
paramtype = "light",
light_source = LIGHT_MAX - 1,
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
liquidtype = "flowing",
liquid_alternative_flowing = "nether:lava_flowing",
liquid_alternative_source = "default:lava_source",
liquid_viscosity = LAVA_VISC,
damage_per_second = 4*2,
post_effect_color = {a=192, r=255, g=64, b=0},
special_materials = {
{image="default_lava.png", backface_culling=false},
{image="default_lava.png", backface_culling=true},
},
groups = {lava=3, liquid=2, hot=3},
})
minetest.register_node("nether:lava_source", {
description = "Nether Lava",
inventory_image = minetest.inventorycube("default_lava.png"),
drawtype = "liquid",
tiles = {"default_lava.png"},
paramtype = "light",
light_source = LIGHT_MAX - 1,
walkable = false,
pointable = false,
diggable = false,
buildable_to = true,
liquidtype = "source",
liquid_alternative_flowing = "nether:lava_flowing",
liquid_alternative_source = "default:lava_source",
liquid_viscosity = LAVA_VISC,
damage_per_second = 4*2,
post_effect_color = {a=192, r=255, g=64, b=0},
special_materials = {
-- New-style lava source material (mostly unused)
{image="default_lava.png", backface_culling=false},
},
groups = {lava=3, liquid=2, hot=3},
})]]
-- Netherrack
minetest.register_node("nether:netherrack", {
description = "Netherrack",
tiles = {"nether_netherrack.png"},
groups = {cracky=3, oddly_breakable_by_hand=3},
sounds = default.node_sound_stone_defaults(),
})
-- Netherbrick
minetest.register_node("nether:netherrack_brick", {
description = "Netherrack Brick",
tiles = {"nether_netherrack.png^nether_brick_shadow.png"},
groups = {cracky=3, oddly_breakable_by_hand=3},
sounds = default.node_sound_stone_defaults(),
})
-- Nether tree
minetest.register_node("nether:blood", {
description = "Nether Blood",
tiles = {"nether_blood.png"},
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=1},
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("nether:blood_top", {
description = "Nether Blood",
tiles = {"nether_blood_top.png", "nether_blood.png", "nether_blood.png^nether_blood_side.png"},
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=1},
sounds = default.node_sound_wood_defaults(),
})
minetest.register_node("nether:blood_stem", {
description = "Nether Blood Stem",
tiles = {"nether_blood_stem_top.png", "nether_blood_stem_top.png", "nether_blood_stem.png"},
groups = {snappy=2, choppy=2, oddly_breakable_by_hand=1},
sounds = default.node_sound_wood_defaults(),
})
--[[ Nether leaves
minetest.register_node("nether:leaves", {
description = "Nether Leaves",
drawtype = "allfaces_optional",
-- visual_scale = 1.189, --scale^2=sqrt(2)
tiles = {"nether_leaves.png"},
paramtype = "light",
groups = {snappy=3, leafdecay=2},
sounds = default.node_sound_leaves_defaults(),
})]]
-- Nether apple
minetest.register_node("nether:apple", {
description = "Nether Apple",
drawtype = "plantlike",
tiles = {"nether_apple.png"},
inventory_image = "nether_apple.png",
paramtype = "light",
sunlight_propagates = true,
walkable = false,
groups = {fleshy=3, dig_immediate=3},
on_use = minetest.item_eat(-4),
sounds = default.node_sound_defaults(),
})
-- Nether vine
minetest.register_node("nether:vine", {
description = "Nether vine",
walkable = false,
drop = '',
sunlight_propagates = true,
paramtype = "light",
tiles = { "nether_vine.png" },
drawtype = "plantlike",
inventory_image = "nether_vine.png",
groups = { snappy = 3,flammable=2 },
sounds = default.node_sound_leaves_defaults(),
after_dig_node = function(pos)
local p = {x=pos.x, y=pos.y-1, z=pos.z}
local vine = "nether:vine"
while minetest.get_node(p).name == vine do
minetest.remove_node(p)
p.y = p.y-1
end
end
})
-- Nether torch
minetest.register_node("nether:torch", {
description = "Nether Torch",
drawtype = "torchlike",
tiles = {"nether_torch_on_floor.png", "nether_torch_on_ceiling.png", "nether_torch.png"},
inventory_image = "nether_torch_on_floor.png",
wield_image = "nether_torch_on_floor.png",
paramtype = "light",
paramtype2 = "wallmounted",
sunlight_propagates = true,
walkable = false,
light_source = LIGHT_MAX - 1,
selection_box = {
type = "wallmounted",
wall_top = {-0.1, 0.5-0.6, -0.1, 0.1, 0.5, 0.1},
wall_bottom = {-0.1, -0.5, -0.1, 0.1, -0.5+0.6, 0.1},
wall_side = {-0.5, -0.3, -0.1, -0.5+0.3, 0.3, 0.1},
},
groups = {choppy=2, dig_immediate=3},
legacy_wallmounted = true,
sounds = default.node_sound_defaults(),
})
-- Nether Pearl
minetest.register_craftitem("nether:pearl", {
description = "Nether Pearl",
wield_image = "nether_pearl.png",
inventory_image = "nether_pearl.png",
visual = "sprite",
physical = true,
textures = {"nether_pearl.png"},
})
local c_air = minetest.get_content_id("air")
local c_netherrack = minetest.get_content_id("nether:netherrack")
local c_netherrack_brick = minetest.get_content_id("nether:netherrack_brick")
local c_glowstone = minetest.get_content_id("glow:stone") --https://github.com/Zeg9/minetest-glow
local c_lava = minetest.get_content_id("default:lava_source")
local c_nether_shroom = minetest.get_content_id("riesenpilz:nether_shroom")
local c_nether_vine = minetest.get_content_id("nether:vine")
local function return_nether_ore(glowstone)
if glowstone
and pr:next(0,GLOWSTONE_FREQ_ROOF) == 1 then
return c_glowstone
end
return c_netherrack
end
local info = true
local trees_enabled = true
local vine_maxlength = math.floor(NETHER_HEIGHT/4+0.5)
-- Create the Nether
minetest.register_on_generated(function(minp, maxp, seed)
if not (maxp.y >= NETHER_BOTTOM-100 and minp.y <= NETHER_DEPTH+100) then --avoid big map generation
return
end
local addpos = {}
if info then
t1 = os.clock()
local geninfo = "[nether] generates at: x=["..minp.x.."; "..maxp.x.."]; y=["..minp.y.."; "..maxp.y.."]; z=["..minp.z.."; "..maxp.z.."]"
print(geninfo)
minetest.chat_send_all(geninfo)
end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
pr = PseudoRandom(seed+33)
local tab,num = {},1
local num2 = 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)
local tab2 = nether_weird_noise(minp, pymg, 20, 8)
for z=minp.z, maxp.z do
for x=minp.x, maxp.x do
local r_tree = pr:next(1,NETHER_TREE_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 test = perlin1:get2d({x=x, y=z})+1
local test2 = perlin2:get2d({x=x, y=z})
local test3 = math.abs(perlin3:get2d({x=x, y=z}))
local t = math.floor(test*3+0.5)
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_DEPTH-pr:next(0,NETHER_RANDOM)+t
local py_h = tab2[num2].y
num2 = num2+1
for y=minp.y, maxp.y, 1 do
local p_addpos = area:index(x, y, z)
--if py_h >= maxp.y-4 then
if y == py_h then
data[p_addpos] = c_netherrack_brick
--[[else
data[p_addpos] = c_air
end]]
elseif data[p_addpos] ~= c_air then
if y <= NETHER_BOTTOM then
if y <= bottom then
data[p_addpos] = return_nether_ore(1)
else
data[p_addpos] = c_lava
end
elseif r_tree == 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[p_addpos] = c_lava
else
data[p_addpos] = return_nether_ore(0)
end
elseif r_shroom == 1
and r_tree ~= 1
and y == bottom+1 then
data[p_addpos] = c_nether_shroom
elseif (y == top and r_glowstone == 1) then
data[p_addpos] = c_glowstone
elseif y >= top then
data[p_addpos] = return_nether_ore(1)
elseif y <= top-1
and generate_vine
and y >= top-r_vine_length then
data[p_addpos] = c_nether_vine
else
data[p_addpos] = c_air
end
end
-- d_p_addpos = data[p_addpos]
end
end
end
vm:set_data(data)
-- vm:set_lighting(12)
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
if trees_enabled then --Trees:
for _,v in ipairs(tab) do
nether:grow_nethertree(v)
end
end
--[[ We don't want the Throne of Hades to get regenerated (especially since it will screw up portals)
if (minp.x <= HADES_THRONE_STARTPOS_ABS.x)
and (maxp.x >= HADES_THRONE_STARTPOS_ABS.x)
and (minp.y <= HADES_THRONE_STARTPOS_ABS.y)
and (maxp.y >= HADES_THRONE_STARTPOS_ABS.y)
and (minp.z <= HADES_THRONE_STARTPOS_ABS.z)
and (maxp.z >= HADES_THRONE_STARTPOS_ABS.z)
and (nether:fileexists(HADES_THRONE_GENERATED) == false) then
-- Pass 3: Make way for the Throne of Hades!
for x=(HADES_THRONE_STARTPOS_ABS.x - 1), (HADES_THRONE_ENDPOS_ABS.x + 1), 1 do
for z=(HADES_THRONE_STARTPOS_ABS.z - 1), (HADES_THRONE_ENDPOS_ABS.z + 1), 1 do
-- Notice I did not put a -1 for the beginning. This is because we don't want the throne to float
for y=HADES_THRONE_STARTPOS_ABS.y, (HADES_THRONE_ENDPOS_ABS.y + 1), 1 do
addpos = {x=x, y=y, z=z}
minetest.add_node(addpos, {name="air"})
end
end
end
-- Pass 4: Throne of Hades
for i,v in ipairs(HADES_THRONE_ABS) do
if v.portalblock == true then
NETHER_PORTALS_FROM_NETHER[table.getn(NETHER_PORTALS_FROM_NETHER)+1] = v.pos
nether:save_portal_from_nether(v.pos)
nether:createportal(v.pos)
else
minetest.add_node(v.pos, {name=v.block})
end
end
nether:touch(HADES_THRONE_GENERATED)
end]]
if info then
local geninfo = string.format("[nether] done after: %.2fs", os.clock() - t1)
print(geninfo)
minetest.chat_send_all(geninfo)
end
end)
--[[minetest.register_on_generated(function(minp, maxp, seed)
if minp.y <= 99 then
return
end
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local data = vm:get_data()
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
local perlin1 = minetest.get_perlin(13,3, 0.5, 50) --Get map specific perlin
local perlin2 = minetest.get_perlin(133,3, 0.5, 10)
for x=minp.x, maxp.x, 1 do
for z=minp.z, maxp.z, 1 do
local test = perlin1:get2d({x=x, y=z})+1
local test2 = perlin2:get2d({x=x, y=z})
-- print(test)
if test2 < 0 then
h = 200+math.floor(test2*3+0.5)
else
h = 203+math.floor(test*3+0.5)
end
for y=minp.y, maxp.y, 1 do
p_addpos = area:index(x, y, z)
if y <= h then
data[p_addpos] = c_netherrack
elseif y <= 201 then
data[p_addpos] = c_lava
end
end
end
end
vm:set_data(data)
--vm:set_lighting({day=0, night=0})
vm:calc_lighting()
vm:update_liquids()
vm:write_to_map()
end)]]
-- Return the name of the node below a position
function nether:nodebelow(pos)
return minetest.get_node({x=pos.x, y=(pos.y-1), z=pos.z}).name
end
-- Check if we can add a "sticky" node (i.e. it has to stick to something else, or else it won't be added)
-- This is largely based on Gilli's code
function nether:can_add_sticky_node(pos)
local objname
for x = -1, 1 do
for y = -1, 1 do
for z = -1, 1 do
local p = {x=pos.x+x, y=pos.y+y, z=pos.z+z}
local n = minetest.get_node(p)
objname = n.name
if minetest.registered_nodes[objname].walkable == true then
return true
end
end
end
end
return false
end
-- Add a "sticky" node
function nether:add_sticky_node(pos, opts)
if nether:can_add_sticky_node(pos) == true then
minetest.add_node(pos, opts)
return true
else
return false
end
end
local nether_c_blood = minetest.get_content_id("nether:blood")
local nether_c_blood_top = minetest.get_content_id("nether:blood_top")
local nether_c_blood_stem = minetest.get_content_id("nether:blood_stem")
local nether_c_apple = minetest.get_content_id("default:apple")
local nether_c_nether_apple = minetest.get_content_id("nether:apple")
function nether:grow_nethertree(pos)
local t1 = os.clock()
local height = 6
local manip = minetest.get_voxel_manip()
local area = r_area(manip, 2, height, pos)
local nodes = manip:get_data()
for i = 0, height-1 do
nodes[area:index(pos.x, pos.y+i, pos.z)] = nether_c_blood_stem
end
for i = -1,1 do
for j = -1,1 do
nodes[area:index(pos.x+i, pos.y+height, pos.z+j)] = nether_c_blood_top
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}
local udat = nether_c_blood_top
if math.random(2) == 1 then
nodes[area:index(p1[1], p1[2], p1[3])] = nether_c_blood_top
nodes[area:index(p2[1], p2[2], p2[3])] = nether_c_blood_top
udat = nether_c_blood
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
nodes[area:index(p[1], p[2], p[3])] = nether_c_nether_apple
elseif math.random(10) == 1 then
nodes[area:index(p[1], p[2], p[3])] = nether_c_apple
end
end
end
end
set_vm_data(manip, nodes, pos, t1, "blood")
end
--[[ Create a nether tree
function nether:grow_nethertree(pos)
--TRUNK
pos.y=pos.y+1
local trunkpos={x=pos.x, z=pos.z}
for y=pos.y, pos.y+4+math.random(2) do
trunkpos.y=y
minetest.add_node(trunkpos, {name="nether:tree"})
end
--LEAVES
local leafpos={}
for x=(trunkpos.x-NETHER_TREESIZE), (trunkpos.x+NETHER_TREESIZE), 1 do
for y=(trunkpos.y-NETHER_TREESIZE), (trunkpos.y+NETHER_TREESIZE), 1 do
for z=(trunkpos.z-NETHER_TREESIZE), (trunkpos.z+NETHER_TREESIZE), 1 do
if (x-trunkpos.x)*(x-trunkpos.x)
+(y-trunkpos.y)*(y-trunkpos.y)
+(z-trunkpos.z)*(z-trunkpos.z)
<= NETHER_TREESIZE*NETHER_TREESIZE + NETHER_TREESIZE then
leafpos={x=x, y=y, z=z}
if minetest.get_node(leafpos).name=="air" then
if math.random(NETHER_APPLE_FREQ) == 1 then
if math.random(NETHER_HEAL_APPLE_FREQ) == 1 then
minetest.add_node(leafpos, {name="default:apple"})
else
minetest.add_node(leafpos, {name="nether:apple"})
end
else
minetest.add_node(leafpos, {name="nether:leaves"})
end
end
end
end
end
end
end]]
-- == PORTAL RELATED STUFF ==
NETHER_PORTALS_TO_NETHER = {}
NETHER_PORTALS_FROM_NETHER = {}
NETHER_PORTALS_TO_NETHER_FILE = minetest.get_worldpath() .. "/portalstonether.txt"
NETHER_PORTALS_FROM_NETHER_FILE = minetest.get_worldpath() .. "/portalsfromnether.txt"
-- Count the number of times a position appears in a table
function table_count(tt, item)
local count
count = 0
for ii,xx in pairs(tt) do
if (item.x == xx.x) and (item.y == xx.y) and (item.z == xx.z) then
count = count + 1
end
end
return count
end
-- Remove duplicate positions from table
function table_unique(tt)
local newtable
newtable = {}
for ii,xx in ipairs(tt) do
if(table_count(newtable, xx) == 0) then
newtable[#newtable+1] = xx
end
end
return newtable
end
-- Copied from neko259 with a few minor edits from lkjoel
function split(pString, pPattern)
local Table = {}
local fpat = "(.-)" .. pPattern
local last_end = 1
local s, e, cap = pString:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(Table,cap)
end
last_end = e+1
s, e, cap = pString:find(fpat, last_end)
end
if last_end <= #pString then
cap = pString:sub(last_end)
table.insert(Table, cap)
end
return Table
end
-- Save a portal to nether
function nether:save_portal_to_nether(pos)
local file = io.open(NETHER_PORTALS_TO_NETHER_FILE, "a")
if file ~= nil then
file:write("x" .. pos.x .. "\ny" .. pos.y .. "\nz" .. pos.z .. "\np", "\n")
file:close()
else
nether:printerror("Cannot write portal to file!")
end
end
-- Save all nether portals
function nether:save_portals_to_nether()
local array2 = NETHER_PORTALS_TO_NETHER
NETHER_PORTALS_TO_NETHER = table_unique(array2)
file = io.open(NETHER_PORTALS_TO_NETHER_FILE, "w")
if file ~= nil then
file:write("")
file:close()
for i,v in ipairs(NETHER_PORTALS_TO_NETHER) do
nether:save_portal_to_nether(v)
end
else
nether:printerror("Cannot create portal file!")
end
end
-- Save a portal from nether
function nether:save_portal_from_nether(pos)
local file = io.open(NETHER_PORTALS_FROM_NETHER_FILE, "a")
if file ~= nil then
file:write("x" .. pos.x .. "\ny" .. pos.y .. "\nz" .. pos.z .. "\np", "\n")
file:close()
else
nether:printerror("Cannot write portal to file!")
end
end
-- Save all portals from nether
function nether:save_portals_from_nether()
local array2 = NETHER_PORTALS_FROM_NETHER
NETHER_PORTALS_FROM_NETHER = table_unique(array2)
file = io.open(NETHER_PORTALS_FROM_NETHER_FILE, "w")
if file ~= nil then
file:write("")
file:close()
for i,v in ipairs(NETHER_PORTALS_FROM_NETHER) do
nether:save_portal_from_nether(v)
end
else
nether:printerror("Cannot create portal file!")
end
end
-- Read portals to nether
function nether:read_portals_to_nether()
local array = {}
local array2 = {}
local file = io.open(NETHER_PORTALS_TO_NETHER_FILE, "r")
if file ~= nil then
for line in io.lines(NETHER_PORTALS_TO_NETHER_FILE) do
if not (line == "" or line == nil) then
if line:sub(1, 1) == "p" then
array2[table.getn(array2)+1] = array
elseif line:sub(1, 1) == "x" then
array.x = tonumber(split(line, "x")[1])
elseif line:sub(1, 1) == "y" then
array.y = tonumber(split(line, "y")[1])
elseif line:sub(1, 1) == "z" then
array.z = tonumber(split(line, "z")[1])
end
end
end
else
file = io.open(NETHER_PORTALS_TO_NETHER_FILE, "w")
if file ~= nil then
file:write("")
file:close()
else
nether:printerror("Cannot create portal file!")
end
end
NETHER_PORTALS_TO_NETHER = table_unique(array2)
end
-- Read portals from nether
function nether:read_portals_from_nether()
local array = {}
local array2 = {}
local file = io.open(NETHER_PORTALS_FROM_NETHER_FILE, "r")
if file ~= nil then
for line in io.lines(NETHER_PORTALS_FROM_NETHER_FILE) do
if not (line == "" or line == nil) then
if line:sub(1, 1) == "p" then
array2[table.getn(array2)+1] = array
elseif line:sub(1, 1) == "x" then
array.x = tonumber(split(line, "x")[1])
elseif line:sub(1, 1) == "y" then
array.y = tonumber(split(line, "y")[1])
elseif line:sub(1, 1) == "z" then
array.z = tonumber(split(line, "z")[1])
end
end
end
else
file = io.open(NETHER_PORTALS_FROM_NETHER_FILE, "w")
if file ~= nil then
file:write("")
file:close()
else
nether:printerror("Cannot create portal file!")
end
end
NETHER_PORTALS_FROM_NETHER = table_unique(array2)
end
nether:read_portals_to_nether()
nether:read_portals_from_nether()
-- Teleport the player
function nether:teleport_player(from_nether, player)
local randomportal = 1
local coin = math.floor(math.random(0, 1))
if coin == 0 then
coin = -1
else
coin = 1
end
local coin2 = math.floor(math.random(1, 2))
local num = 1
local forgetit = false
if from_nether == true then
num = table.getn(NETHER_PORTALS_TO_NETHER)
if num == 1 then
randomportal = 1
elseif num < 1 then
forgetit = true
teleportpos = NETHER_SPAWNPOS_ABS
else
randomportal = math.floor(math.random(1, num))
end
if forgetit == false then
portalpos = NETHER_PORTALS_TO_NETHER[randomportal]
end
else
num = table.getn(NETHER_PORTALS_FROM_NETHER)
if num == 1 then
randomportal = 1
elseif num < 1 then
forgetit = true
teleportpos = NETHER_SPAWNPOS_ABS
else
randomportal = math.floor(math.random(1, num))
end
if forgetit == false then
portalpos = NETHER_PORTALS_FROM_NETHER[randomportal]
end
end
if forgetit == false then
teleportpos = {x=portalpos.x + coin2, y=portalpos.y + 1, z=portalpos.z + coin}
end
player:setpos(teleportpos)
end
-- Creates a portal
function nether:createportal(pos)
local currx
local curry
local currz
local currpos = {}
for i,v in ipairs(NETHER_PORTAL) do
currx = v.pos.x + pos.x
curry = v.pos.y + pos.y
currz = v.pos.z + pos.z
currpos = {x=currx, y=curry, z=currz}
minetest.add_node(currpos, {name=v.block})
end
end
-- Portal Creator
minetest.register_node("nether:portal_creator", {
tiles = {"nether_portal_creator.png"},
description = "Nether Portal Creator",
})
minetest.register_on_placenode(function(pos, node)
if node.name == "nether:portal_creator" then
if nether:inside_nether(pos) then
NETHER_PORTALS_FROM_NETHER[table.getn(NETHER_PORTALS_FROM_NETHER)+1] = pos
nether:save_portal_from_nether(pos)
else
NETHER_PORTALS_TO_NETHER[table.getn(NETHER_PORTALS_TO_NETHER)+1] = pos
nether:save_portal_to_nether(pos)
end
nether:createportal(pos)
end
nodeupdate(pos)
end)
minetest.register_abm({
nodenames = "nether:portal_creator",
interval = 1,
chance = 1,
action = function(pos)
nether:createportal(pos)
end
})
-- Portal Stuff
minetest.register_node("nether:portal", {
description = "Nether Portal",
drawtype = "glasslike",
tiles = {"nether_portal_stuff.png"},
inventory_image = "nether_portal_stuff.png",
wield_image = "nether_portal_stuff.png",
light_source = LIGHT_MAX - 2,
paramtype = "light",
sunlight_propagates = true,
use_texture_alpha = true,
walkable = false,
digable = false,
pointable = false,
legacy_wallmounted = false,
-- buildable_to = true,
drop = "",
groups = {not_in_creative_inventory=1},
post_effect_color = {a=200, r=50, g=0, b=60},
metadata_name = "generic"
})
minetest.register_abm({
nodenames = {"nether:portal"},
interval = 1,
chance = 1,
action = function(pos, node)
minetest.add_particlespawner(
32, --amount
4, --time
{x=pos.x-0.47, y=pos.y-0.5, z=pos.z-1}, --minpos
{x=pos.x+0.47, y=pos.y+0.34, z=pos.z+1}, --maxpos
{x=0, y=1, z=0}, --minvel
{x=0, y=2, z=0}, --maxvel
{x=-0.5,y=-3,z=-0.3}, --minacc
{x=0.5,y=-0.4,z=0.3}, --maxacc
1, --minexptime
2, --maxexptime
0.4, --minsize
3, --maxsize
true, --collisiondetection
"nether_portal_particle.png" --texture
)
local objs = minetest.get_objects_inside_radius(pos, 1)
if objs[1] ~= nil then
local nodemeta = minetest.get_meta(pos)
for _,obj in pairs(objs) do
local objpos = obj:getpos()
local objmeta = minetest.get_meta(objpos)
local objplayername = obj:get_player_name()
if objpos.y > pos.y-1
and objpos.y < pos.y
and objplayername ~= nil
and objplayername ~= "" then
local innether = nether:inside_nether(obj:getpos())
local objstring1 = objmeta:get_string("teleportingfromnether")
if innether
and (
objstring1 == ""
or objstring1 == nil
) then
objmeta:set_string("teleportingfromnether", "true")
objmeta:set_string("teleportingtonether", "")
nether:teleport_player(innether, obj)
return
end
local objstring2 = objmeta:get_string("teleportingtonether")
if not innether
and (
objstring2 == ""
or objstring2 == nil
) then
objmeta:set_string("teleportingtonether", "true")
objmeta:set_string("teleportingfromnether", "")
nether:teleport_player(innether, obj)
end
end
end
end
end,
})
-- CRAFTING DEFINITIONS
minetest.register_craft({
output = "nether:portal_creator",
recipe = {
{"default:obsidian", "default:obsidian", "default:obsidian"},
{"default:obsidian", "nether:pearl", "default:obsidian"},
{"default:obsidian", "default:obsidian", "default:obsidian"},
}
})
print("Nether mod loaded!")