[nether] Update
|
@ -18,4 +18,5 @@ If you got ideas or found bugs, please tell them to me.
|
|||
|
||||
|
||||
TODO:
|
||||
— find a way to get the perlin noise inside [-1; 1] or use another noise
|
||||
— find a way to get the perlin noise inside [-1; 1] or use another noise
|
||||
— add something containing items to that buildings
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 319 B After Width: | Height: | Size: 319 B |
Before Width: | Height: | Size: 452 B After Width: | Height: | Size: 452 B |
Before Width: | Height: | Size: 572 B After Width: | Height: | Size: 572 B |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 762 B |
Before Width: | Height: | Size: 574 B After Width: | Height: | Size: 574 B |
Before Width: | Height: | Size: 612 B After Width: | Height: | Size: 612 B |
|
@ -2,5 +2,6 @@ default
|
|||
glow
|
||||
riesenpilz
|
||||
stairs
|
||||
vector_extras
|
||||
fence_registration?
|
||||
watershed?
|
||||
|
|
|
@ -55,6 +55,9 @@ local mushroom_rarity = 80
|
|||
-- Frequency of trees in the nether forest (higher is less frequent)
|
||||
local tree_rarity = 200
|
||||
|
||||
local abm_tree_interval = 864
|
||||
local abm_tree_chance = 100
|
||||
|
||||
-- height of the nether generation's end
|
||||
nether.start = f_h_max+100
|
||||
|
||||
|
@ -690,6 +693,10 @@ function nether.grow_netherstructure(pos, generated)
|
|||
end
|
||||
|
||||
|
||||
local set = vector.set_data_to_pos
|
||||
local get = vector.get_data_from_pos
|
||||
local remove = vector.remove_data_from_pos
|
||||
|
||||
local function soft_node(id)
|
||||
return id == c.air or id == c.ignore
|
||||
end
|
||||
|
@ -699,7 +706,6 @@ local function update_minmax(min, max, p)
|
|||
max.x = math.max(max.x, p.x)
|
||||
min.z = math.min(min.z, p.z)
|
||||
max.z = math.max(max.z, p.z)
|
||||
return min, max
|
||||
end
|
||||
|
||||
local fruit_chances = {}
|
||||
|
@ -742,62 +748,69 @@ function nether.grow_tree(pos, generated)
|
|||
local trunks = {}
|
||||
local trunk_corners = {}
|
||||
local h_stem = math.random(h_stem_min, h_stem_max)
|
||||
local stems = {{x=pos.x, y=pos.y+h_stem, z=pos.z}}
|
||||
local fi
|
||||
while not fi do
|
||||
for n,p in pairs(stems) do
|
||||
local used_dirs = {}
|
||||
for _,dir in pairs(dirs) do
|
||||
if math.random(1,2) == 1 then
|
||||
table.insert(used_dirs, dir)
|
||||
end
|
||||
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
|
||||
end
|
||||
if not used_dirs[1] then
|
||||
local dir1 = math.random(4)
|
||||
local dir2 = math.random(3)
|
||||
if dir1 <= dir2 then
|
||||
dir2 = dir2+1
|
||||
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]
|
||||
trunks[x.." "..p.y.." "..z] = dir[3]
|
||||
end
|
||||
r = r+1
|
||||
p.x = p.x+r*dir[1]
|
||||
p.z = p.z+r*dir[2]
|
||||
trunk_corners[p.x.." "..p.y.." "..p.z] = dir[4] or dir[3]
|
||||
local h = math.random(h_arm_min, h_arm_max)
|
||||
for i = 1,h do
|
||||
trunks[p.x.." "..p.y+i.." "..p.z] = true
|
||||
end
|
||||
p.y = p.y+h
|
||||
table.insert(stems, p)
|
||||
end
|
||||
if p.y > pos.y+h_trunk_max then
|
||||
fi = true
|
||||
break
|
||||
end
|
||||
stems[n] = nil
|
||||
end
|
||||
if not used_dirs[1] then
|
||||
local dir1 = math.random(4)
|
||||
local dir2 = math.random(3)
|
||||
if dir1 <= dir2 then
|
||||
dir2 = dir2+1
|
||||
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]
|
||||
set(trunks, z,p.y,x, dir[3])
|
||||
end
|
||||
r = r+1
|
||||
p.x = p.x+r*dir[1]
|
||||
p.z = p.z+r*dir[2]
|
||||
set(trunk_corners, p.z,p.y,p.x, dir[4] or dir[3])
|
||||
local h = math.random(h_arm_min, h_arm_max)
|
||||
for i = 1,h do
|
||||
set(trunks, p.z,p.y+i,p.x, true)
|
||||
end
|
||||
p.y = p.y+h
|
||||
--n = #todo+1 -- caused small trees
|
||||
todo[#todo+1] = p
|
||||
end
|
||||
if p.y > pos.y+h_trunk_max then
|
||||
break
|
||||
end
|
||||
|
||||
n = n or next(todo)
|
||||
end
|
||||
local leaves = {}
|
||||
local fruits = {}
|
||||
local trunk_ps = {}
|
||||
local count = 0
|
||||
for n,par in pairs(trunks) do
|
||||
local p = {}
|
||||
p.x, p.y, p.z = unpack(string.split(n, " "))
|
||||
if par ~= true then
|
||||
p.par = par
|
||||
local ps, trmin, trmax, trunk_count = vector.get_data_pos_table(trunks)
|
||||
|
||||
update_minmax(min, max, trmin)
|
||||
update_minmax(min, max, trmax)
|
||||
|
||||
for _,d in pairs(ps) do
|
||||
if d[4] == true then
|
||||
d[4] = nil
|
||||
end
|
||||
table.insert(trunk_ps, p)
|
||||
trunk_ps[#trunk_ps+1] = d
|
||||
local pz, py, px = unpack(d)
|
||||
count = count+1
|
||||
if count > leaf_thickness then
|
||||
count = 0
|
||||
|
@ -805,18 +818,21 @@ function nether.grow_tree(pos, generated)
|
|||
local fruit_chance = fruit_chances[y]
|
||||
for z = -2,2 do
|
||||
for x = -2,2 do
|
||||
local dist = math.sqrt(x*x+y*y+z*z)
|
||||
if math.floor(dist) ~= 0
|
||||
and math.random(1, dist) == 1 then
|
||||
local pstr = p.x+x.." "..p.y+y.." "..p.z+z
|
||||
if not trunks[pstr] then
|
||||
if math.random(1, fruit_rarity) == 1
|
||||
and fruit_chance
|
||||
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
|
||||
if not get(trunks, z,y,x) then
|
||||
if fruit_chance
|
||||
and math.random(1, fruit_rarity) == 1
|
||||
and math.random(1, fruit_chance) == 1 then
|
||||
fruits[pstr] = true
|
||||
set(fruits, z,y,x, true)
|
||||
else
|
||||
leaves[pstr] = true
|
||||
set(leaves, z,y,x, true)
|
||||
end
|
||||
update_minmax(min, max, {x=x, z=z})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -825,37 +841,8 @@ function nether.grow_tree(pos, generated)
|
|||
end
|
||||
end
|
||||
|
||||
local leaf_ps = {}
|
||||
for n,_ in pairs(leaves) do
|
||||
local p = {}
|
||||
p.x, p.y, p.z = unpack(string.split(n, " "))
|
||||
table.insert(leaf_ps, p)
|
||||
min, max = update_minmax(min, max, p)
|
||||
end
|
||||
|
||||
for n,_ in pairs(trunks) do
|
||||
local p = {}
|
||||
p.x, _, p.z = unpack(string.split(n, " "))
|
||||
min, max = update_minmax(min, max, p)
|
||||
end
|
||||
|
||||
for i = -1,h_stem+1 do
|
||||
table.insert(trunk_ps, {x=pos.x, y=pos.y+i, z=pos.z, par=0})
|
||||
end
|
||||
|
||||
local trunk_corner_ps = {}
|
||||
for n,par in pairs(trunk_corners) do
|
||||
local p = {}
|
||||
p.x, p.y, p.z = unpack(string.split(n, " "))
|
||||
p.par = par
|
||||
table.insert(trunk_corner_ps, p)
|
||||
end
|
||||
|
||||
local fruit_ps = {}
|
||||
for n,_ in pairs(fruits) do
|
||||
local p = {}
|
||||
p.x, p.y, p.z = unpack(string.split(n, " "))
|
||||
table.insert(fruit_ps, p)
|
||||
trunk_ps[#trunk_ps+1] = {pos.z, pos.y+i, pos.x, 0} -- par 0 because of leaves
|
||||
end
|
||||
|
||||
local manip = minetest.get_voxel_manip()
|
||||
|
@ -864,8 +851,8 @@ function nether.grow_tree(pos, generated)
|
|||
local nodes = manip:get_data()
|
||||
local param2s = manip:get_param2_data()
|
||||
|
||||
for _,p in pairs(leaf_ps) do
|
||||
p = area:indexp(p)
|
||||
for _,p in pairs(vector.get_data_pos_table(leaves)) do
|
||||
p = area:index(p[3], p[2], p[1])
|
||||
if soft_node(nodes[p]) then
|
||||
nodes[p] = c.nether_leaves
|
||||
param2s[p] = math.random(0,179)
|
||||
|
@ -873,30 +860,28 @@ function nether.grow_tree(pos, generated)
|
|||
end
|
||||
end
|
||||
|
||||
for _,p in pairs(fruit_ps) do
|
||||
p = area:indexp(p)
|
||||
for _,p in pairs(vector.get_data_pos_table(fruits)) do
|
||||
p = area:index(p[3], p[2], p[1])
|
||||
if soft_node(nodes[p]) then
|
||||
nodes[p] = c.nether_apple
|
||||
end
|
||||
end
|
||||
|
||||
for _,p in pairs(trunk_ps) do
|
||||
local par = p.par
|
||||
p = area:indexp(p)
|
||||
local par = p[4]
|
||||
p = area:index(p[3], p[2], p[1])
|
||||
if par then
|
||||
param2s[p] = par
|
||||
end
|
||||
nodes[p] = c.nether_tree
|
||||
end
|
||||
|
||||
for _,p in pairs(trunk_corner_ps) do
|
||||
local par = p.par
|
||||
p = area:indexp(p)
|
||||
nodes[p] = c.nether_tree_corner
|
||||
param2s[p] = par
|
||||
for _,p in pairs(vector.get_data_pos_table(trunk_corners)) do
|
||||
local vi = area:index(p[3], p[2], p[1])
|
||||
nodes[vi] = c.nether_tree_corner
|
||||
param2s[vi] = p[4]
|
||||
end
|
||||
|
||||
--calculating took ca. 0.07 - 0.18 [s]
|
||||
manip:set_data(nodes)
|
||||
manip:set_param2_data(param2s)
|
||||
manip:write_to_map()
|
||||
|
@ -904,7 +889,7 @@ function nether.grow_tree(pos, generated)
|
|||
if generated then
|
||||
spam = 3
|
||||
end
|
||||
nether:inform("a nether tree grew at ("..pos.x.."|"..pos.y.."|"..pos.z..")", spam, t1)
|
||||
nether:inform("a nether tree with "..trunk_count.." branch trunk nodes grew at ("..pos.x.."|"..pos.y.."|"..pos.z..")", spam, t1)
|
||||
if not generated then
|
||||
local t1 = os.clock()
|
||||
manip:update_map()
|
||||
|
@ -933,8 +918,8 @@ minetest.register_abm({
|
|||
minetest.register_abm({
|
||||
nodenames = {"nether:tree_sapling"},
|
||||
neighbors = {"group:nether_dirt"},
|
||||
interval = 864,
|
||||
chance = 100,
|
||||
interval = abm_tree_interval,
|
||||
chance = 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
|
||||
|
|
|
@ -539,6 +539,7 @@ minetest.register_node("nether:leaves", {
|
|||
inventory_image = "nether_leaves.png",
|
||||
wield_image = "nether_leaves.png",
|
||||
paramtype = "light",
|
||||
paramtype2 = "degrotate",
|
||||
is_ground_content = false,
|
||||
groups = {snappy=3, leafdecay=3, leaves=1},
|
||||
drop = {
|
||||
|
|
|
@ -7,108 +7,192 @@ local function table_contains(t, v)
|
|||
return false
|
||||
end
|
||||
|
||||
local teleportball_player
|
||||
local creative = minetest.setting_getbool("creative_mode")
|
||||
local function throw_pearl(item, player)
|
||||
local playerpos = player:getpos()
|
||||
local obj = minetest.add_entity({x=playerpos.x,y=playerpos.y+1.625,z=playerpos.z}, "nether:pearl_entity")
|
||||
playerpos.y = playerpos.y+1.625
|
||||
local obj = minetest.add_entity(playerpos, "nether:pearl_entity")
|
||||
local dir = player:get_look_dir()
|
||||
obj:setvelocity({x=dir.x*30, y=dir.y*30, z=dir.z*30})
|
||||
obj:setvelocity(vector.multiply(dir, 30))
|
||||
obj:setacceleration({x=dir.x*-3, y=-dir.y^8*80-10, z=dir.z*-3})
|
||||
if not minetest.setting_getbool("creative_mode") then
|
||||
obj:get_luaentity().player = player:get_player_name()
|
||||
if not creative then
|
||||
item:take_item()
|
||||
return item
|
||||
end
|
||||
teleportball_player = player
|
||||
return item
|
||||
end
|
||||
|
||||
local ENTITY = {
|
||||
timer=0,
|
||||
local function get_node(pos)
|
||||
local name = minetest.get_node(pos).name
|
||||
if name ~= "ignore" then
|
||||
return name
|
||||
end
|
||||
minetest.get_voxel_manip():read_from_map(pos, pos)
|
||||
name = minetest.get_node_or_nil(pos)
|
||||
if not name then
|
||||
return
|
||||
end
|
||||
return name.name
|
||||
end
|
||||
|
||||
local softs = {}
|
||||
local function is_soft(pos)
|
||||
local name = get_node(pos)
|
||||
if not name then
|
||||
return false
|
||||
end
|
||||
local is_soft = softs[name]
|
||||
if is_soft ~= nil then
|
||||
return is_soft
|
||||
end
|
||||
if not minetest.registered_nodes[name] then
|
||||
softs[name] = false
|
||||
return false
|
||||
end
|
||||
is_soft = minetest.registered_nodes[name].walkable == false
|
||||
softs[name] = is_soft
|
||||
return is_soft
|
||||
end
|
||||
|
||||
-- teleports the player there if there's free space
|
||||
local function teleport_player(pos, player)
|
||||
if not is_soft(pos) then
|
||||
return false
|
||||
end
|
||||
if not is_soft({x=pos.x, y=pos.y+1, z=pos.z})
|
||||
and not is_soft({x=pos.x, y=pos.y-1, z=pos.z}) then
|
||||
return false
|
||||
end
|
||||
pos.y = pos.y+0.05
|
||||
player:moveto(pos)
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
local dg_ps = {}
|
||||
local function forceload(pos)
|
||||
dg_ps[#dg_ps+1] = pos
|
||||
minetest.forceload_block(pos)
|
||||
minetest.after(5, function(pos)
|
||||
minetest.forceload_free_block(pos)
|
||||
for i,p in pairs(dg_ps) do
|
||||
if vector.equals(p, pos) then
|
||||
dg_ps[i] = nil
|
||||
return
|
||||
end
|
||||
end
|
||||
end, pos)
|
||||
end
|
||||
minetest.register_on_shutdown(function()
|
||||
for _,p in pairs(dg_ps) do
|
||||
minetest.forceload_free_block(p)
|
||||
end
|
||||
end)--]]
|
||||
|
||||
minetest.register_entity("nether:pearl_entity", {
|
||||
collisionbox = {0,0,0,0,0,0}, --not pointable
|
||||
visual_size = {x=0.1, y=0.1},
|
||||
physical = false, -- Collides with things
|
||||
textures = {"nether_pearl.png"},
|
||||
lastpos={},
|
||||
player = "",
|
||||
}
|
||||
on_activate = function(self, staticdata)
|
||||
if not staticdata
|
||||
or staticdata == "" then
|
||||
return
|
||||
end
|
||||
local tmp = minetest.deserialize(staticdata)
|
||||
if not tmp then
|
||||
minetest.log("error", "[nether] pearl: invalid staticdata ")
|
||||
return
|
||||
end
|
||||
self.player = tmp.player
|
||||
end,
|
||||
get_staticdata = function(self)
|
||||
--forceload(vector.round(self.object:getpos()))
|
||||
return minetest.serialize({
|
||||
player = self.player,
|
||||
})
|
||||
end,
|
||||
timer = 0,
|
||||
on_step = function(self, dtime)
|
||||
self.timer = self.timer+dtime
|
||||
|
||||
local allowed_nodes = {"air", "default:water_source"}
|
||||
local function teleport_player(pos, player)
|
||||
local nd2 = minetest.get_node(pos).name
|
||||
pos.y = pos.y+1
|
||||
local nd3 = minetest.get_node(pos).name
|
||||
if table_contains(allowed_nodes, nd2)
|
||||
and table_contains(allowed_nodes, nd3) then
|
||||
pos.y = pos.y-1.4
|
||||
player:moveto(pos)
|
||||
pos.y = pos.y-0.6
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
--[[
|
||||
local delay = self.delay
|
||||
if delay < 0.1 then
|
||||
self.delay = delay+dtime
|
||||
return
|
||||
end
|
||||
self.delay = 0--]]
|
||||
|
||||
ENTITY.on_step = function(self, dtime)
|
||||
self.timer=self.timer+dtime
|
||||
if self.timer > 20 then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
local pos = self.object:getpos()
|
||||
local rpos = vector.round(pos)
|
||||
local lastpos = self.lastpos
|
||||
if not lastpos then
|
||||
self.lastpos = vector.new(rpos)
|
||||
return
|
||||
end
|
||||
if lastpos.x
|
||||
and vector.equals(vector.round(lastpos), rpos) then
|
||||
return
|
||||
end
|
||||
|
||||
local player = self.player
|
||||
if not player then
|
||||
minetest.log("error", "[nether] pearl: missing playername")
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
player = minetest.get_player_by_name(player)
|
||||
if not player then
|
||||
minetest.log("error", "[nether] pearl: missing player")
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
if not get_node(rpos) then
|
||||
minetest.log("error", "[nether] pearl: missing node")
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
self.lastpos = vector.new(pos)
|
||||
|
||||
--[[ local delay = self.delay
|
||||
if delay < 0.1 then
|
||||
self.delay = delay+dtime
|
||||
return
|
||||
end
|
||||
self.delay = 0]]
|
||||
local pos = self.object:getpos()
|
||||
local lastpos = self.lastpos
|
||||
if lastpos.x
|
||||
and vector.equals(vector.round(lastpos), vector.round(pos)) then
|
||||
return
|
||||
end
|
||||
local player = self.player
|
||||
if not player
|
||||
or player == "" then
|
||||
self.player = teleportball_player
|
||||
player = teleportball_player
|
||||
end
|
||||
if not player then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
if lastpos.x then --If there is no lastpos for some reason.
|
||||
local free, p = minetest.line_of_sight(lastpos, pos)
|
||||
if not free then
|
||||
local nd1 = minetest.get_node(p).name
|
||||
if not table_contains(allowed_nodes, nd1)
|
||||
and nd1 ~= "ignore" then
|
||||
self.object:remove()
|
||||
minetest.after(0, function(p) --minetest.after us used that the sound is played after the teleportation
|
||||
minetest.sound_play("nether_pearl", {pos=p, max_hear_distance=10})
|
||||
end, p)
|
||||
p.y = p.y+1
|
||||
if teleport_player(p, player) then
|
||||
if free then
|
||||
return
|
||||
end
|
||||
if is_soft(p) then
|
||||
return
|
||||
end
|
||||
self.object:remove()
|
||||
minetest.after(0, function(p) --minetest.after is used that the sound is played after the teleportation
|
||||
minetest.sound_play("nether_pearl", {pos=p, max_hear_distance=10})
|
||||
end, p)
|
||||
p.y = p.y+1
|
||||
if teleport_player(vector.new(p), player) then
|
||||
return
|
||||
end
|
||||
p.y = p.y-2
|
||||
for i = -1,1,2 do
|
||||
for _,j in pairs({{i, 0}, {0, i}}) do
|
||||
if teleport_player({x=p.x+j[1], y=p.y, z=p.z+j[2]}, player) then
|
||||
return
|
||||
end
|
||||
p.y = p.y-2
|
||||
for i = -1,1,2 do
|
||||
for _,j in pairs({{i, 0}, {0, i}}) do
|
||||
if teleport_player({x=p.x+j[1], y=p.y, z=p.z+j[2]}, player) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = -1,1,2 do
|
||||
for j = -1,1,2 do
|
||||
if teleport_player({x=p.x+j, y=p.y, z=p.z+i}, player) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = -1,1,2 do
|
||||
for j = -1,1,2 do
|
||||
if teleport_player({x=p.x+j, y=p.y, z=p.z+i}, player) then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if self.timer > 20 then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
self.lastpos = vector.new(pos)
|
||||
end
|
||||
|
||||
minetest.register_entity("nether:pearl_entity", ENTITY)
|
||||
})
|
||||
|
||||
minetest.override_item("nether:pearl", {on_use = throw_pearl})
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
--code copied from Pilzadam's nether mod and edited
|
||||
|
||||
-- kills the player if he uses PilzAdam portal
|
||||
local portal_target = nether.buildings+1
|
||||
local damage_enabled = minetest.setting_getbool("enable_damage")
|
||||
local nether_prisons = minetest.setting_getbool("enable_damage")
|
||||
local obsidian_portal_kills = nether_prisons and true
|
||||
local mclike_portal = false
|
||||
|
||||
local abm_allowed
|
||||
minetest.after(5, function()
|
||||
|
@ -17,12 +21,15 @@ table.icontains = table.icontains or function(t, v)
|
|||
end
|
||||
|
||||
local players_in_nether = {}
|
||||
local file = io.open(minetest.get_worldpath()..'/nether_players', "r")
|
||||
if file then
|
||||
local contents = file:read('*all')
|
||||
io.close(file)
|
||||
if contents then
|
||||
players_in_nether = string.split(contents, " ")
|
||||
-- only get info from file if nether prisons
|
||||
if nether_prisons then
|
||||
local file = io.open(minetest.get_worldpath()..'/nether_players', "r")
|
||||
if file then
|
||||
local contents = file:read('*all')
|
||||
io.close(file)
|
||||
if contents then
|
||||
players_in_nether = string.split(contents, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -37,7 +44,7 @@ local function save_nether_players()
|
|||
end
|
||||
|
||||
local update_background
|
||||
--if damage_enabled then
|
||||
--if nether_prisons then
|
||||
function update_background(player, down)
|
||||
if down then
|
||||
player:set_sky({r=15, g=0, b=0}, "plain")
|
||||
|
@ -49,16 +56,59 @@ local update_background
|
|||
-- function update_background()end
|
||||
--end
|
||||
|
||||
-- returns nodename if area is generated, else calls generation function
|
||||
local function generated_or_generate(pos)
|
||||
local name = minetest.get_node(pos).name
|
||||
if name ~= "ignore" then
|
||||
return name
|
||||
end
|
||||
minetest.get_voxel_manip():read_from_map(pos, pos)
|
||||
name = minetest.get_node_or_nil(pos)
|
||||
if not name then
|
||||
minetest.emerge_area(vector.subtract(pos, 80), vector.add(pos, 80))
|
||||
return false
|
||||
end
|
||||
return name.name
|
||||
end
|
||||
|
||||
-- where the player appears after dying
|
||||
local function get_player_died_target(player)
|
||||
local target = vector.add(player:getpos(), {x=math.random(-100,100), y=0, z=math.random(-100,100)})
|
||||
target.y = portal_target + math.random(4)
|
||||
return target
|
||||
end
|
||||
|
||||
-- used for obsidian portal
|
||||
local function obsidian_teleport(player, pname)
|
||||
minetest.chat_send_player(pname, "For any reason you arrived here. Type /nether_help to find out things like craft recipes.")
|
||||
if obsidian_portal_kills then
|
||||
player:set_hp(0)
|
||||
return true
|
||||
end
|
||||
if not mclike_portal then
|
||||
local target = vector.round(get_player_died_target(player))
|
||||
if generated_or_generate(target) then
|
||||
player:moveto(target)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- teleports players to nether or helps it
|
||||
function nether.player_to_nether(player, safe)
|
||||
local pname = player:get_player_name()
|
||||
if table.icontains(players_in_nether, pname) then
|
||||
return
|
||||
end
|
||||
table.insert(players_in_nether, pname)
|
||||
players_in_nether[#players_in_nether+1] = pname
|
||||
save_nether_players()
|
||||
if not safe then
|
||||
minetest.chat_send_player(pname, "For any reason you arrived here. Type /nether_help to find out things like craft recipes.")
|
||||
player:set_hp(0)
|
||||
if not nether_prisons then
|
||||
player:moveto(get_player_died_target(player))
|
||||
end
|
||||
end
|
||||
update_background(player, true)
|
||||
end
|
||||
|
@ -79,7 +129,6 @@ function nether.player_from_nether(player)
|
|||
end
|
||||
|
||||
|
||||
--if damage_enabled then
|
||||
local function player_exists(name)
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
if player:get_player_name() == name then
|
||||
|
@ -128,69 +177,95 @@ minetest.register_chatcommand("from_hell", {
|
|||
end
|
||||
minetest.chat_send_player(pname, "You are free now")
|
||||
player_from_nether(player)
|
||||
local pos_togo = {x = 0, y = 35, z = -7}
|
||||
if minetest.setting_getbool("static_spawnpoint") ~= nil then
|
||||
local stsp_conf = minetest.setting_get("static_spawnpoint")
|
||||
pos_togo = {x = stsp_conf:split(",")[1]+0,y = stsp_conf:split(",")[2]+0,z = stsp_conf:split(",")[3]+0}
|
||||
end
|
||||
player:moveto(pos_togo)
|
||||
return true
|
||||
local pos = player:getpos()
|
||||
player:moveto({x=pos.x, y=100, z=pos.z})
|
||||
return true, pname.." is now out of the nether."
|
||||
end
|
||||
})]]
|
||||
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
local pname = player:get_player_name()
|
||||
if not table.icontains(players_in_nether, pname) then
|
||||
return
|
||||
end
|
||||
local target = vector.add(player:getpos(), {x=math.random(-100,100), y=0, z=math.random(-100,100)})
|
||||
target.y = portal_target + math.random(4)
|
||||
player:moveto(target)
|
||||
minetest.after(0, function(pname, target)
|
||||
local player = minetest.get_player_by_name(pname)
|
||||
if player then
|
||||
player:moveto(target)
|
||||
end
|
||||
end, pname, target)
|
||||
return true
|
||||
end)
|
||||
|
||||
local function update_players()
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
if nether_prisons then
|
||||
-- randomly set player position when he/she dies in nether
|
||||
minetest.register_on_respawnplayer(function(player)
|
||||
local pname = player:get_player_name()
|
||||
local ppos = player:getpos()
|
||||
if table.icontains(players_in_nether, pname) then
|
||||
if ppos.y > nether.start then
|
||||
player:moveto({x=ppos.x, y=portal_target, z=ppos.z})
|
||||
update_background(player, true)
|
||||
--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport out of the nether."..
|
||||
if not table.icontains(players_in_nether, pname) then
|
||||
return
|
||||
end
|
||||
local target = get_player_died_target(player)
|
||||
player:moveto(target)
|
||||
minetest.after(0, function(pname, target)
|
||||
-- fixes respawn bug
|
||||
local player = minetest.get_player_by_name(pname)
|
||||
if player then
|
||||
player:moveto(target)
|
||||
end
|
||||
end, pname, target)
|
||||
return true
|
||||
end)
|
||||
|
||||
-- function for teleporting players where they belong to
|
||||
local function update_players()
|
||||
for _,player in pairs(minetest.get_connected_players()) do
|
||||
local pname = player:get_player_name()
|
||||
local ppos = player:getpos()
|
||||
if table.icontains(players_in_nether, pname) then
|
||||
if ppos.y > nether.start then
|
||||
player:moveto({x=ppos.x, y=portal_target, z=ppos.z})
|
||||
update_background(player, true)
|
||||
--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport out of the nether."..
|
||||
"\n2. Maybe the server lagged."..
|
||||
"\n3. please rejoin")]]
|
||||
end
|
||||
elseif ppos.y < nether.start then
|
||||
update_background(player)
|
||||
player:moveto({x=ppos.x, y=20, z=ppos.z})
|
||||
--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport to the nether."..
|
||||
"\n2. Maybe the server lagged."..
|
||||
"\n3. please rejoin")]]
|
||||
end
|
||||
elseif ppos.y < nether.start then
|
||||
update_background(player)
|
||||
player:moveto({x=ppos.x, y=20, z=ppos.z})
|
||||
--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport to the nether."..
|
||||
"\n2. Maybe the server lagged."..
|
||||
"\n3. please rejoin")]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function tick()
|
||||
update_players()
|
||||
minetest.after(2, tick)
|
||||
end
|
||||
tick()
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(0, function(player)
|
||||
if player:getpos().y < nether.start then
|
||||
update_background(player, true)
|
||||
-- fix wrong player positions
|
||||
local timer = 0 --doesn't work if the server lags
|
||||
minetest.register_globalstep(function(dtime)
|
||||
timer = timer + dtime;
|
||||
if timer >= 2 then
|
||||
--minetest.after(1, update_players)
|
||||
update_players()
|
||||
timer = 0
|
||||
end
|
||||
end, player)
|
||||
end)
|
||||
end)
|
||||
|
||||
-- set background when player joins
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(0, function(player)
|
||||
if player:getpos().y < nether.start then
|
||||
update_background(player, true)
|
||||
end
|
||||
end, player)
|
||||
end)
|
||||
else
|
||||
-- test if player is in nether when he/she joins
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
minetest.after(0, function(player)
|
||||
if player:getpos().y < nether.start then
|
||||
if not table.icontains(players_in_nether, pname) then
|
||||
players_in_nether[#players_in_nether+1] = pname
|
||||
end
|
||||
return
|
||||
end
|
||||
for i,name in pairs(players_in_nether) do
|
||||
if name == pname then
|
||||
players_in_nether[i] = nil
|
||||
return
|
||||
end
|
||||
end
|
||||
end, player)
|
||||
end)
|
||||
end
|
||||
|
||||
-- removes the violet stuff from the obsidian portal
|
||||
local function remove_portal_essence(pos)
|
||||
for z = -1,1 do
|
||||
for y = -2,2 do
|
||||
|
@ -204,6 +279,50 @@ local function remove_portal_essence(pos)
|
|||
end
|
||||
end
|
||||
|
||||
-- change parts of the particledefinition instead of recreating it every time
|
||||
local particledef = {
|
||||
amount = 32,
|
||||
time = 4,
|
||||
minvel = {x=0, y=1, z=0},
|
||||
maxvel = {x=0, y=2, z=0},
|
||||
minacc = {x=-0.5,y=-3,z=-0.3},
|
||||
maxacc = {x=0.5,y=-0.4,z=0.3},
|
||||
minexptime = 1,
|
||||
maxexptime = 1,
|
||||
minsize = 0.4,
|
||||
maxsize = 3,
|
||||
collisiondetection = true,
|
||||
}
|
||||
|
||||
-- teleports player to neter (obsidian portal)
|
||||
local function obsi_teleport_player(player, pos, target)
|
||||
local pname = player:get_player_name()
|
||||
if table.icontains(players_in_nether, pname) then
|
||||
return
|
||||
end
|
||||
|
||||
local objpos = player:getpos()
|
||||
objpos.y = objpos.y+0.1 -- Fix some glitches at -8000
|
||||
if minetest.get_node(vector.round(objpos)).name ~= "nether:portal" then
|
||||
return
|
||||
end
|
||||
|
||||
if not obsidian_teleport(player, pname) then
|
||||
-- e.g. ungenerated area
|
||||
return
|
||||
end
|
||||
|
||||
players_in_nether[#players_in_nether+1] = pname
|
||||
save_nether_players()
|
||||
update_background(player, true)
|
||||
|
||||
remove_portal_essence(pos)
|
||||
|
||||
minetest.sound_play("nether_portal_usual", {to_player=pname, gain=1})
|
||||
--obj:setpos(target)
|
||||
end
|
||||
|
||||
-- abm for particles of the obsidian portal essence and for teleporting
|
||||
minetest.register_abm({
|
||||
nodenames = {"nether:portal"},
|
||||
interval = 1,
|
||||
|
@ -213,45 +332,16 @@ minetest.register_abm({
|
|||
if not abm_allowed then
|
||||
return
|
||||
end
|
||||
minetest.add_particlespawner({
|
||||
amount = 32,
|
||||
time = 4,
|
||||
minpos = {x=pos.x-0.25, y=pos.y-0.5, z=pos.z-0.25},
|
||||
maxpos = {x=pos.x+0.25, y=pos.y+0.34, z=pos.z+0.25},
|
||||
minvel = {x=0, y=1, z=0},
|
||||
maxvel = {x=0, y=2, z=0},
|
||||
minacc = {x=-0.5,y=-3,z=-0.3},
|
||||
maxacc = {x=0.5,y=-0.4,z=0.3},
|
||||
minexptime = 1,
|
||||
maxexptime = 1,
|
||||
minsize = 0.4,
|
||||
maxsize = 3,
|
||||
collisiondetection = true,
|
||||
texture = "nether_portal_particle.png^[transform"..math.random(0,7),
|
||||
})
|
||||
particledef.minpos = {x=pos.x-0.25, y=pos.y-0.5, z=pos.z-0.25}
|
||||
particledef.maxpos = {x=pos.x+0.25, y=pos.y+0.34, z=pos.z+0.25}
|
||||
particledef.texture = "nether_portal_particle.png^[transform"..math.random(0,7)
|
||||
minetest.add_particlespawner(particledef)
|
||||
for _,obj in pairs(minetest.get_objects_inside_radius(pos, 1)) do
|
||||
if obj:is_player() then
|
||||
local meta = minetest.get_meta(pos)
|
||||
local target = minetest.string_to_pos(meta:get_string("target"))
|
||||
if target then
|
||||
minetest.after(3, function(obj, pos, target)
|
||||
local pname = obj:get_player_name()
|
||||
if table.icontains(players_in_nether, pname) then
|
||||
return
|
||||
end
|
||||
local objpos = obj:getpos()
|
||||
objpos.y = objpos.y+0.1 -- Fix some glitches at -8000
|
||||
if minetest.get_node(vector.round(objpos)).name ~= "nether:portal" then
|
||||
return
|
||||
end
|
||||
|
||||
remove_portal_essence(pos)
|
||||
|
||||
minetest.sound_play("nether_portal_usual", {to_player=pname, gain=1})
|
||||
nether.player_to_nether(obj)
|
||||
--obj:setpos(target)
|
||||
|
||||
end, obj, pos, target)
|
||||
minetest.after(3, obsi_teleport_player, obj, pos, target)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -299,6 +389,7 @@ local function check_portal(p1, p2)
|
|||
return true
|
||||
end
|
||||
|
||||
-- tests if it's an obsidian portal
|
||||
local function is_portal(pos)
|
||||
for d=-3,3 do
|
||||
for y=-4,4 do
|
||||
|
@ -314,6 +405,15 @@ local function is_portal(pos)
|
|||
end
|
||||
end
|
||||
|
||||
-- put here the function for creating a second portal
|
||||
local create_second_portal
|
||||
if mclike_portal then
|
||||
function create_second_portal(target)
|
||||
-- change target here
|
||||
end
|
||||
end
|
||||
|
||||
-- adds the violet portal essence
|
||||
local function make_portal(pos)
|
||||
local p1, p2 = is_portal(pos)
|
||||
if not p1
|
||||
|
@ -322,7 +422,10 @@ local function make_portal(pos)
|
|||
return false
|
||||
end
|
||||
|
||||
if p1.y < nether.start then
|
||||
local in_nether = p1.y < nether.start
|
||||
|
||||
if in_nether
|
||||
and not mclike_portal then
|
||||
print("[nether] aborted, obsidian portals can't be used to get out")
|
||||
return
|
||||
end
|
||||
|
@ -350,7 +453,17 @@ local function make_portal(pos)
|
|||
|
||||
local target = {x=p1.x, y=p1.y, z=p1.z}
|
||||
target.x = target.x + 1
|
||||
target.y = portal_target + math.random(4)
|
||||
if in_nether then
|
||||
target.y = 0
|
||||
create_second_portal(target)
|
||||
else
|
||||
target.y = portal_target + math.random(4)
|
||||
end
|
||||
|
||||
if not generated_or_generate(target)
|
||||
and mclike_portal then
|
||||
return false
|
||||
end
|
||||
|
||||
for d=0,3 do
|
||||
for y=p1.y,p2.y do
|
||||
|
@ -373,6 +486,7 @@ local function make_portal(pos)
|
|||
return true
|
||||
end
|
||||
|
||||
-- destroy the portal when destroying obsidian
|
||||
minetest.override_item("default:obsidian", {
|
||||
on_destruct = function(pos)
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
@ -426,12 +540,13 @@ minetest.override_item("default:obsidian", {
|
|||
end
|
||||
})
|
||||
|
||||
-- override mese crystal fragment for making an obsidian portal
|
||||
minetest.after(0.1, function()
|
||||
minetest.override_item("default:mese_crystal_fragment", {
|
||||
on_place = function(stack, player, pt)
|
||||
if pt.under
|
||||
and minetest.get_node(pt.under).name == "default:obsidian" then
|
||||
print("[nether] tries to enable a portal")
|
||||
--print("[nether] tries to enable a portal")
|
||||
local done = make_portal(pt.under)
|
||||
if done then
|
||||
minetest.chat_send_player(
|
||||
|
@ -447,9 +562,9 @@ minetest.after(0.1, function()
|
|||
end
|
||||
})
|
||||
end)
|
||||
--end
|
||||
|
||||
|
||||
-- a not filled square
|
||||
vector.square = vector.square or
|
||||
function(r)
|
||||
local tab, n = {}, 1
|
||||
|
@ -464,20 +579,21 @@ function(r)
|
|||
return tab
|
||||
end
|
||||
|
||||
-- detects if it's a portal
|
||||
local function netherport(pos)
|
||||
local x, y, z = pos.x, pos.y, pos.z
|
||||
for _,i in ipairs({-1, 3}) do
|
||||
for _,i in pairs({-1, 3}) do
|
||||
if minetest.get_node({x=x, y=y+i, z=z}).name ~= "nether:white" then
|
||||
return
|
||||
end
|
||||
end
|
||||
for _,sn in ipairs(vector.square(1)) do
|
||||
for _,sn in pairs(vector.square(1)) do
|
||||
if minetest.get_node({x=x+sn[1], y=y-1, z=z+sn[2]}).name ~= "nether:netherrack"
|
||||
or minetest.get_node({x=x+sn[1], y=y+3, z=z+sn[2]}).name ~= "nether:blood_cooked" then
|
||||
return
|
||||
end
|
||||
end
|
||||
for _,sn in ipairs(vector.square(2)) do
|
||||
for _,sn in pairs(vector.square(2)) do
|
||||
if minetest.get_node({x=x+sn[1], y=y-1, z=z+sn[2]}).name ~= "nether:netherrack_black"
|
||||
or minetest.get_node({x=x+sn[1], y=y+3, z=z+sn[2]}).name ~= "nether:wood_empty" then
|
||||
return
|
||||
|
@ -520,6 +636,7 @@ local function set_portal(t, z,x, y)
|
|||
t[z][x] = y
|
||||
end
|
||||
|
||||
-- used when a player eats that fruit in a portal
|
||||
function nether_port(player, pos)
|
||||
if not player
|
||||
or not pos
|
||||
|
@ -532,17 +649,37 @@ function nether_port(player, pos)
|
|||
end
|
||||
minetest.sound_play("nether_teleporter", {to_player=player:get_player_name()}) --MFF crabman (5/09/2015) fix positional sound don't work to player
|
||||
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
|
||||
nether.player_from_nether(player)
|
||||
local pos_togo = {x = 0, y = 35, z = -7}
|
||||
if minetest.setting_getbool("static_spawnpoint") ~= nil then
|
||||
local stsp_conf = minetest.setting_get("static_spawnpoint")
|
||||
pos_togo = minetest.string_to_pos(stsp_conf)
|
||||
set_portal(known_portals_d, pos.z,pos.x, pos.y)
|
||||
player_from_nether(player)
|
||||
|
||||
local my = tonumber(meta:get_string("y"))
|
||||
local y = get_portal(known_portals_u, pos.z,pos.x)
|
||||
if y then
|
||||
if y ~= my then
|
||||
meta:set_string("y", y)
|
||||
end
|
||||
else
|
||||
y = my or 100
|
||||
end
|
||||
player:moveto(pos_togo)
|
||||
pos.y = y
|
||||
|
||||
player:moveto(pos)
|
||||
else
|
||||
set_portal(known_portals_u, pos.z,pos.x, pos.y)
|
||||
pos.y = get_portal(known_portals_d, pos.z,pos.x) or portal_target+math.random(4)
|
||||
|
||||
local my = tonumber(meta:get_string("y"))
|
||||
local y = get_portal(known_portals_d, pos.z,pos.x)
|
||||
if y then
|
||||
if y ~= my then
|
||||
meta:set_string("y", y)
|
||||
end
|
||||
else
|
||||
y = my or portal_target+math.random(4)
|
||||
end
|
||||
pos.y = y
|
||||
|
||||
player:moveto(pos)
|
||||
nether.player_to_nether(player, true)
|
||||
end
|
||||
|
|
BIN
mods/nether/nether/textures/nether_vine_normal.png
Normal file
After Width: | Height: | Size: 455 B |