Override player:set_pos etc. to disallow teleports from/to nether

constantly testing the player position is not longer necessary.
This commit is contained in:
HybridDog 2018-08-15 19:52:39 +02:00
parent 4a7dd247e7
commit df2d49edb0
1 changed files with 105 additions and 91 deletions

View File

@ -79,49 +79,48 @@ local function get_player_died_target(player)
end end
-- used for obsidian portal -- used for obsidian portal
local function obsidian_teleport(player, pname) local function obsidian_teleport(player, pname, target)
minetest.chat_send_player(pname, "For any reason you arrived here. Type " .. minetest.chat_send_player(pname, "For any reason you arrived here. Type " ..
"/nether_help to find out things like craft recipes.") "/nether_help to find out things like craft recipes.")
if obsidian_portal_kills then players_in_nether[pname] = true
save_nether_players()
update_background(player, true)
if target then
player:set_pos(target)
else
player:set_hp(0) player:set_hp(0)
return true
end 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 end
-- teleports players to nether or helps it -- teleports players to nether or helps it
local function player_to_nether(player, safe) local function player_to_nether(player, pos)
local pname = player:get_player_name() local pname = player:get_player_name()
if players_in_nether[pname] then if players_in_nether[pname] then
return return
end end
players_in_nether[pname] = true players_in_nether[pname] = true
save_nether_players() 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) update_background(player, true)
if pos then
player:set_pos(pos)
return
end
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:set_pos(get_player_died_target(player))
end
end end
local function player_from_nether(player) local function player_from_nether(player, pos)
local pname = player:get_player_name() local pname = player:get_player_name()
if players_in_nether[pname] then if players_in_nether[pname] then
players_in_nether[pname] = nil players_in_nether[pname] = nil
save_nether_players() save_nether_players()
end end
update_background(player) update_background(player)
player:set_pos(pos)
end end
@ -173,9 +172,8 @@ minetest.register_chatcommand("from_hell", {
return false, "Something went wrong." return false, "Something went wrong."
end end
minetest.chat_send_player(pname, "You are free now") minetest.chat_send_player(pname, "You are free now")
player_from_nether(player)
local pos = player:getpos() local pos = player:getpos()
player:moveto({x=pos.x, y=100, z=pos.z}) player_from_nether(player, {x=pos.x, y=100, z=pos.z})
return true, pname.." is now out of the nether." return true, pname.." is now out of the nether."
end end
}) })
@ -189,7 +187,7 @@ if nether_prisons then
return return
end end
local target = get_player_died_target(player) local target = get_player_died_target(player)
player:moveto(target) player:set_pos(target)
minetest.after(0, function(pname, target) minetest.after(0, function(pname, target)
-- fixes respawn bug -- fixes respawn bug
local player = minetest.get_player_by_name(pname) local player = minetest.get_player_by_name(pname)
@ -200,63 +198,76 @@ if nether_prisons then
return true return true
end) end)
-- function for teleporting players where they belong to -- override set_pos etc. to disallow player teleportion by e.g. travelnet
local function update_players() local function can_teleport(player, pos)
for _,player in pairs(minetest.get_connected_players()) do local pname = player:get_player_name()
local pname = player:get_player_name() local in_nether = players_in_nether[pname] == true
local ppos = player:getpos()
if players_in_nether[pname] then -- test if the target is valid
if ppos.y > nether.start then if pos.y < nether.start then
player:moveto({x=ppos.x, y=portal_target, z=ppos.z}) if in_nether then
update_background(player, true) return true
--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport out of the nether.".. end
"\n2. Maybe the server lagged.".. elseif not in_nether then
"\n3. please rejoin")]] return true
end end
elseif ppos.y < nether.start then
-- test if the current position is valid
local current_pos = player:get_pos()
local now_in_nether = current_pos.y < nether.start
if now_in_nether ~= in_nether then
if in_nether then
minetest.log("action", "Player \"" .. pname ..
"\" has to be in the nether, 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 nether, teleporting it!")
update_background(player) update_background(player)
player:moveto({x=ppos.x, y=20, z=ppos.z}) current_pos.y = 20
--[[minetest.kick_player(pname, "\n1. Maybe you were not allowed to teleport to the nether.".. player:set_pos(current_pos)
"\n2. Maybe the server lagged.".. end
"\n3. please rejoin")]] return false
end
minetest.chat_send_player(pname,
"You can not simply teleport to or from the nether!")
minetest.log("action", "Player \"" .. pname ..
"\" attempted to teleport from or to the nether, 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
if player:getpos().y < nether.start 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 end
end
-- the function delayer mod works similar to a scheduler
local delay_function = minetest.delay_function or minetest.after
local function tick()
update_players()
minetest.after(0.5, function() delay_function(1.5, tick) end)
end
tick()
-- set background when player joins
minetest.register_on_joinplayer(function(player)
minetest.after(0, function(player)
if player
and player:getpos().y < nether.start then
update_background(player, true)
end
end, player)
end) end)
else else
-- test if player is in nether when he/she joins -- test if player is in nether when he/she joins
--~ minetest.register_on_joinplayer(function(player) minetest.register_on_joinplayer(function(player)
--~ print(dump(player:get_pos())) players_in_nether[player:get_player_name()] =
--~ minetest.after(0, function(player) player:getpos().y < nether.start or nil
--~ local pname = player:get_player_name() end)
--~ if player:getpos().y < nether.start then
--~ if not players_in_nether[pname] then
--~ players_in_nether[pname] = true
--~ end
--~ return
--~ end
--~ if players_in_nether[pname] then
--~ players_in_nether[pname] = nil
--~ end
--~ end, player)
--~ end)
end end
-- removes the violet stuff from the obsidian portal -- removes the violet stuff from the obsidian portal
@ -301,19 +312,26 @@ local function obsi_teleport_player(player, pos, target)
return return
end end
if not obsidian_teleport(player, pname) then local has_teleported
if obsidian_portal_kills then
obsidian_teleport(player, pname)
has_teleported = true
elseif not mclike_portal then
local target = vector.round(get_player_died_target(player))
if generated_or_generate(target) then
obsidian_teleport(player, pname, target)
has_teleported = true
end
end
if not has_teleported then
-- e.g. ungenerated area -- e.g. ungenerated area
return return
end end
players_in_nether[pname] = true
save_nether_players()
update_background(player, true)
remove_portal_essence(pos) remove_portal_essence(pos)
minetest.sound_play("nether_portal_usual", {to_player=pname, gain=1}) minetest.sound_play("nether_portal_usual", {to_player=pname, gain=1})
--obj:setpos(target)
end end
-- abm for particles of the obsidian portal essence and for teleporting -- abm for particles of the obsidian portal essence and for teleporting
@ -541,7 +559,6 @@ minetest.after(0.1, function()
on_place = function(stack, player, pt) on_place = function(stack, player, pt)
if pt.under if pt.under
and minetest.get_node(pt.under).name == "default:obsidian" then and minetest.get_node(pt.under).name == "default:obsidian" then
--print("[nether] tries to enable a portal")
local done = make_portal(pt.under) local done = make_portal(pt.under)
if done then if done then
minetest.chat_send_player(player:get_player_name(), minetest.chat_send_player(player:get_player_name(),
@ -573,8 +590,7 @@ function(r)
return tab return tab
end end
-- detects if it's a portal local function is_netherportal(pos)
local function netherport(pos)
local x, y, z = pos.x, pos.y, pos.z local x, y, z = pos.x, pos.y, pos.z
for _,i in pairs({-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 if minetest.get_node({x=x, y=y+i, z=z}).name ~= "nether:white" then
@ -638,14 +654,13 @@ function nether_port(player, pos)
minetest.log("error", "[nether] nether_port: something failed.") minetest.log("error", "[nether] nether_port: something failed.")
return return
end end
if not netherport(pos) then if not is_netherportal(pos) then
return return
end end
minetest.sound_play("nether_teleporter", {pos=pos}) minetest.sound_play("nether_teleporter", {pos=pos})
local meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z}) local meta = minetest.get_meta({x=pos.x, y=pos.y-1, z=pos.z})
if pos.y < nether.start then if pos.y < nether.start then
set_portal(known_portals_d, pos.z,pos.x, pos.y) set_portal(known_portals_d, pos.z,pos.x, pos.y)
player_from_nether(player)
local my = tonumber(meta:get_string("y")) local my = tonumber(meta:get_string("y"))
local y = get_portal(known_portals_u, pos.z,pos.x) local y = get_portal(known_portals_u, pos.z,pos.x)
@ -656,9 +671,9 @@ function nether_port(player, pos)
else else
y = my or 100 y = my or 100
end end
pos.y = y pos.y = y - 0.3
player:moveto(pos) player_from_nether(player, pos)
else else
set_portal(known_portals_u, pos.z,pos.x, pos.y) set_portal(known_portals_u, pos.z,pos.x, pos.y)
@ -671,10 +686,9 @@ function nether_port(player, pos)
else else
y = my or portal_target+math.random(4) y = my or portal_target+math.random(4)
end end
pos.y = y pos.y = y - 0.3
player:moveto(pos) player_to_nether(player, pos)
player_to_nether(player, true)
end end
minetest.sound_play("nether_teleporter", {pos=pos}) minetest.sound_play("nether_teleporter", {pos=pos})
return true return true