diff --git a/README.md b/README.md index 0714078..0d62ac0 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/nether/rest/Nicht Leere Datei.lua "b/nether/\n/Nicht Leere Datei.lua" similarity index 100% rename from nether/rest/Nicht Leere Datei.lua rename to "nether/\n/Nicht Leere Datei.lua" diff --git a/nether/rest/nether_fruit_leaves.png "b/nether/\n/nether_fruit_leaves.png" similarity index 100% rename from nether/rest/nether_fruit_leaves.png rename to "nether/\n/nether_fruit_leaves.png" diff --git a/nether/rest/nether_glowstone.png "b/nether/\n/nether_glowstone.png" similarity index 100% rename from nether/rest/nether_glowstone.png rename to "nether/\n/nether_glowstone.png" diff --git a/nether/rest/nether_leaves.png "b/nether/\n/nether_leaves.png" similarity index 100% rename from nether/rest/nether_leaves.png rename to "nether/\n/nether_leaves.png" diff --git a/nether/rest/nether_leaves_decision/nether_leaves.png "b/nether/\n/nether_leaves_decision/nether_leaves.png" similarity index 100% rename from nether/rest/nether_leaves_decision/nether_leaves.png rename to "nether/\n/nether_leaves_decision/nether_leaves.png" diff --git a/nether/rest/nether_leaves_decision/nether_leaves_high_cont.png "b/nether/\n/nether_leaves_decision/nether_leaves_high_cont.png" similarity index 100% rename from nether/rest/nether_leaves_decision/nether_leaves_high_cont.png rename to "nether/\n/nether_leaves_decision/nether_leaves_high_cont.png" diff --git a/nether/rest/nether_netherrack.png1 "b/nether/\n/nether_netherrack.png1" similarity index 100% rename from nether/rest/nether_netherrack.png1 rename to "nether/\n/nether_netherrack.png1" diff --git a/nether/rest/nether_portal_creator.png "b/nether/\n/nether_portal_creator.png" similarity index 100% rename from nether/rest/nether_portal_creator.png rename to "nether/\n/nether_portal_creator.png" diff --git a/nether/rest/nether_tree.png "b/nether/\n/nether_tree.png" similarity index 100% rename from nether/rest/nether_tree.png rename to "nether/\n/nether_tree.png" diff --git a/nether/rest/nether_tree_top.png "b/nether/\n/nether_tree_top.png" similarity index 100% rename from nether/rest/nether_tree_top.png rename to "nether/\n/nether_tree_top.png" diff --git a/nether/rest/temp.txt "b/nether/\n/temp.txt" similarity index 100% rename from nether/rest/temp.txt rename to "nether/\n/temp.txt" diff --git a/nether/depends.txt b/nether/depends.txt index 2f29bdb..a6b36a8 100755 --- a/nether/depends.txt +++ b/nether/depends.txt @@ -2,5 +2,6 @@ default glow riesenpilz stairs +vector_extras fence_registration? watershed? diff --git a/nether/init.lua b/nether/init.lua index cd6ead1..b0bfdde 100755 --- a/nether/init.lua +++ b/nether/init.lua @@ -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 diff --git a/nether/items.lua b/nether/items.lua index 6bc156d..e30bd84 100755 --- a/nether/items.lua +++ b/nether/items.lua @@ -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 = { diff --git a/nether/pearl.lua b/nether/pearl.lua index 25dfac2..d02f2e8 100755 --- a/nether/pearl.lua +++ b/nether/pearl.lua @@ -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}) diff --git a/nether/portal.lua b/nether/portal.lua index eaa581c..9617d8f 100755 --- a/nether/portal.lua +++ b/nether/portal.lua @@ -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 diff --git a/nether/textures/nether_vine_normal.png b/nether/textures/nether_vine_normal.png new file mode 100644 index 0000000..8c3c777 Binary files /dev/null and b/nether/textures/nether_vine_normal.png differ