forked from Mineclonia/Mineclonia
Execute players for illegal dimension hopping
This commit is contained in:
parent
28e4622712
commit
a3fd07a167
|
@ -0,0 +1,196 @@
|
|||
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
|
||||
)
|
|
@ -0,0 +1,2 @@
|
|||
name = mcl_anti_dimension_hopping
|
||||
depends = mcl_init, mcl_death_messages, mcl_portals, mcl_spawn, mcl_worlds
|
Loading…
Reference in New Issue