2021-08-01 14:39:05 -04:00
2021-08-01 14:51:19 -04:00
local S = minetest.get_translator ( " teleporter_tool " )
2021-08-01 14:39:05 -04:00
-- The wear added to the teleporter per teleport. When the wear gets past 65535, the
-- tool breaks.
local WEAR_PER_USE = 328 -- 200 uses.
2021-08-03 16:21:55 -04:00
-- Provides a reference to ...
-- https://stackoverflow.com/questions/2282444/how-to-check-if-a-table-contains-an-element-in-lua
function table . contains ( table , element )
for _ , value in pairs ( table ) do
if value == element then
return true
end
end
return false
end
2021-08-01 14:39:05 -04:00
-- Tries to tell whether an ObjectRef represents a real connected player.
local function object_is_player ( object )
if not object then return false end
if not minetest.is_player ( object ) then return false end
-- Pipeworks uses this:
if object.is_fake_player then return false end
-- Check if the positions match:
local player = minetest.get_player_by_name ( object : get_player_name ( ) )
if not player then return false end
local object_pos = object : get_pos ( )
local player_pos = player : get_pos ( )
if not object_pos or not player_pos then return false end
return vector.equals ( object_pos , player_pos )
end
-- Verify when we talk to meta it is setup
local function pre_check ( item )
local meta = minetest.deserialize ( item : get_metadata ( ) )
if meta == nil then
meta = { }
meta.save_block = nil
end
return meta
end
-- Tries to teleport the node. The user will be
-- messaged if the teleport didn't occur. The return value is whether it did.
2021-08-03 16:21:55 -04:00
local function teleport_node ( pos , user , pt , tool )
2021-08-01 14:39:05 -04:00
local meta = pre_check ( tool )
local pname = user : get_player_name ( )
if meta.save_block == nil then
local old = minetest.get_node_or_nil ( pos )
if old ~= nil then
-- Allow aquiring teleport only if source is allowed to be interacted by the player. (Except if they have server or protection_bypass privs)
if not minetest.is_protected ( pos , pname ) or minetest.check_player_privs ( pname , { server = true } ) or minetest.check_player_privs ( pname , { protection_bypass = true } ) then
meta.save_block = pos -- Store the pos table
tool : set_metadata ( minetest.serialize ( meta ) ) -- Save it
minetest.chat_send_player ( pname , S ( " Aquired node at %s for teleport " ) : format ( minetest.pos_to_string ( pos ) ) )
else
2021-08-01 14:51:19 -04:00
minetest.log ( " action " , S ( " Player '%s' tried to move block %s by means of teleporter_tool:teleporter " ) : format ( pname , minetest.pos_to_string ( pos ) ) )
2021-08-01 14:39:05 -04:00
minetest.chat_send_player ( pname , S ( " Node at %s can't be teleported. " ) : format ( minetest.pos_to_string ( pos ) ) )
end
return { action = true , use = false }
else
minetest.chat_send_player ( pname , S ( " Old location at %s is unloaded, get closer. " ) : format ( minetest.pos_to_string ( pos ) ) )
2021-08-03 16:21:55 -04:00
meta.save_block = nil -- Reset the teleport
tool : set_metadata ( minetest.serialize ( meta ) ) -- Save it
2021-08-01 14:39:05 -04:00
return { action = false , use = false }
end
else
local old = minetest.get_node_or_nil ( meta.save_block )
local old_meta = minetest.get_meta ( meta.save_block )
old_meta = old_meta : to_table ( )
if old ~= nil then
2021-08-03 16:21:55 -04:00
local new = pt.above
2021-08-01 14:39:05 -04:00
-- Allow teleport only if source and destination are allowed to be interacted by the player. (Except if they have server or protection_bypass privs)
if not minetest.is_protected ( meta.save_block , pname ) and not minetest.is_protected ( new , pname ) or minetest.check_player_privs ( pname , { server = true } ) or minetest.check_player_privs ( pname , { protection_bypass = true } ) then
minetest.remove_node ( meta.save_block )
minetest.add_node ( new , old )
local new_node = minetest.get_meta ( new )
new_node : from_table ( old_meta )
minetest.chat_send_player ( pname , S ( " Teleported %s to %s. " ) : format ( minetest.pos_to_string ( meta.save_block ) , minetest.pos_to_string ( new ) ) )
meta.save_block = nil -- Reset the teleport
tool : set_metadata ( minetest.serialize ( meta ) ) -- Save it
return { action = true , use = true }
else
2021-08-01 14:51:19 -04:00
minetest.log ( " action " , S ( " Player '%s' tried to move block %s to %s by means of teleporter_tool:teleporter " ) : format ( pname , minetest.pos_to_string ( meta.save_block ) , minetest.pos_to_string ( new ) ) )
2021-08-01 14:39:05 -04:00
minetest.chat_send_player ( pname , S ( " Node at %s can't be teleported to %s. " ) : format ( minetest.pos_to_string ( meta.save_block ) , minetest.pos_to_string ( new ) ) )
2021-08-03 16:21:55 -04:00
meta.save_block = nil -- Reset the teleport
tool : set_metadata ( minetest.serialize ( meta ) ) -- Save it
2021-08-01 14:39:05 -04:00
end
else
minetest.chat_send_player ( pname , S ( " Old location at %s is unloaded, get closer. " ) : format ( minetest.pos_to_string ( meta.save_block ) ) )
2021-08-03 16:21:55 -04:00
meta.save_block = nil -- Reset the teleport
tool : set_metadata ( minetest.serialize ( meta ) ) -- Save it
2021-08-01 14:39:05 -04:00
return { action = false , use = false }
end
end
return { action = false , use = false }
end
-- Do the interaction. If reverse is true, the action pulling (otherwise it's
-- pushing.)
local function interact ( tool , user , pointed_thing , reverse )
local meta_updated = false
if pointed_thing.type == " node " then
local name = user and user : get_player_name ( ) or " "
local use_pos = pointed_thing.under
local meta = pre_check ( tool )
2021-08-03 16:21:55 -04:00
local op = teleport_node ( use_pos , user , pointed_thing , tool )
2021-08-01 14:39:05 -04:00
if op.action then
local sound = " teleporter_tool_pull "
if meta.save_block ~= nil then
sound = " teleporter_tool_push "
end
--minetest.chat_send_player(name, S("Playing sound '%s'"):format(sound))
minetest.sound_play ( sound , {
pos = use_pos ,
gain = 0.2 ,
} , true )
-- Only remove wear if not in creative
if not minetest.is_creative_enabled ( name ) and op.use then
tool : add_wear ( WEAR_PER_USE )
end
end
end
if meta_updated then
tool : set_metadata ( minetest.serialize ( meta ) )
end
return tool
end
2021-08-01 14:51:19 -04:00
minetest.register_tool ( " teleporter_tool:teleporter " , {
2021-08-01 14:39:05 -04:00
description = S ( " Teleporter " ) ,
2021-08-01 14:51:19 -04:00
inventory_image = " teleporter_tool_teleporter.png " ,
2021-08-01 14:39:05 -04:00
_mcl_toollike_wield = true ,
node_dig_prediction = " " ,
on_place = function ( tool , user , pointed_thing )
return interact ( tool , user , pointed_thing , true )
end ,
on_use = function ( tool , user , pointed_thing )
return interact ( tool , user , pointed_thing , false )
end ,
after_use = function ( ) return nil end , -- Do nothing.
} )
local EXTRA_BLOCK = " default:diamond "
local STICK = " group:stick "
-- In case default isn't present then switch to mcl_core
if ( not minetest.registered_items [ EXTRA_BLOCK ] ) and minetest.registered_items [ " mcl_core:diamond " ] then
EXTRA_BLOCK = " mcl_core:diamond "
end
if minetest.registered_items [ " mesecons_pistons:piston_sticky_off " ] then
local PISTON = " mesecons_pistons:piston_sticky_off "
minetest.register_craft ( {
2021-08-01 14:51:19 -04:00
output = " teleporter_tool:teleporter " ,
2021-08-01 14:39:05 -04:00
recipe = {
{ PISTON , EXTRA_BLOCK } ,
{ PISTON , STICK } ,
{ " " , STICK } ,
} ,
} )
end