--code copied from Pilzadam's nether mod and edited local S = hell.get_translator -- kills the player if he uses PilzAdam portal local portal_target = hell.buildings+1 local hell_prisons = minetest.settings:get_bool("enable_damage") local obsidian_portal_kills = hell_prisons and true local mclike_portal = false local save_path = minetest.get_worldpath() .. "/hell_players" local players_in_hell = {} -- only get info from file if hell prisons if hell_prisons then local file = io.open(save_path, "r") if file then local contents = file:read("*all") io.close(file) if contents then local playernames = string.split(contents, " ") for i = 1,#playernames do players_in_hell[playernames[i]] = true end end end end local function save_hell_players() local playernames,n = {},1 for name in pairs(players_in_hell) do playernames[n] = name n = n+1 end local f = io.open(save_path, "w") assert(f, "Could not open hell_players file for writing.") f:write(table.concat(playernames, " ")) io.close(f) end local update_background if hell_prisons then function update_background(player, down) if down then player:set_sky({base_color={r=15, g=0, b=0}, type="plain"}) else player:set_sky({type="regular"}) end end else function update_background() end end -- where the player appears after dying local function get_player_died_target(player) local target = vector.add(player:get_pos(), {x=math.random(-5,5), y=0, z=math.random(-5,5)}) target.y = portal_target + math.random(4) return target end -- used for obsidian portal local function obsidian_teleport(player, pname, target) minetest.chat_send_player(pname, S("For any reason you arrived here. Type /hell_help to find out things like craft recipes.")) players_in_hell[pname] = true save_hell_players() update_background(player, true) player:set_hp(0) if target then player:set_pos(target) end end -- teleports players to hell or helps it local function player_to_hell(player, pos) local pname = player:get_player_name() if players_in_hell[pname] then return end players_in_hell[pname] = true save_hell_players() update_background(player, true) if pos then player:set_pos(pos) return end minetest.chat_send_player(pname, S("For any reason you arrived here. Type /hell_help to find out things like craft recipes.")) player:set_hp(0) if hell_prisons then player:set_pos(get_player_died_target(player)) end end local function player_from_hell(player, pos) local pname = player:get_player_name() if players_in_hell[pname] then players_in_hell[pname] = nil save_hell_players() end update_background(player) player:set_pos(pos) end local function is_player_connected(name) for _,player in pairs(minetest.get_connected_players()) do if player:get_player_name() == name then return true end end return false end -- Chatcommands (edited) written by sss minetest.register_chatcommand("to_hell", { params = "[player_name]", description = S("Send someone to hell"), func = function(name, pname) if not minetest.check_player_privs(name, {hell=true}) then return false, S("You need the hell privilege to execute this chatcommand.") end if not is_player_connected(pname) then pname = name end local player = minetest.get_player_by_name(pname) if not player then return false, S("Something went wrong.") end minetest.chat_send_player(pname, S("Go to hell !!!")) player_to_hell(player) return true, S("@1 is now in the hell.", pname) end }) minetest.register_chatcommand("from_hell", { params = "[player_name]", description = S("Extract someone from hell"), func = function(name, pname) if not minetest.check_player_privs(name, {hell=true}) then return false, S("You need the hell priv to execute this chatcommand.") end if not is_player_connected(pname) then pname = name end local player = minetest.get_player_by_name(pname) if not player then return false, S("Something went wrong.") end minetest.chat_send_player(pname, S("You are free now")) local pos = player:get_pos() player_from_hell(player, {x=pos.x, y=100, z=pos.z}) return true, S("@1 is now out of the hell.", pname) end }) if hell_prisons then -- randomly set player position when he/she dies in hell minetest.register_on_respawnplayer(function(player) local pname = player:get_player_name() if not players_in_hell[pname] then return end local target = get_player_died_target(player) player:set_pos(target) minetest.after(0, function(pname, target) -- fixes respawn bug local player = minetest.get_player_by_name(pname) if player then player:move_to(target) end end, pname, target) return true end) -- override set_pos etc. to disallow player teleportion by e.g. travelnet local function can_teleport(player, pos) if not player:is_player() then -- the same metatable is used for entities return true end local pname = player:get_player_name() local in_hell = players_in_hell[pname] -- test if the target is valid if pos.y < hell.start and pos.y > hell.DEPTH-510 then if in_hell then return true end elseif not in_hell then return true end -- test if the current position is valid local current_pos = player:get_pos() local now_in_hell = current_pos.y < hell.start and current_pos.y > hell.DEPTH-510 if now_in_hell ~= in_hell then if in_hell then minetest.log("action", "Player \"" .. pname .. "\" has to be in the hell, teleporting it!") update_background(player, true) current_pos.y = portal_target player:set_pos(current_pos) else minetest.log("action", "Player \"" .. pname .. "\" must not be in the hell, teleporting it!") update_background(player) current_pos.y = 20 player:set_pos(current_pos) end return false end minetest.chat_send_player(pname, S("You can not simply teleport to or from the hell!")) minetest.log("action", "Player \"" .. pname .. "\" attempted to teleport from or to the hell, ignoring.") return false end local methods = {"set_pos", "move_to"} -- "setpos", "moveto"} local metatable_overridden minetest.register_on_joinplayer(function(player) -- set the background when the player joins local y = player:get_pos().y if y < hell.start and y > hell.DEPTH-510 then update_background(player, true) end -- overide set_pos etc. if not yet done if metatable_overridden then return end metatable_overridden = true local mt = getmetatable(player) for i = 1,#methods do local methodname = methods[i] local origfunc = mt[methodname] mt[methodname] = function(...) if can_teleport(...) then origfunc(...) end end end end) else -- test if player is in hell when he/she joins minetest.register_on_joinplayer(function(player) local y = player:get_pos().y players_in_hell[player:get_player_name()] = y < hell.start and y > hell.DEPTH-510 or nil end) end -- a not filled square vector.square = vector.square or function(r) local tab, n = {}, 1 for i = -r+1, r do for j = -1, 1, 2 do local a, b = r*j, i*j tab[n] = {a, b} tab[n+1] = {b, a} n=n+2 end end return tab end local function is_hellportal(pos) local x, y, z = pos.x, pos.y, pos.z if y < 0 then y = y+1 end for _,i in pairs({-1, 3}) do if minetest.get_node({x=x, y=y+i, z=z}).name ~= "hell:white" then return end end for _,sn in pairs(vector.square(1)) do if minetest.get_node({x=x+sn[1], y=y-1, z=z+sn[2]}).name ~= "hell:hellrack" or minetest.get_node({x=x+sn[1], y=y+3, z=z+sn[2]}).name ~= "hell:blood_cooked" then return end end for _,sn in pairs(vector.square(2)) do if minetest.get_node({x=x+sn[1], y=y-1, z=z+sn[2]}).name ~= "hell:hellrack_black" or minetest.get_node({x=x+sn[1], y=y+3, z=z+sn[2]}).name ~= "hell:wood_empty" then return end end for i = -1,1,2 do for j = -1,1,2 do if minetest.get_node({x=x+i, y=y+2, z=z+j}).name ~= "hell:apple" then return end end end for i = -2,2,4 do for j = 0,2 do for k = -2,2,4 do if minetest.get_node({x=x+i, y=y+j, z=z+k}).name ~= "hell:hellrack_brick_blue" then return end end end end for i = -1,1 do for j = -1,1 do if minetest.get_node({x=x+i, y=y+4, z=z+j}).name ~= "hell:wood_empty" then return end end end return true end -- cache known portals local known_portals_d = {} local known_portals_u = {} local function get_portal(t, z,x) return t[z] and t[z][x] end local function set_portal(t, z,x, y) t[z] = t[z] or {} t[z][x] = y end -- used when a player eats hell:apple in a portal local function hell_port(player, pos) if not player or not pos or not pos.x then minetest.log("error", "[hell] hell_port: something failed.") return end if not is_hellportal(pos) then return end minetest.sound_play("hell_teleporter", {pos=pos}) local meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z}) if pos.y < hell.start and pos.y > hell.DEPTH-510 then set_portal(known_portals_d, pos.z,pos.x, pos.y) local my = tonumber(meta:get_string("y")) local destination_pos = vector.multiply(pos, hell.FASTTRAVEL_FACTOR) destination_pos.x = math.min(30900, math.max(-30900, destination_pos.x)) -- clip to world boundary destination_pos.z = math.min(30900, math.max(-30900, destination_pos.z)) -- clip to world boundary local y = get_portal(known_portals_u, destination_pos.z, destination_pos.x) if y then if y ~= my then meta:set_string("y", y) end else y = my or 100 end destination_pos.y = y - 0.3 player_from_hell(player, destination_pos) else set_portal(known_portals_u, pos.z,pos.x, pos.y) local my = tonumber(meta:get_string("y")) local destination_pos = vector.divide(pos, hell.FASTTRAVEL_FACTOR) destination_pos.x = math.floor(0.5 + destination_pos.x) -- round to int destination_pos.z = math.floor(0.5 + destination_pos.z) -- round to int local y = get_portal(known_portals_d, destination_pos.z, destination_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 destination_pos.y = y + 0.7 player_to_hell(player, destination_pos) end minetest.sound_play("hell_teleporter", {pos=pos}) return true end minetest.override_item("hell:apple", { on_use = function(itemstack, user, pointed_thing) local inv = user:get_inventory() if not inv then return end if hell_port(user, vector.round(user:get_pos())) then itemstack:take_item() return itemstack else return minetest.do_item_eat(-5, "hell:blood_extracted 2", itemstack, user, pointed_thing) end end, }) if hell.HELL_REALM_ENABLED then -- Use the Portal API to add a portal type which goes to the Hell -- See portal_api.txt for documentation nether.register_portal("hell_gate", { shape = nether.PortalShape_Circular, frame_node_name = "nether:brick", wormhole_node_color = 5, -- 5 is red title = S("Hell Gate"), particle_texture = { name = "nether_particle_anim2.png", animation = { type = "vertical_frames", aspect_w = 7, aspect_h = 7, length = 1, }, scale = 1.5 }, book_of_portals_pagetext = S("Construction requires 16 blocks of ??. The finished frame must be in the shape of a circle and laid vertically, like a door.").."\n\n"..S("However, I never knew what material to use for building this door despite my many attempts.").."\n\n"..S("One day, however, I met an old lady who frankly looked like a witch. In the course of our discussion we came to talk about the Hell Gate. This old lady confessed to me that in her family there was a legend that one of her ancestors had managed to activate the portal. But that the poor man was instantly killed as he passed through it. The gate was destroyed and several years passed. But since a certain night, the poor widow of the deceased began to rave that her Husband had come back from the dead to take her also to hell because he said that he had made this world a wonderful place and that after several years, he would have found a way to come back and return to it as he wished without causing death. A few days later, the widow disappeared without a trace. Since then the house was destroyed in a fire with all the secrets it could hold. Only an old cauldron remained amidst the ashes.").."\n\n"..S("When I wanted to ask the old lady with what material the gate was made, she stared at me with eyes so black that I had the impression that the Nether wanted to take over me, and I did not insist any further."), is_within_realm = function(pos) -- return true if pos is inside the Hell return pos.y < hell.DEPTH and pos.y > hell.DEPTH-510 end, find_realm_anchorPos = function(surface_anchorPos) -- divide x and z by a factor of 8 to implement Hell fast-travel local destination_pos = vector.divide(surface_anchorPos, hell.FASTTRAVEL_FACTOR) destination_pos.x = math.floor(0.5 + destination_pos.x) -- round to int destination_pos.z = math.floor(0.5 + destination_pos.z) -- round to int destination_pos.y = hell.DEPTH-390 -- temp value so find_nearest_working_portal() returns hell portals -- a y_factor of 0 makes the search ignore the altitude of the portals (as long as they are in the Hell) local existing_portal_location, existing_portal_orientation = nether.find_nearest_working_portal("hell_gate", destination_pos, 8, 0) if existing_portal_location ~= nil then return existing_portal_location, existing_portal_orientation else destination_pos.y = hell.DEPTH-390 + math.random(0, 30) return destination_pos end end, find_surface_anchorPos = function(realm_anchorPos) -- A portal definition doesn't normally need to provide a find_surface_anchorPos() function, -- since find_surface_target_y() will be used by default, but Hell portals also scale position -- to create fast-travel. -- Defining a custom function also means we can look for existing nearby portals. -- Multiply x and z by a factor of 8 to implement Hell fast-travel local destination_pos = vector.multiply(realm_anchorPos, hell.FASTTRAVEL_FACTOR) destination_pos.x = math.min(30900, math.max(-30900, destination_pos.x)) -- clip to world boundary destination_pos.z = math.min(30900, math.max(-30900, destination_pos.z)) -- clip to world boundary destination_pos.y = 0 -- temp value so find_nearest_working_portal() doesn't return hell portals -- a y_factor of 0 makes the search ignore the altitude of the portals (as long as they are outside the Hell) local existing_portal_location, existing_portal_orientation = nether.find_nearest_working_portal("hell_gate", destination_pos, 8 * hell.FASTTRAVEL_FACTOR, 0) if existing_portal_location ~= nil then return existing_portal_location, existing_portal_orientation else destination_pos.y = nether.find_surface_target_y(destination_pos.x, destination_pos.z, "hell_gate") return destination_pos end end, on_ignite = function(portalDef, anchorPos, orientation) -- make some sparks fly local p1, p2 = portalDef.shape:get_p1_and_p2_from_anchorPos(anchorPos, orientation) local pos = vector.divide(vector.add(p1, p2), 2) local textureName = portalDef.particle_texture if type(textureName) == "table" then textureName = textureName.name end minetest.add_particlespawner({ amount = 110, time = 0.1, minpos = {x = pos.x - 0.5, y = pos.y - 1.2, z = pos.z - 0.5}, maxpos = {x = pos.x + 0.5, y = pos.y + 1.2, z = pos.z + 0.5}, minvel = {x = -5, y = -1, z = -5}, maxvel = {x = 5, y = 1, z = 5}, minacc = {x = 0, y = 0, z = 0}, maxacc = {x = 0, y = 0, z = 0}, minexptime = 0.1, maxexptime = 0.5, minsize = 0.2 * portalDef.particle_texture_scale, maxsize = 0.8 * portalDef.particle_texture_scale, collisiondetection = false, texture = textureName .. "^[colorize:#F00:alpha", animation = portalDef.particle_texture_animation, glow = 8 }) end, on_player_teleported = function(portal_definition, player, playerPos, new_playerPos) local pname = player:get_player_name() if players_in_hell[pname] then return end obsidian_teleport(player, pname, new_playerPos) minetest.sound_play("hell_portal_usual", {to_player=pname, gain=1}) end, }) end -- Pour éviter de pouvoir aller en enfer depuis le nether avec un portail du nether construit depuis l'enfer if nether.NETHER_REALM_ENABLED then nether.registered_portals["nether_portal"].on_player_teleported = function(portal_definition, player, playerPos, new_playerPos) local new_y = new_playerPos.y if new_y > hell.DEPTH-510 and new_y < hell.DEPTH then minetest.after( 0,function(player, target) -- fixes respawn bug if player then player:move_to(target) end end, player, playerPos) minetest.chat_send_player(player:get_player_name(), S("You shall not pass!")) end end end