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/pearl.lua b/nether/pearl.lua index 25dfac2..2fcd674 100644 --- a/nether/pearl.lua +++ b/nether/pearl.lua @@ -7,36 +7,60 @@ 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, - collisionbox = {0,0,0,0,0,0}, --not pointable - physical = false, -- Collides with things - textures = {"nether_pearl.png"}, - lastpos={}, - player = "", -} +local function get_node(pos) + local name = minetest.get_node(pos).name + if name == "ignore" then + minetest.get_voxel_manip():read_from_map(pos, pos) + name = minetest.get_node_or_nil(pos) + if not name then + return + end + name = name.name + end + return name +end -local allowed_nodes = {"air", "default:water_source"} +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) - local nd2 = minetest.get_node(pos).name + local nd2 = is_soft(pos) 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 + local nd3 = is_soft(pos) + if nd2 + and nd3 then pos.y = pos.y-1.4 player:moveto(pos) pos.y = pos.y-0.6 @@ -45,70 +69,130 @@ local function teleport_player(pos, player) return false end -ENTITY.on_step = function(self, dtime) - self.timer=self.timer+dtime +--[[ +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", { + timer = 0, + collisionbox = {0,0,0,0,0,0}, --not pointable + physical = false, -- Collides with things + textures = {"nether_pearl.png"}, + 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, + on_step = function(self, dtime) + self.timer = self.timer+dtime + + --[[ + local delay = self.delay + if delay < 0.1 then + self.delay = delay+dtime + return + end + self.delay = 0--]] + + 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(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 ab75ab7..3d5a64a 100644 --- a/nether/portal.lua +++ b/nether/portal.lua @@ -3,7 +3,7 @@ -- kills the player if he uses PilzAdam portal local obsidian_portal_kills = true local portal_target = nether.buildings+1 -local damage_enabled = minetest.setting_getbool("enable_damage") +local nether_prisons = minetest.setting_getbool("enable_damage") local abm_allowed minetest.after(5, function() @@ -40,7 +40,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") @@ -84,372 +84,372 @@ local function 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 - return true +if nether_prisons then + local function player_exists(name) + for _,player in pairs(minetest.get_connected_players()) do + if player:get_player_name() == name then + return true + end end + return false end - return false -end --- Chatcommands (edited) written by sss -minetest.register_chatcommand("to_hell", { - params = "[]", - description = "Send someone to hell", - func = function(name, pname) - if not minetest.check_player_privs(name, {nether=true}) then - return false, "You need the nether priv to execute this chatcommand." + -- Chatcommands (edited) written by sss + minetest.register_chatcommand("to_hell", { + params = "[]", + description = "Send someone to hell", + func = function(name, pname) + if not minetest.check_player_privs(name, {nether=true}) then + return false, "You need the nether priv to execute this chatcommand." + end + if not player_exists(pname) then + pname = name + end + local player = minetest.get_player_by_name(pname) + if not player then + return false, "Something went wrong." + end + minetest.chat_send_player(pname, "Go to hell !!!") + player_to_nether(player) + return true, pname.." is now in the nether." end - if not player_exists(pname) then - pname = name - end - local player = minetest.get_player_by_name(pname) - if not player then - return false, "Something went wrong." - end - minetest.chat_send_player(pname, "Go to hell !!!") - player_to_nether(player) - return true, pname.." is now in the nether." - end -}) + }) -minetest.register_chatcommand("from_hell", { - params = "[]", - description = "Extract from hell", - func = function(name, pname) - if not minetest.check_player_privs(name, {nether=true}) then - return false, "You need the nether priv to execute this chatcommand." + minetest.register_chatcommand("from_hell", { + params = "[]", + description = "Extract from hell", + func = function(name, pname) + if not minetest.check_player_privs(name, {nether=true}) then + return false, "You need the nether priv to execute this chatcommand." + end + if not player_exists(pname) then + pname = name + end + local player = minetest.get_player_by_name(pname) + if not player then + return false, "Something went wrong." + end + minetest.chat_send_player(pname, "You are free now") + player_from_nether(player) + local pos = player:getpos() + player:moveto({x=pos.x, y=100, z=pos.z}) + return true, pname.." is now out of the nether." end - if not player_exists(pname) then - pname = name - end - local player = minetest.get_player_by_name(pname) - if not player then - return false, "Something went wrong." - end - minetest.chat_send_player(pname, "You are free now") - player_from_nether(player) - 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 + 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 = 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 + 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 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) - -minetest.register_on_joinplayer(function(player) - minetest.after(0, function(player) - if player:getpos().y < nether.start then - update_background(player, true) + 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) -local function remove_portal_essence(pos) - for z = -1,1 do - for y = -2,2 do - for x = -1,1 do - local p = {x=pos.x+x, y=pos.y+y, z=pos.z+z} - if minetest.get_node(p).name == "nether:portal" then - minetest.remove_node(p) - end + minetest.register_on_joinplayer(function(player) + minetest.after(0, function(player) + if player:getpos().y < nether.start then + update_background(player, true) end - end - end -end + end, player) + end) -minetest.register_abm({ - nodenames = {"nether:portal"}, - interval = 1, - chance = 2, - catch_up = false, - action = function(pos, node) - 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), - }) - 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}) - player_to_nether(obj) - --obj:setpos(target) - - end, obj, pos, target) - end - end - end - end, -}) - -local function move_check(p1, max, dir) - local p = {x=p1.x, y=p1.y, z=p1.z} - local d = math.abs(max-p1[dir]) / (max-p1[dir]) - while p[dir] ~= max do - p[dir] = p[dir] + d - if minetest.get_node(p).name ~= "default:obsidian" then - return false - end - end - return true -end - -local function check_portal(p1, p2) - if p1.x ~= p2.x then - if not move_check(p1, p2.x, "x") then - return false - end - if not move_check(p2, p1.x, "x") then - return false - end - elseif p1.z ~= p2.z then - if not move_check(p1, p2.z, "z") then - return false - end - if not move_check(p2, p1.z, "z") then - return false - end - else - return false - end - - if not move_check(p1, p2.y, "y") then - return false - end - if not move_check(p2, p1.y, "y") then - return false - end - - return true -end - -local function is_portal(pos) - for d=-3,3 do - for y=-4,4 do - local px = {x=pos.x+d, y=pos.y+y, z=pos.z} - local pz = {x=pos.x, y=pos.y+y, z=pos.z+d} - if check_portal(px, {x=px.x+3, y=px.y+4, z=px.z}) then - return px, {x=px.x+3, y=px.y+4, z=px.z} - end - if check_portal(pz, {x=pz.x, y=pz.y+4, z=pz.z+3}) then - return pz, {x=pz.x, y=pz.y+4, z=pz.z+3} - end - end - end -end - -local function make_portal(pos) - local p1, p2 = is_portal(pos) - if not p1 - or not p2 then - print("[nether] something failed.") - return false - end - - if p1.y < nether.start then - print("[nether] aborted, obsidian portals can't be used to get out") - return - end - - for d=1,2 do - for y=p1.y+1,p2.y-1 do - local p - if p1.z == p2.z then - p = {x=p1.x+d, y=y, z=p1.z} - else - p = {x=p1.x, y=y, z=p1.z+d} - end - if minetest.get_node(p).name ~= "air" then - return false - end - end - end - - local param2 - if p1.z == p2.z then - param2 = 0 - else - param2 = 1 - end - - local target = {x=p1.x, y=p1.y, z=p1.z} - target.x = target.x + 1 - target.y = portal_target + math.random(4) - - for d=0,3 do - for y=p1.y,p2.y do - local p = {} - if param2 == 0 then - p = {x=p1.x+d, y=y, z=p1.z} - else - p = {x=p1.x, y=y, z=p1.z+d} - end - if minetest.get_node(p).name == "air" then - minetest.set_node(p, {name="nether:portal", param2=param2}) - end - local meta = minetest.get_meta(p) - meta:set_string("p1", minetest.pos_to_string(p1)) - meta:set_string("p2", minetest.pos_to_string(p2)) - meta:set_string("target", minetest.pos_to_string(target)) - end - end - print("[nether] construction accepted.") - return true -end - -minetest.override_item("default:obsidian", { - on_destruct = function(pos) - local meta = minetest.get_meta(pos) - local p1 = minetest.string_to_pos(meta:get_string("p1")) - local p2 = minetest.string_to_pos(meta:get_string("p2")) - local target = minetest.string_to_pos(meta:get_string("target")) - if not p1 or not p2 then - return - end - for x=p1.x,p2.x do - for y=p1.y,p2.y do - for z=p1.z,p2.z do - local nn = minetest.get_node({x=x,y=y,z=z}).name - if nn == "default:obsidian" or nn == "nether:portal" then - if nn == "nether:portal" then - minetest.remove_node({x=x,y=y,z=z}) - end - local m = minetest.get_meta({x=x,y=y,z=z}) - m:set_string("p1", "") - m:set_string("p2", "") - m:set_string("target", "") - end - end - end - end - meta = minetest.get_meta(target) - if not meta then - return - end - p1 = minetest.string_to_pos(meta:get_string("p1")) - p2 = minetest.string_to_pos(meta:get_string("p2")) - if not p1 or not p2 then - return - end - for x=p1.x,p2.x do - for y=p1.y,p2.y do - for z=p1.z,p2.z do - local nn = minetest.get_node({x=x,y=y,z=z}).name - if nn == "default:obsidian" or nn == "nether:portal" then - if nn == "nether:portal" then - minetest.remove_node({x=x,y=y,z=z}) - end - local m = minetest.get_meta({x=x,y=y,z=z}) - m:set_string("p1", "") - m:set_string("p2", "") - m:set_string("target", "") - end - end - end - end - end -}) - -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") - local done = make_portal(pt.under) - if done then - minetest.chat_send_player( - player:get_player_name(), - "Warning: If you are in the nether you may not be able to find the way out!" - ) - if not minetest.setting_getbool("creative_mode") then - stack:take_item() + local function remove_portal_essence(pos) + for z = -1,1 do + for y = -2,2 do + for x = -1,1 do + local p = {x=pos.x+x, y=pos.y+y, z=pos.z+z} + if minetest.get_node(p).name == "nether:portal" then + minetest.remove_node(p) end end end - return stack + end + end + + minetest.register_abm({ + nodenames = {"nether:portal"}, + interval = 1, + chance = 2, + catch_up = false, + action = function(pos, node) + 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), + }) + 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}) + player_to_nether(obj) + --obj:setpos(target) + + end, obj, pos, target) + end + end + end + end, + }) + + local function move_check(p1, max, dir) + local p = {x=p1.x, y=p1.y, z=p1.z} + local d = math.abs(max-p1[dir]) / (max-p1[dir]) + while p[dir] ~= max do + p[dir] = p[dir] + d + if minetest.get_node(p).name ~= "default:obsidian" then + return false + end + end + return true + end + + local function check_portal(p1, p2) + if p1.x ~= p2.x then + if not move_check(p1, p2.x, "x") then + return false + end + if not move_check(p2, p1.x, "x") then + return false + end + elseif p1.z ~= p2.z then + if not move_check(p1, p2.z, "z") then + return false + end + if not move_check(p2, p1.z, "z") then + return false + end + else + return false + end + + if not move_check(p1, p2.y, "y") then + return false + end + if not move_check(p2, p1.y, "y") then + return false + end + + return true + end + + local function is_portal(pos) + for d=-3,3 do + for y=-4,4 do + local px = {x=pos.x+d, y=pos.y+y, z=pos.z} + local pz = {x=pos.x, y=pos.y+y, z=pos.z+d} + if check_portal(px, {x=px.x+3, y=px.y+4, z=px.z}) then + return px, {x=px.x+3, y=px.y+4, z=px.z} + end + if check_portal(pz, {x=pz.x, y=pz.y+4, z=pz.z+3}) then + return pz, {x=pz.x, y=pz.y+4, z=pz.z+3} + end + end + end + end + + local function make_portal(pos) + local p1, p2 = is_portal(pos) + if not p1 + or not p2 then + print("[nether] something failed.") + return false + end + + if p1.y < nether.start then + print("[nether] aborted, obsidian portals can't be used to get out") + return + end + + for d=1,2 do + for y=p1.y+1,p2.y-1 do + local p + if p1.z == p2.z then + p = {x=p1.x+d, y=y, z=p1.z} + else + p = {x=p1.x, y=y, z=p1.z+d} + end + if minetest.get_node(p).name ~= "air" then + return false + end + end + end + + local param2 + if p1.z == p2.z then + param2 = 0 + else + param2 = 1 + end + + local target = {x=p1.x, y=p1.y, z=p1.z} + target.x = target.x + 1 + target.y = portal_target + math.random(4) + + for d=0,3 do + for y=p1.y,p2.y do + local p = {} + if param2 == 0 then + p = {x=p1.x+d, y=y, z=p1.z} + else + p = {x=p1.x, y=y, z=p1.z+d} + end + if minetest.get_node(p).name == "air" then + minetest.set_node(p, {name="nether:portal", param2=param2}) + end + local meta = minetest.get_meta(p) + meta:set_string("p1", minetest.pos_to_string(p1)) + meta:set_string("p2", minetest.pos_to_string(p2)) + meta:set_string("target", minetest.pos_to_string(target)) + end + end + print("[nether] construction accepted.") + return true + end + + minetest.override_item("default:obsidian", { + on_destruct = function(pos) + local meta = minetest.get_meta(pos) + local p1 = minetest.string_to_pos(meta:get_string("p1")) + local p2 = minetest.string_to_pos(meta:get_string("p2")) + local target = minetest.string_to_pos(meta:get_string("target")) + if not p1 or not p2 then + return + end + for x=p1.x,p2.x do + for y=p1.y,p2.y do + for z=p1.z,p2.z do + local nn = minetest.get_node({x=x,y=y,z=z}).name + if nn == "default:obsidian" or nn == "nether:portal" then + if nn == "nether:portal" then + minetest.remove_node({x=x,y=y,z=z}) + end + local m = minetest.get_meta({x=x,y=y,z=z}) + m:set_string("p1", "") + m:set_string("p2", "") + m:set_string("target", "") + end + end + end + end + meta = minetest.get_meta(target) + if not meta then + return + end + p1 = minetest.string_to_pos(meta:get_string("p1")) + p2 = minetest.string_to_pos(meta:get_string("p2")) + if not p1 or not p2 then + return + end + for x=p1.x,p2.x do + for y=p1.y,p2.y do + for z=p1.z,p2.z do + local nn = minetest.get_node({x=x,y=y,z=z}).name + if nn == "default:obsidian" or nn == "nether:portal" then + if nn == "nether:portal" then + minetest.remove_node({x=x,y=y,z=z}) + end + local m = minetest.get_meta({x=x,y=y,z=z}) + m:set_string("p1", "") + m:set_string("p2", "") + m:set_string("target", "") + end + end + end + end end }) -end) + + 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") + local done = make_portal(pt.under) + if done then + minetest.chat_send_player( + player:get_player_name(), + "Warning: If you are in the nether you may not be able to find the way out!" + ) + if not minetest.setting_getbool("creative_mode") then + stack:take_item() + end + end + end + return stack + end + }) + end) end