Mineclonia/mods/MISC/mcl_anti_dimension_hopping/init.lua

197 lines
5.3 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

local S = minetest.get_translator("mcl_anti_dimension_hopping")
local storage = minetest.get_mod_storage()
local MAX_DISTANCE = 40
local dimension_change_is_legal = function(
player_name, -- string
dimension, -- "end"|"nether"|"overworld"|"void"
last_dimension, -- "end"|"nether"|"overworld"|"void"
last_last_dimension -- "end"|"nether"|"overworld"|"void"|nil
)
local player = minetest.get_player_by_name(player_name)
if nil == player then
return false
end
local player_position = player:get_pos()
if "end" == dimension then
assert( player_position.y > mcl_vars.mg_end_min )
assert( player_position.y < mcl_vars.mg_end_max )
-- Going to the End through a portal is allowed, but a
-- player must appear at End spawn for it to be legal.
-- The Nether as the last dimension is included here
-- because an End portal in the nether sends players
-- to End spawn, but cheaters can not teleport down
-- from the Nether, as the Nether is below the End.
if (
"overworld" == last_dimension or
"nether" == last_dimension
) then
if vector.distance(
player_position,
mcl_vars.mg_end_platform_pos
) < MAX_DISTANCE then
return true
end
end
-- Going to the End via the Void is allowed only if
-- the player entered the Void from the End … nil has
-- to be handled here for players who were in the Void
-- when this mod was activated.
if "void" == last_dimension then
if (
"end" == last_last_dimension or
nil == last_last_dimension
) then
return true
end
end
end
if "nether" == dimension then
assert( player_position.y > mcl_vars.mg_nether_min )
assert( player_position.y < mcl_vars.mg_nether_max )
-- Going to the Nether through a portal is allowed.
if "overworld" == last_dimension then
if nil ~= minetest.find_node_near(
player_position,
MAX_DISTANCE,
"mcl_portals:portal"
) then
-- TODO: check for portal in Overworld
return true
end
end
-- Going to the Nether via the Void is allowed only if
-- the player entered the Void from the Nether … nil
-- has to be handled here for players who were in the
-- Void when this mod was activated.
if "void" == last_dimension then
if (
"nether" == last_last_dimension or
nil == last_last_dimension
) then
return true
end
end
end
if "overworld" == dimension then
assert( player_position.y > mcl_vars.mg_overworld_min )
assert( player_position.y < mcl_vars.mg_overworld_max )
-- Going to the Overworld from the Nether through a
-- portal is allowed.
if "nether" == last_dimension then
if nil ~= minetest.find_node_near(
player_position,
MAX_DISTANCE,
"mcl_portals:portal"
) then
-- TODO: check for portal in Nether
return true
end
return true
end
-- Going to the Overworld via the Void is allowed only
-- if the player entered the Void from the Overworld …
-- nil has to be handled here for players who were in
-- the Void when this mod was activated.
if "void" == last_dimension then
if (
"overworld" == last_last_dimension or
nil == last_last_dimension
) then
return true
end
end
-- Going to the Overworld via the End (or any other
-- way) is allowed only if the player appears at their
-- respawn location, either because they used a portal
-- in the End or because they died.
local player_spawn_position = (
mcl_spawn.get_player_spawn_pos(player) or
mcl_spawn.get_world_spawn_pos(player)
)
if vector.distance(
player_position,
player_spawn_position
) < MAX_DISTANCE then
return true
end
end
if "void" == dimension then
-- Going to the Void is always legal a player who
-- enters the Void and then goes anywhere else than
-- where they came from is already handled above.
return true
end
return false
end
local kill_player_for_dimensional_trespassing = function(
player_name,
dimension,
last_dimension,
last_last_dimension
)
local player = minetest.get_player_by_name(player_name)
if nil == player then
return
end
-- If the player holds a totem of undying, destroy it before
-- killing, so it doesn't rescue the player.
local wield = player:get_wielded_item()
if wield:get_name() == "mobs_mc:totem" then
player:set_wielded_item("")
end
local death_message = S(
"@1 was executed for dimensional trespassing.",
player_name
)
mcl_death_messages.player_damage(
player,
death_message
)
player:set_hp(0)
local log_message = string.format(
"%s was executed for dimensional trespassing: %s → %s → %s",
tostring(player_name),
tostring(last_last_dimension),
tostring(last_dimension),
tostring(dimension)
)
minetest.log(
"action",
log_message
)
end
mcl_worlds.register_on_dimension_change(
function(player, dimension, last_dimension)
local player_name = player:get_player_name()
local last_last_dimension = storage:get_string(
player_name .. ":dimension_previous_previous"
)
if not dimension_change_is_legal(
player_name,
dimension,
last_dimension,
last_last_dimension
) then
kill_player_for_dimensional_trespassing(
player_name,
dimension,
last_dimension,
last_last_dimension
)
end
storage:set_string(
player_name .. ":dimension_previous_previous",
last_dimension
)
storage:set_string(
player_name .. ":dimension_previous",
dimension
)
end
)