code:
--= Teleport Potion mod by TenPlus1 (SFX are license free)

-- Craft teleport potion or pad, use to bookmark location, place to open
-- portal or place pad, portals show a blue flame that you can walk into
-- before it closes (10 seconds), potions can also be thrown for local teleport.

-- Load support for intllib.
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP .. "/intllib.lua")

-- check for MineClone2
local mcl = minetest.get_modpath("mcl_core")

-- max teleport distance
local dist = tonumber(minetest.settings:get("map_generation_limit") or 31000)

-- creative check
local creative_mode_cache = minetest.settings:get_bool("creative_mode")
local function is_creative(name)
	return creative_mode_cache or minetest.check_player_privs(name, {creative = true})
end

local check_coordinates = function(str)

	if not str or str == "" then
		return nil
	end

	-- get coords from string
	local x, y, z = string.match(str, "^(-?%d+),(-?%d+),(-?%d+)$")

	-- check coords
	if x == nil or string.len(x) > 6
	or y == nil or string.len(y) > 6
	or z == nil or string.len(z) > 6 then
		return nil
	end

	-- convert string coords to numbers
	x = tonumber(x)
	y = tonumber(y)
	z = tonumber(z)

	-- are coords in map range ?
	if x > dist or x < -dist
	or y > dist or y < -dist
	or z > dist or z < -dist then
		return nil
	end

	-- return ok coords
	return {x = x, y = y, z = z}
end

-- particle effects
local function tp_effect(pos)
	minetest.add_particlespawner({
		amount = 20,
		time = 0.25,
		minpos = pos,
		maxpos = pos,
		minvel = {x = -2, y = 1, z = -2},
		maxvel = {x = 2,  y = 2,  z = 2},
		minacc = {x = 0, y = -2, z = 0},
		maxacc = {x = 0, y = -4, z = 0},
		minexptime = 0.1,
		maxexptime = 1,
		minsize = 0.5,
		maxsize = 1.5,
		texture = "particle.png",
		glow = 15,
	})
end

local teleport_destinations = {}

local function set_teleport_destination(playername, dest)
	teleport_destinations[playername] = dest
	tp_effect(dest)
	minetest.sound_play("portal_open", {
		pos = dest,
		gain = 1.0,
		max_hear_distance = 10
	}, true)
end

--------------------------------------------------------------------------------
--- Teleport portal
--------------------------------------------------------------------------------
minetest.register_node("teleport_potion:portal", {
	drawtype = "plantlike",
	tiles = {
		{name="portal.png",
			animation = {
				type = "vertical_frames",
				aspect_w = 16,
				aspect_h = 16,
				length = 1.0
			}
		}
	},
	light_source = 13,
	walkable = false,
	paramtype = "light",
	pointable = false,
	buildable_to = true,
	waving = 1,
	sunlight_propagates = true,
	damage_per_second = 1, -- walking into portal hurts player

	-- start timer when portal appears
	on_construct = function(pos)
		minetest.get_node_timer(pos):start(10)
	end,

	-- remove portal after 10 seconds
	on_timer = function(pos)

		minetest.sound_play("portal_close", {
			pos = pos,
			gain = 1.0,
			max_hear_distance = 10
		}, true)

		minetest.remove_node(pos)
	end,
	on_blast = function() end,
	drop = {},
})

-- Throwable potion
local function throw_potion(itemstack, player)

	local playerpos = player:get_pos()

	local obj = minetest.add_entity({
		x = playerpos.x,
		y = playerpos.y + 1.5,
		z = playerpos.z
	}, "teleport_potion:potion_entity")

	local dir = player:get_look_dir()
	local velocity = 20

	obj:set_velocity({
		x = dir.x * velocity,
		y = dir.y * velocity,
		z = dir.z * velocity
	})

	obj:set_acceleration({
		x = dir.x * -3,
		y = -9.5,
		z = dir.z * -3
	})

	obj:set_yaw(player:get_look_horizontal())
	obj:get_luaentity().player = player
end

local potion_entity = {
	physical = true,
	visual = "sprite",
	visual_size = {x = 1.0, y = 1.0},
	textures = {"potion.png"},
	collisionbox = {-0.1,-0.1,-0.1,0.1,0.1,0.1},
	lastpos = {},
	player = "",
}

potion_entity.on_step = function(self, dtime)

	if not self.player then
		self.object:remove()
		return
	end

	local pos = self.object:get_pos()

	if self.lastpos.x ~= nil then

		local vel = self.object:get_velocity()

		-- only when potion hits something physical
		if vel.x == 0
		or vel.y == 0
		or vel.z == 0 then

			if self.player ~= "" then

				-- round up coords to fix glitching through doors
				self.lastpos = vector.round(self.lastpos)

				self.player:set_pos(self.lastpos)

				minetest.sound_play("portal_close", {
					pos = self.lastpos,
					gain = 1.0,
					max_hear_distance = 5
				}, true)

				tp_effect(self.lastpos)
			end

			self.object:remove()

			return

		end
	end

	self.lastpos = pos
end

minetest.register_entity("teleport_potion:potion_entity", potion_entity)

--------------------------------------------------------------------------------
--- Teleport potion
--------------------------------------------------------------------------------
minetest.register_node("teleport_potion:potion", {
	tiles = {"potion.png"},
	drawtype = "signlike",
	paramtype = "light",
	paramtype2 = "wallmounted",
	walkable = false,
	sunlight_propagates = true,
	description = S("Teleport Potion (use to set destination; place to open portal)"),
	inventory_image = "potion.png",
	wield_image = "potion.png",
	groups = {dig_immediate = 3, vessel = 1},
	selection_box = {type = "wallmounted"},

	on_use = function(itemstack, user, pointed_thing)
		if pointed_thing.type == "node" then
			set_teleport_destination(user:get_player_name(), pointed_thing.above)
		else
			throw_potion(itemstack, user)
			if not is_creative(user:get_player_name()) then
				itemstack:take_item()
				return itemstack
			end
		end
	end,

	after_place_node = function(pos, placer, itemstack, pointed_thing)
		local name = placer:get_player_name()
		local dest = teleport_destinations[name]
		if dest then
			minetest.set_node(pos, {name = "teleport_potion:portal"})
			local meta = minetest.get_meta(pos)
			-- Set portal destination
			meta:set_int("x", dest.x)
			meta:set_int("y", dest.y)
			meta:set_int("z", dest.z)
			-- Portal open effect and sound
			tp_effect(pos)
			minetest.sound_play("portal_open", {
				pos = pos,
				gain = 1.0,
				max_hear_distance = 10
			})
		else
			minetest.chat_send_player(name, S("Potion failed!"))
			minetest.remove_node(pos)
			minetest.add_item(pos, "teleport_potion:potion")
		end
	end,
})

-- teleport potion recipe
if mcl then
minetest.register_craft({
	output = "teleport_potion:potion",
	recipe = {
		{"", "mcl_core:diamond", ""},
		{"mcl_core:diamond", "mcl_potions:glass_bottle", "mcl_core:diamond"},
		{"", "mcl_core:diamond", ""},
	},
})
else
minetest.register_craft({
	output = "teleport_potion:potion",
	recipe = {
		{"", "default:diamond", ""},
		{"default:diamond", "vessels:glass_bottle", "default:diamond"},
		{"", "default:diamond", ""},
	},
})
end

--------------------------------------------------------------------------------
--- Teleport pad
--------------------------------------------------------------------------------
local teleport_formspec_context = {}

minetest.register_node("teleport_potion:pad", {
	tiles = {"padd.png", "padd.png^[transformFY"},
	drawtype = "nodebox",
	paramtype = "light",
	paramtype2 = "facedir",
	legacy_wallmounted = true,
	walkable = true,
	sunlight_propagates = true,
	description = S("Teleport Pad (use to set destination; place to open portal)"),
	inventory_image = "padd.png",
	wield_image = "padd.png",
	light_source = 5,
	groups = {snappy = 3},
	node_box = {
		type = "fixed",
		fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
	},
	selection_box = {
		type = "fixed",
		fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
	},

	-- Save pointed nodes coordinates as destination for further portals
	on_use = function(itemstack, user, pointed_thing)
		if pointed_thing.type == "node" then
			set_teleport_destination(user:get_player_name(), pointed_thing.above)
		end
	end,

	-- Initialize teleport to saved location or the current position
	after_place_node = function(pos, placer, itemstack, pointed_thing)
		local meta = minetest.get_meta(pos)
		local name = placer:get_player_name()
		local dest = teleport_destinations[name]
		if not dest then
			dest = pos
		end
		-- Set coords
		meta:set_int("x", dest.x)
		meta:set_int("y", dest.y)
		meta:set_int("z", dest.z)

		meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
				dest.x, dest.y, dest.z))

		minetest.sound_play("portal_open", {
			pos = pos,
			gain = 1.0,
			max_hear_distance = 10
		}, true)
	end,

	-- Show formspec depending on the players privileges.
	on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
		local name = clicker:get_player_name()

		if minetest.is_protected(pos, name) then
			minetest.record_protection_violation(pos, name)
			return
		end

		local meta = minetest.get_meta(pos)
		local coords = {
			x = meta:get_int("x"),
			y = meta:get_int("y"),
			z = meta:get_int("z")
		}
		local coords = coords.x .. "," .. coords.y .. "," .. coords.z
		local desc = meta:get_string("desc")
		formspec = "field[desc;" .. S("Description") .. ";"
				.. minetest.formspec_escape(desc) .. "]"
		-- Only allow privileged players to change coordinates
		if minetest.check_player_privs(name, "teleport") then
			formspec = formspec ..
					"field[coords;" .. S("Teleport coordinates") .. ";" .. coords .. "]"
		end

		teleport_formspec_context[name] = {
			pos = pos,
			coords = coords,
			desc = desc,
		}
		minetest.show_formspec(name, "teleport_potion:set_destination", formspec)
	end,
})

-- Check and set coordinates
minetest.register_on_player_receive_fields(function(player, formname, fields)
	if formname ~= "teleport_potion:set_destination" then
		return false
	end
	local name = player:get_player_name()
	local context = teleport_formspec_context[name]
	if not context then return false end
	teleport_formspec_context[name] = nil
	local meta = minetest.get_meta(context.pos)
	-- Coordinates were changed
	if fields.coords and fields.coords ~= context.coords then
		local coords = check_coordinates(fields.coords)
		if coords then
			meta:set_int("x", coords.x)
			meta:set_int("y", coords.y)
			meta:set_int("z", coords.z)
		else
			minetest.chat_send_player(name, S("Teleport Pad coordinates failed!"))
		end
	end
	-- Update infotext
	if fields.desc and fields.desc ~= "" then
		meta:set_string("desc", fields.desc)
		meta:set_string("infotext", S("Teleport to @1", fields.desc))
	else
		local coords = minetest.string_to_pos("(" .. context.coords .. ")")
		meta:set_string("infotext", S("Pad Active (@1,@2,@3)",
			coords.x, coords.y, coords.z))
	end
	return true
end)

-- teleport pad recipe
if mcl then
minetest.register_craft({
	output = "teleport_potion:pad",
	recipe = {
		{"teleport_potion:potion", "mcl_core:glass", "teleport_potion:potion"},
		{"mcl_core:glass", "mesecons:redstone", "mcl_core:glass"},
		{"teleport_potion:potion", "mcl_core:glass", "teleport_potion:potion"},
	},
})
else
minetest.register_craft({
	output = "teleport_potion:pad",
	recipe = {
		{"teleport_potion:potion", "default:glass", "teleport_potion:potion"},
		{"default:glass", "default:mese", "default:glass"},
		{"teleport_potion:potion", "default:glass", "teleport_potion:potion"}
	}
})
end

-- check portal & pad, teleport any entities on top
minetest.register_abm({
	label = "Potion/Pad teleportation",
	nodenames = {"teleport_potion:portal", "teleport_potion:pad"},
	interval = 2,
	chance = 1,
	catch_up = false,

	action = function(pos, node, active_object_count, active_object_count_wider)

		-- check objects inside pad/portal
		local objs = minetest.get_objects_inside_radius(pos, 1)

		if #objs == 0 then
			return
		end

		-- get coords from pad/portal
		local meta = minetest.get_meta(pos)

		if not meta then return end -- errorcheck

		local target_coords = {
			x = meta:get_int("x"),
			y = meta:get_int("y"),
			z = meta:get_int("z")
		}

		for n = 1, #objs do

			if objs[n]:is_player() then

				-- play sound on portal end
				minetest.sound_play("portal_close", {
					pos = pos,
					gain = 1.0,
					max_hear_distance = 5
				}, true)

				-- move player
				objs[n]:set_pos(target_coords)

				-- paricle effects on arrival
				tp_effect(target_coords)

				-- play sound on destination end
				minetest.sound_play("portal_close", {
					pos = target_coords,
					gain = 1.0,
					max_hear_distance = 5
				}, true)

				-- rotate player to look in pad placement direction
				local rot = node.param2
				local yaw = 0

				if rot == 0 or rot == 20 then
					yaw = 0 -- north
				elseif rot == 2 or rot == 22 then
					yaw = 3.14 -- south
				elseif rot == 1 or rot == 23 then
					yaw = 4.71 -- west
				elseif rot == 3 or rot == 21 then
					yaw = 1.57 -- east
				end

				objs[n]:set_look_yaw(yaw)
			end
		end
	end
})

-- add lucky blocks

-- Teleport Potion mod
if minetest.get_modpath("lucky_block") then
	lucky_block:add_blocks({
		{"dro", {"teleport_potion:potion"}, 2},
		{"tel"},
		{"dro", {"teleport_potion:pad"}, 1},
		{"lig"},
	})
end

print ("[MOD] Teleport Potion loaded")


code:
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.

-- Get the latest version of this file at:
--   https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua

local function format(str, ...)
	local args = { ... }
	local function repl(escape, open, num, close)
		if escape == "" then
			local replacement = tostring(args[tonumber(num)])
			if open == "" then
				replacement = replacement..close
			end
			return replacement
		else
			return "@"..open..num..close
		end
	end
	return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end

local gettext, ngettext
if minetest.get_modpath("intllib") then
	if intllib.make_gettext_pair then
		-- New method using gettext.
		gettext, ngettext = intllib.make_gettext_pair()
	else
		-- Old method using text files.
		gettext = intllib.Getter()
	end
end

-- Fill in missing functions.

gettext = gettext or function(msgid, ...)
	return format(msgid, ...)
end

ngettext = ngettext or function(msgid, msgid_plural, n, ...)
	return format(n==1 and msgid or msgid_plural, ...)
end

return gettext, ngettext

repo_name: Desour/PlayMinetestServer

license: mit


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:37+0200\n"
"PO-Revision-Date: 2016-05-27 08:38+0200\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.12\n"
"Last-Translator: Xanthin\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Language: de\n"

#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr ""
"Teleportationstrank (platzieren und rechtsklicken,\n"
"um Standort zu verzaubern)"

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr "Koordinaten eingeben (z.B. 200,20,-200)"

#: init.lua
msgid "Right-click to enchant teleport location"
msgstr "Rechtsklick um Teleportationsort zu verzaubern"

#: init.lua
msgid "Potion failed!"
msgstr "Trank misslungen!"

#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr ""
"Teleportationsfeld (platzieren und rechtsklicken,\n"
"um Standort zu verzaubern)"

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr "Koordinaten eingeben (z.B. 200,20,-200,Haus)"

#: init.lua
msgid "Teleport to @1"
msgstr "Teleportiere nach @1"

#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr "Feld aktiv (@1,@2,@3)"

#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr "Teleportationsfeldkoordinaten fehlgeschlagen!"


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:34+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr "Poción de teletransporte (colocar y hacer clic derecho para encantar la ubicación)"

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr "Inserta las coordenadas del teletransporte (Por ejemplo, 200,20, -200)"

#: init.lua
msgid "Right-click to enchant teleport location"
msgstr "Haga clic derecho para encantar la ubicación de teletransporte"

#: init.lua
msgid "Potion failed!"
msgstr "¡Poción fallida!"

#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr "Teleport Pad (Colocalo y haz clic derecho para encantar la ubicación)"

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr "Inserte las coordenadas del teletransporte (por ejemplo, 200,20, -200, Inicio)"

#: init.lua
msgid "Teleport to @1"
msgstr "Teletransportarse a @1"

#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr "Pad activo"

#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr "¡Coordenadas del Teleport Pad erroneas!"


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:35+0200\n"
"PO-Revision-Date: 2017-05-14 08:37+0200\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.8.12\n"
"Last-Translator: Peppy <peppy@twang-factory.com>\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"Language: fr\n"

#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr "Potion de téléportation (poser puis clic-droit pour enchanter l'emplacement)"

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr "Saisissez les coordonnées de téléportation  (ex : 200,20,-200)"

#: init.lua
msgid "Right-click to enchant teleport location"
msgstr "Clic-droit pour enchanter l'emplacement de téléportation"

#: init.lua
msgid "Potion failed!"
msgstr "La potion n'a pas fonctionné !"

#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr "Pad de téléportation (poser puis clic-droit pour enchanter l'emplacement)"

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr "Saisissez les coordonnées de téléportation  (ex : 200,20,-200,Maison)"

#: init.lua
msgid "Teleport to @1"
msgstr "Téléportation vers @1"

#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr "Pad activé (@1,@,2,@3)"

#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr "Les coordonnées du pad sont inchangées !"


code:
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-05-14 08:34+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#: init.lua
msgid "Teleport Potion (place and right-click to enchant location)"
msgstr ""

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200)"
msgstr ""

#: init.lua
msgid "Right-click to enchant teleport location"
msgstr ""

#: init.lua
msgid "Potion failed!"
msgstr ""

#: init.lua
msgid "Teleport Pad (place and right-click to enchant location)"
msgstr ""

#: init.lua
msgid "Enter teleport coords (e.g. 200,20,-200,Home)"
msgstr ""

#: init.lua
msgid "Teleport to @1"
msgstr ""

#: init.lua
msgid "Pad Active (@1,@2,@3)"
msgstr ""

#: init.lua
msgid "Teleport Pad coordinates failed!"
msgstr ""


code: name = teleport_potion


code:
name: Build
on: [push, pull_request]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1
    - name: apt
      run: sudo apt-get install -y luarocks
    - name: luacheck install
      run: luarocks install --local luacheck
    - name: luacheck run
      run: $HOME/.luarocks/bin/luacheck ./


code:
unused_args = false
allow_defined_top = true

globals = {
    "minetest",
}

read_globals = {
    string = {fields = {"split"}},
    table = {fields = {"copy", "getn"}},

    -- Builtin
    "vector", "ItemStack",
    "dump", "DIR_DELIM", "VoxelArea", "Settings",

    -- MTG
    "default", "sfinv", "creative",
}


code:
# minetest-toolranks [toolranks]

Minetest tool ranks mod

Tools gain levels for digging nodes. Higher level tools dig faster and take longer to wear out.

## Are you a mod developer?

Does one of your mods add new tools?
If so, to support this mod, add this code to your mod, after your tool's code:

```lua
if minetest.get_modpath("toolranks") then
    minetest.override_item("mymod:mytool", {
        original_description = "My Tool",
        description = toolranks.create_description("My Tool"),
        after_use = toolranks.new_afteruse
    })
    end
end
```

Or alternatively, you can use the helper function:

```lua
toolranks.add_tool("mymod:mytool")
```


code:
local mod_storage = minetest.get_mod_storage()
local S = minetest.get_translator("toolranks")

toolranks = {}

toolranks.colors = {
  grey = minetest.get_color_escape_sequence("#9d9d9d"),
  green = minetest.get_color_escape_sequence("#1eff00"),
  gold = minetest.get_color_escape_sequence("#ffdf00"),
  white = minetest.get_color_escape_sequence("#ffffff")
}

local max_speed = tonumber(minetest.settings:get("toolranks_speed_multiplier")) or 2.0
local max_use = tonumber(minetest.settings:get("toolranks_use_multiplier")) or 2.0
local max_level = tonumber(minetest.settings:get("toolranks_levels")) or 10
local level_digs = tonumber(minetest.settings:get("toolranks_level_digs")) or 500
local level_multiplier = 1 / max_level

function toolranks.get_tool_type(description)
  if not description then
    return "tool"
  else
    local d = string.lower(description)
    if string.find(d, "pickaxe") then
      return "pickaxe"
    elseif string.find(d, "axe") then
      return "axe"
    elseif string.find(d, "shovel") then
      return "shovel"
    elseif string.find(d, "hoe") then
      return "hoe"
    elseif string.find(d, "sword") then
      return "sword"
    else
      return "tool"
    end
  end
end

function toolranks.get_level(uses)
  if type(uses) == "number" and uses > 0 then
    return math.min(max_level, math.floor(uses / level_digs))
  end
  return 0
end

function toolranks.create_description(name, uses)
  local description = name
  local tooltype = toolranks.get_tool_type(description)
  local newdesc = S(
    "@1@2\n@3Level @4 @5\n@6@Node dug: @7",
    toolranks.colors.green,
    description,
    toolranks.colors.gold,
    toolranks.get_level(uses),
    S(tooltype),
    toolranks.colors.grey,
    (type(uses) == "number" and uses or 0)
  )
  return newdesc
end

function toolranks.new_afteruse(itemstack, user, node, digparams)
  local itemmeta = itemstack:get_meta()
  local itemdef = itemstack:get_definition()
  local itemdesc = itemdef.original_description
  local dugnodes = tonumber(itemmeta:get_string("dug")) or 0
  local lastlevel = tonumber(itemmeta:get_string("lastlevel")) or 0
  local most_digs = mod_storage:get_int("most_digs") or 0
  local most_digs_user = mod_storage:get_string("most_digs_user") or 0

  if digparams.wear > 0 then -- Only count nodes that spend the tool
    dugnodes = dugnodes + 1
    itemmeta:set_string("dug", dugnodes)
  end

  if dugnodes > most_digs then
    if most_digs_user ~= user:get_player_name() then -- Avoid spam.
      minetest.chat_send_all(S(
        "Most used tool is now a @1@2@3 owned by @4 with @5 uses.",
        toolranks.colors.green,
        itemdesc,
        toolranks.colors.white,
        user:get_player_name(),
        dugnodes
      ))
    end
    mod_storage:set_int("most_digs", dugnodes)
    mod_storage:set_string("most_digs_user", user:get_player_name())
  end

  if itemstack:get_wear() > 60136 then
    minetest.chat_send_player(user:get_player_name(), S("Your tool is about to break!"))
    minetest.sound_play("default_tool_breaks", {
      to_player = user:get_player_name(),
      gain = 2.0,
    })
  end

  local level = toolranks.get_level(dugnodes)
  if lastlevel < level then
    local levelup_text = S(
      "Your @1@2@3 just leveled up!",
      toolranks.colors.green,
      itemdesc,
      toolranks.colors.white
    )
    minetest.chat_send_player(user:get_player_name(), levelup_text)
    minetest.sound_play("toolranks_levelup", {
      to_player = user:get_player_name(),
      gain = 2.0,
    })

    local speed_multiplier = 1 + (level * level_multiplier * (max_speed - 1))
    local use_multiplier = 1 + (level * level_multiplier * (max_use - 1))
    local caps = table.copy(itemdef.tool_capabilities)

    caps.full_punch_interval = caps.full_punch_interval and (caps.full_punch_interval / speed_multiplier)
    caps.punch_attack_uses = caps.punch_attack_uses and (caps.punch_attack_uses * use_multiplier)

    for _,c in pairs(caps.groupcaps) do
      c.uses = c.uses * use_multiplier
      for i,t in ipairs(c.times) do
        c.times[i] = t / speed_multiplier
      end
    end
    itemmeta:set_tool_capabilities(caps)
  end

  itemmeta:set_string("lastlevel", level)
  itemmeta:set_string("description", toolranks.create_description(itemdesc, dugnodes))
  itemstack:add_wear(digparams.wear)
  return itemstack
end

-- Helper function
function toolranks.add_tool(name)
  local desc = ItemStack(name):get_definition().description
  minetest.override_item(name, {
    original_description = desc,
    description = toolranks.create_description(desc),
    after_use = toolranks.new_afteruse
  })
end

-- Sword
toolranks.add_tool("default:sword_wood")
toolranks.add_tool("default:sword_stone")
toolranks.add_tool("default:sword_steel")
toolranks.add_tool("default:sword_bronze")
toolranks.add_tool("default:sword_mese")
toolranks.add_tool("default:sword_diamond")

-- Pickaxe
toolranks.add_tool("default:pick_wood")
toolranks.add_tool("default:pick_stone")
toolranks.add_tool("default:pick_steel")
toolranks.add_tool("default:pick_bronze")
toolranks.add_tool("default:pick_mese")
toolranks.add_tool("default:pick_diamond")

-- Axe
toolranks.add_tool("default:axe_wood")
toolranks.add_tool("default:axe_stone")
toolranks.add_tool("default:axe_steel")
toolranks.add_tool("default:axe_bronze")
toolranks.add_tool("default:axe_mese")
toolranks.add_tool("default:axe_diamond")

-- Shovel
toolranks.add_tool("default:shovel_wood")
toolranks.add_tool("default:shovel_stone")
toolranks.add_tool("default:shovel_steel")
toolranks.add_tool("default:shovel_bronze")
toolranks.add_tool("default:shovel_mese")
toolranks.add_tool("default:shovel_diamond")


code:
# textdomain: toolranks
@1@2@n@3Level @4 @5@n@6Node dug: @7=@1@2@n@3Level @4 @5@n@6Node dug: @7
pickaxe=pickaxe
axe=axe
shovel=shovel
hoe=hoe
sword=sword
tool=tool
Most used tool is now a @1@2@3 owned by @4 with @5 uses.=Most used tool is now a @1@2@3 owned by @4 with @5 uses.
Your tool is about to break!=Your tool is about to break!
Your @1@2@3 just leveled up!=Your @1@2@3 just leveled up!


code:
# textdomain: toolranks
@1@2@n@3Level @4 @5@n@6Node dug: @7=@1@2@n@3@5 niveau @4@n@6Blocks minés : @7
pickaxe=pioche
axe=hache
shovel=pelle
hoe=houe
sword=épée
tool=outil
Most used tool is now a @1@2@3 owned by @4 with @5 uses.=L’outil le plus utilisé est désormais @1@2@3 appartenant à @4 avec @5 utilisations.
Your tool is about to break!=Votre outil va se casser !
Your @1@2@3 just leveled up!=Votre @1@2@3 a gagné un niveau !


code:
name = toolranks
depends = default


code:
# Number of tool levels
toolranks_levels (Levels) int 10
# Number of nodes that need to be dug to reach the next tool level
toolranks_level_digs (Digs per level) int 500
# Dig speed multiplier at maximum tool level (1.0 to disable)
toolranks_speed_multiplier (Dig speed multiplier) float 2.0 1.0 10.0
# Durability multiplier at maximum tool level (1.0 to disable)
toolranks_use_multiplier (Durability multiplier) float 2.0 1.0 10.0


code:
# Compiled Lua sources
luac.out

# luarocks build files
*.src.rock
*.zip
*.tar.gz

# Object files
*.o
*.os
*.ko
*.obj
*.elf

# Precompiled Headers
*.gch
*.pch

# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp

# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib

# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex


code:
std = "lua51+minetest"
unused_args = false
allow_defined_top = true
max_line_length = 90

stds.minetest = {
	read_globals = {
		"minetest",
		"VoxelManip",
		"VoxelArea",
		"PseudoRandom",
		"ItemStack",
		"default",
		table = {
			fields = {
				"copy",
			},
		},
	}
}

read_globals = {
	"toolranks",
	"farming",
}

files["tool_types.lua"] = {
	read_globals = {
		toolranks = {
			fields = {
				get_tool_type = {
					read_only = false,
					other_fields = false
				},
				create_description = {
					read_only = false,
					otherfields = false
				},
			}
		}
	}
}


code:
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.3.0
    hooks:
      - id: end-of-file-fixer
      - id: trailing-whitespace
      - id: mixed-line-ending


code:
language: python
sudo: false
addons:
  apt:
    packages:
      - luarocks
cache:
  timeout: 1000
  directories:
    - $HOME/.luarocks
before_install:
  - luarocks install --local luacheck
  - pip3 install pre-commit
script:
  - pre-commit run --all-files
  - $HOME/.luarocks/bin/luacheck .
notifications:
  email: false


code:
# minetest-toolranks-extras

[![Build Status](https://travis-ci.org/louisroyer/minetest-toolranks-extras.svg?branch=master)](https://travis-ci.org/louisroyer/minetest-toolranks-extras) [![ContentDB](https://content.minetest.net/packages/louisroyer/toolranks_extras/shields/title/)](https://content.minetest.net/packages/louisroyer/toolranks_extras/) [![ContentDB](https://content.minetest.net/packages/louisroyer/toolranks_extras/shields/downloads/)](https://content.minetest.net/packages/louisroyer/toolranks_extras/)

This minetest mod extends [toolranks](https://github.com/lisacvuk/minetest-toolranks). It adds support for `minetest-games`’s mods (except `default`).
This mod currently adds support for hoes from `farming` mod.
This mod is compatible with [farming redo](https://notabug.org/tenplus1/farming) (nothing breaks if you have both installed).

This mod also adds an API to register new types of tools for toolranks.

## API

```lua
--[[
--   `keyword` is a string to be detected in tool description
--   `tool_type` is a localized tool type (if nil, then unregister the keyword)
--   `node_dug_display` is an (optional) alternative localized display
--       of "Node Dug" (if false, then unregister the display)
--]]
toolranks_extras.register_tool_type(keyword, tool_type, [node_dug_display])

-- example
toolranks_extras.register_tool_type("battle_axe", S("battle axe"))
toolranks_extras.register_tool_type("bow", S("bow"), S("Arrows thrown"))
```

![Screenshot](screenshot.png)

## License
- CC0-1.0, Louis Royer 2020

## Settings
- Settings are available to disable support of some mods (currently only `farming`). This is useful if you want to reimplement minetest-games modules
with a `toolranks` support. It is also possible to ask me to automatically disabling support if your mod is detected (like it is done with farming redo).
- Extras tool types registering can be disabled (registering function will still be available, but will do nothing).


code:
local function add_hoe(material)
	-- registering as tool
	local name = "farming:hoe_"..material
	toolranks.add_tool(name)

	-- getting after_use
	local def = minetest.registered_items[name]
	local hoe_on_use = def.on_use
	local hoe_after_use = def.after_use

	if (hoe_on_use == nil) or (hoe_after_use == nil) then
		return
	end
	minetest.override_item(name, {
		-- we also want hoes to increase dugnodes when farming soil
		on_use = function(itemstack, user, pointed_thing, uses)
			-- if no node is pointed, the hoe cannot be used
			if pointed_thing.under == nil then
				return nil
			end
			local under = minetest.get_node(pointed_thing.under)
			-- get origin wear
			local wear = itemstack:get_wear()
			-- apply previous on_use
			local ret_itemstack = hoe_on_use(itemstack, user, pointed_thing, uses)
			if ret_itemstack == nil then
				return nil
			end
			-- compute wear diff
			local hoe_uses = ret_itemstack:get_wear() - wear
			-- set wear back because it is up to hoe_after_use to add wear
			ret_itemstack:set_wear(wear)
			-- apply afteruse
			return hoe_after_use(ret_itemstack, user, under, {wear = hoe_uses})
		end

	})
end

add_hoe("wood")
add_hoe("stone")
add_hoe("steel")

-- Following hoes are not available in creative inventory, but
-- it is possible to /give them
add_hoe("bronze")
add_hoe("mese")
add_hoe("diamond")


code:
local MP = minetest.get_modpath("toolranks_extras")

toolranks_extras = {}

-- mod information
toolranks_extras.mod = {version = "1.4.2", author = "Louis Royer"}

-- settings
toolranks_extras.settings = {
	enable_farming_tools = minetest.settings:get_bool("toolranks_extras.farming", true),
	enable_tool_types = minetest.settings:get_bool("toolranks_extras.tool_types", true),
}

-- XXX: when https://github.com/minetest/minetest/pull/7377
--      is merged, we can remove this function
--      and %s/toolranks_extras\.log/minetest\.log/g
toolranks_extras.log = function(level, text)
	local prefix = "[toolranks_extra] "
	if text then
		minetest.log(level, prefix..text)
	else
		minetest.log(prefix..level)
	end
end

-- mods detection
local use_farming = minetest.get_modpath("farming")
-- farming redo (https://notabug.org/tenplus1/farming)
-- already implements toolranks support
local use_farming_redo = use_farming and (farming.mod == "redo") or false

-- toolranks version
if toolranks.add_tool == nil then
	toolranks_extras.log("error", "Please a more recent version of"
		.." toolranks (at least version 1.2).")
end

dofile(MP.."/tool_types.lua")
if use_farming and (not use_farming_redo)
	and toolranks_extras.settings.enable_farming_tools then
	dofile(MP.."/hoe.lua")
end


code:
# textdomain: toolranks_extras

### tool_types.lua ###

@1@2@n@3Level @4 @5@n@6@7: @8=


code:
# textdomain: toolranks_extras

### tool_types.lua ###

@1@2@n@3Level @4 @5@n@6@7: @8=@1@2@n@3@5 niveau @4@n@6@7 : @8


code:
name = toolranks_extras
description =  Extended Tool Ranks support.
depends = toolranks
optional_depends = farming
min_minetest_version = 5.0


code:
toolranks_extras.farming (Enable toolranks on farming tools) bool true
toolranks_extras.tool_types (Enable registering of extras tool types) bool true


code:
local S = minetest.get_translator("toolranks_extras")
toolranks_extras.registered_tool_types = {}
toolranks_extras.node_dug_display = {}
--[[
--   `keyword` is a string to be detected in tool description
--   `tool_type` is a localized tool type (if nil, then unregister the keyword)
--   `node_dug_display` is an (optional) alternative localized display
--       of "Node Dug" (if false, then unregister the display)
-- example
-- `toolranks_extras.register_tool_type("battle_axe", S("battle axe"))`
-- `toolranks_extras.register_tool_type("bow", S("bow"), S("Arrows thrown"))`
--]]
toolranks_extras.register_tool_type = function(keyword, tool_type, node_dug_display)
	local k = string.lower(keyword)
	toolranks_extras.registered_tool_types[k] = tool_type
	if node_dug_display == false then
		toolranks_extras.node_dug_display[k] = nil
	elseif node_dug_display ~= nil then
		toolranks_extras.node_dug_display[k] = node_dug_display
	end
end

--[[
-- Returns alternative node dug display if registered, or nil.
--]]
toolranks_extras.get_node_dug_display = function(description)
	local d = string.lower(description)
	for k, desc in pairs(toolranks_extras.node_dug_display) do
		if string.find(d, k) then
			return desc
		end
	end
	return
end

toolranks_extras.ignored_toolranks_tool_types = {}
--[[
--   `keyword` is a string to be detected in tool description
--   `tool_type` is a localized tool type
--
-- example
-- `toolranks_extras.ignore_toolranks_tool_type("pickaxe")`
-- This only works with tool types built in toolranks default get_tool_types function.
--]]
toolranks_extras.ignore_toolranks_tool_type = function(keyword)
	table.insert(toolranks_extras.ignored_toolranks_tool_types, string.lower(keyword))
end
toolranks_extras.ignore_toolranks_tool_type("tool")

if toolranks_extras.settings.enable_tool_types then
	local TR = minetest.get_translator("toolranks")
	local origin_get_tool_type = toolranks.get_tool_type
	--[[
	-- Returns nil if the keyword is ignored, else returns the keyword.
	--]]
	local function check_ignore(keyword)
		for _, k in ipairs(toolranks_extras.ignored_toolranks_tool_types) do
			if keyword == k then
				return
			end
		end
		return keyword
	end

	-- overwrite of toolranks.get_tool_type(description)
	toolranks.get_tool_type = function(description)
		-- execute original function
		local tool_type = check_ignore(origin_get_tool_type(description))
		if tool_type ~= nil then
			return TR(tool_type)
		end
		-- search for registered tool types
		local d = string.lower(description)
		for k, desc in pairs(toolranks_extras.registered_tool_types) do
			if string.find(d, k) then
				return desc
			end
		end
		-- fallback
		return TR("tool")
	end

	-- overwrite of toolranks.create_description(name, uses)
	toolranks.create_description = function(name, uses)
		local tooltype = toolranks.get_tool_type(name)
		local alt_display = toolranks_extras.get_node_dug_display(name)
		if alt_display ~= nil then
			return S("@1@2\n@3Level @4 @5\n@6@7: @8",
				toolranks.colors.green,
				name,
				toolranks.colors.gold,
				toolranks.get_level(uses),
				tooltype,
				toolranks.colors.grey,
				alt_display,
				(type(uses) == "number" and uses or 0)
			)
		end
		return TR(
			"@1@2\n@3Level @4 @5\n@6@Node dug: @7",
			toolranks.colors.green,
			name,
			toolranks.colors.gold,
			toolranks.get_level(uses),
			tooltype,
			toolranks.colors.grey,
			(type(uses) == "number" and uses or 0)
		)
	end
end


code:
# Teleport Request
A mod that allows players to send a teleport request.
**(See "How to use" below for more information.)**

## Privileges:
Each command needs a privilege. These are the following privileges:
- **tp** is requiered in order to use all commands.
- **tp_tpc** is requiered in order to use `/tpc`
- **tp_tpc** is requiered in order to use `/tpe`
- **tp_tpc** is requiered in order to use `/tpj`
- **interact** is also requiered to use all commands.
**tp_admin** overrides everything: e.g. you can teleport to players even when they haven't decided to accept, or not. You can also teleport him/her to you (this happens only when `enable_immediate_teleport` is enabled on `config.lua`).
Players can also teleport to coordinates, however, if the area is protected, the teleport will be denied.

## How to use:
Each command does a function. "**Example Usage**" is an example of how to use the command.
Note there must be 2 players in order to make the commands to work: a player must send a request to another player (**see https://wiki.minetest.net/Server or see https://wiki.minetest.net/Setting_up_a_server for more information**).
There are two methods of sending a request:
1. A request which teleports you to the specified player (command `/tpr <player>`).
2. A request which teleports the specified player to you (command `/tphr <player>`).

To accept a request some sent you, you must use `/tpy`.
These are the following commands available in-game:

``` /tpr [playername] ```
- **Name:** Teleport Request
- **Description:** Requests permission to teleport to another player, where [playername] is their exact name.
- **Required Privileges:** `interact, tp`
- **Example Usage:** */tpr RobbieF* - requests permission from RobbieF to teleport to them.
- **Notes:** Usernames are case-sensitive. If you have "tp_admin" privilege, you will immediately teleport to the specificed player (does not apply if `enable_immediate_teleport` setting is disabled, enabled by default).

``` /tphr [playername] ```
- **Name:** Teleport Here Request
- **Description:** Request permission to teleport another player to you.
- **Required Privileges:** `interact, tp`
- **Example Usage:** /tphr RobbieF - requests RobbieF to teleport to you.
- **Notes:** Usernames are case-sensitive. If you have "tp_admin" privilege, RobbieF will teleport to you immediately (does not apply if `enable_immediate_teleport` setting is disabled, enabled by default).

``` /tpc [x,y,z] ```
- **Name:** Teleport to Coordinates
- **Description:** Teleport to coordinates.
- **Required Privileges:** `interact, tp_tpc, tp`
- **Notes:** Honors area protection: if the area is protected, it must be owned by you in order to teleport to it, or you must have "areas" privilege in order to teleport to those coordinates (this works only when [areas](https://github.com/minetest-mods/areas) is installed).

``` /tpj [axis] [distance] ```
- **Name:** Teleport Jump
- **Description:** Teleport a specified distance along a single specified axis.
- **Required Privilege:** `interact", tp, tp_tpc`
- **Available Options for *axis*:** x, y, z
- **Example Usage:** '/tpj y 10' - teleport 10 nodes into the air.

``` /tpe ```
- **Name:** Teleport Evade
- **Description:** In a sticky situation? Evade your enemy by teleporting to several nearby coordinates in random pattern. There's no knowing where you'll end up.
- **Required Privileges:** `interact, tp_tpc, tp`
- **Example Usage:** '/tpe' - teleports you to a random number of random coordinates in an evasive pattern.

``` /tpy ```
- **Description:** Accept a user's request to teleport to you or teleport you to them.

``` /tpn ```
- **Description:** Deny a user's request to teleport to you or teleport you to them.

## Dependencies
There are no dependencies.
However, optional dependencies are:
- [areas](https://github.com/minetest-mods/areas)
- [intllib](https://github.com/minetest-mods/intllib)
- [beerchat](https://github.com/pandorabox-io/beerchat)
- [chat2](https://github.com/minetest-mods/chat2)

## Requirements
This mod requieres MT/MTG 5.0.0+ to run.
Older versions not supported.

## Bugfixes & suggestions
Report bugs or suggest ideas by [creating an issue](https://github.com/ChaosWormz/teleport-request/issues/new).
If you know how to fix an issue, or want something to be added, consider opening a [pull request](https://github.com/ChaosWormz/teleport-request/compare).

## License
[LGPL-2.1](https://github.com/ChaosWormz/teleport-request/blob/master/LICENSE.md) for everything.

## Contributors:
- [RobbieF](https://minetest.tv) | [GitHub](https://github.com/Cat5TV)
- [DonBatman](https://github.com/donbatman)
- [NathanS21](http://nathansalapat.com/) | [GitHub](https://github.com/NathanSalapat)
- [ChaosWormz](https://github.com/ChaosWormz)
- [Panquesito7](https://github.com/Panquesito7)
- [coil0](https://github.com/coil0)
- [Zeno-](https://github.com/Zeno-)
- [indriApollo](https://github.com/indriApollo)
- [Billy-S](https://github.com/Billy-S)
- Traxie21, the original creator of this mod (however, he/she does not have a GitHub account anymore).

All those who contributed to the original mod (please see `init.lua`).

## Configuring the mod
Open your `minetest.conf` located in your Minetest directory.
Set the values of the settings you'd like to.

Available options are:
```
tp.timeout_delay = 60
tp.enable_immediate_teleport = true
tp_enable_tpp_command = false
```
Those values are the default values of the mod.
You can also go to your Minetest, Settings tab, All settings, Mods, and you'll find `tpr` there.
Or another way to do it, is changing the values in `settingtypes.txt`.

## Installation
- Unzip the archive, rename the folder to tpr and
place it in ..minetest/mods/

- GNU/Linux: If you use a system-wide installation place
    it in ~/.minetest/mods/.

- If you only want this to be used in a single world, place
    the folder in ..worldmods/ in your world directory.

For further information or help, see:
https://wiki.minetest.net/Installing_Mods

## TODO:
- Make it so if a player attempts to teleport to coordinates within a protected area owned by another player, and that player is online, the owner receives a request to allow or deny the user from teleporting to their area.
- Add limitations to /tpc which only allow a user to teleport X number of blocks. Prevents users from teleporting to the edge of the world.
- Assess value in changing all tpr-based chat commands to one global command such as /tp to reduce the chance of confusion between tps_admin and the original mod (and also make it so people don't have to remember so many commands).
- Create a better sound effect for teleport and apply it to all teleport methods (not just /tpc)
- Rewrite to place all chat commands into one single command much like how /teleport works.
- Make evade respect land: no teleporting inside land, but instead make sure player is standing on surface or in water.

If you think something else should be added to this list, [submit an issue](https://github.com/ChaosWormz/teleport-request/issues/new).


code:
--[[
Configuration

Copyright (C) 2015-2019 ChaosWormz

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
USA
--]]

-- Load support for intllib.
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

-- Timeout delay and mod version.
tp.timeout_delay = tonumber(minetest.settings:get("tp.timeout_delay")) or 60
tp.version = "1.5"

-- Enable teleporting immediately to the specified player for those with "tp_admin" privilege.
tp.enable_immediate_teleport = minetest.settings:get_bool("tp.enable_immediate_teleport")

local chatmsg, source, target, name2, target_coords, pos

-- Set the values of the positions of your places, players will be able to teleport to them (no matter if it is protected, or not).
-- You must activate "enable_tpp_command" in order to make this to work.
tp.available_places = {
	spawn = {x = 0, y = 0, z = 0}, -- Set coordinates of spawn here.
	shop = {x = 0, y = 0, z = 0}, -- Set coordinates of the shop here.
}

-- Enable tpp command
tp.enable_tpp_command = minetest.settings:get_bool("tp.enable_tpp_command")

-- Register privileges
minetest.register_privilege("tp", {
	description = S("Let players teleport to other players (request will be sent)"),
	give_to_singleplayer = false,
	give_to_admin = true,
})

minetest.register_privilege("tp_admin", {
	description = S("Gives full admin-access to a player."),
	give_to_singleplayer = false,
	give_to_admin = true,
})

minetest.register_privilege("tp_tpc", {
	description = S("Allow player to teleport to coordinates (if allowed by area protection)"),
	give_to_singleplayer = false,
	give_to_admin = true,
})


code:
--[[
Copyright (C) 2015-2019 ChaosWormz

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
USA

----------------------------------------------------------------------------

Originally made by Traxie21 and released with the WTFPL license.
Forum link: https://forum.minetest.net/viewtopic.php?id=4457

Updates by Zeno, Panquesito7 and ChaosWormz.
License: LGPL-2.1 for everything.

Optional dependencies: areas, intllib
New release by RobbieF under new mod: tps_teleport - http://blog.minetest.tv/teleport-request/
--]]

tp = {}

-- Load support for intllib.
local MP = minetest.get_modpath(minetest.get_current_modname())
local S, NS = dofile(MP.."/intllib.lua")

-- Load configuration.
dofile(MP.."/config.lua")

tp.tpr_list = {}
tp.tphr_list = {}

local map_size = 30912
function tp.can_teleport(to)
	return to.x < map_size and to.x > -map_size and to.y < map_size and to.y > -map_size and to.z < map_size and to.z > -map_size
end

-- Teleport player to a player (used in "/tpr" and in "/tphr" command).
function tp.tpr_teleport_player()
	local target_coords = source:get_pos()
	local target_sound = target:get_pos()
	target:set_pos(tp.find_free_position_near(target_coords))
	minetest.sound_play("whoosh", {pos = target_coords, gain = 0.5, max_hear_distance = 10})
	minetest.sound_play("whoosh", {pos = target_sound, gain = 0.5, max_hear_distance = 10})
	--tp.parti2(target_coords)
end

-- TPC & TPJ
function tp.tpc_teleport_player(player)
	local pname = minetest.get_player_by_name(player)
	minetest.sound_play("whoosh", {pos = pname:get_pos(), gain = 0.5, max_hear_distance = 10})
	pname:set_pos(tp.find_free_position_near(target_coords))
	minetest.sound_play("whoosh", {pos = target_coords, gain = 0.5, max_hear_distance = 10})
	--tp.parti2(target_coords)
end

-- TPP
function tp.tpp_teleport_player(player)
	local pname = minetest.get_player_by_name(player)
	minetest.sound_play("whoosh", {pos = pname:get_pos(), gain = 0.5, max_hear_distance = 10})
	pname:set_pos(tp.find_free_position_near(pos))
	minetest.sound_play("whoosh", {pos = pos, gain = 0.5, max_hear_distance = 10})
	--tp.parti2(target_coords)
end

function tp.find_free_position_near(pos)
	local tries = {
		{x=1,y=0,z=0},
		{x=-1,y=0,z=0},
		{x=0,y=0,z=1},
		{x=0,y=0,z=-1},
	}
	for _,d in pairs(tries) do
		local p = vector.add(pos, d)
		if not minetest.registered_nodes[minetest.get_node(p).name].walkable then
			return p, true
		end
	end
	return pos, false
end

function tp.parti(pos)
	minetest.add_particlespawner(50, 0.4,
		{x=pos.x + 0.5, y=pos.y, z=pos.z + 0.5}, {x=pos.x - 0.5, y=pos.y, z=pos.z - 0.5},
		{x=0, y=5, z=0}, {x=0, y=0, z=0},
		{x=0, y=5, z=0}, {x=0, y=0, z=0},
		3, 5,
		3, 5,
		false,
		"tps_portal_parti.png")
end

function tp.parti2(pos)
	minetest.add_particlespawner(50, 0.4,
		{x=pos.x + 0.5, y=pos.y + 10, z=pos.z + 0.5}, {x=pos.x - 0.5, y=pos.y, z=pos.z - 0.5},
		{x=0, y=-5, z=0}, {x=0, y=0, z=0},
		{x=0, y=-5, z=0}, {x=0, y=0, z=0},
		3, 5,
		3, 5,
		false,
		"tps_portal_parti.png")
end

-- Teleport Request System
function tp.clear_tpr_list(name)
	if tp.tpr_list[name] then
		tp.tpr_list[name] = nil
		return
	end
end

function tp.clear_tphr_list(name)
	if tp.tphr_list[name] then
		tp.tphr_list[name] = nil
		return
	end
end

-- Clear requests when the player leaves
minetest.register_on_leaveplayer(function(name)
	if tp.tpr_list[name] then
		tp.tpr_list[name] = nil
		return
	end

	if tp.tphr_list[name] then
		tp.tphr_list[name] = nil
		return
	end
end)

function tp.tpr_send(sender, receiver)
	-- Compatibility with beerchat (UNTESTED)
		if minetest.get_modpath("beerchat") and not minetest.check_player_privs(sender, {tp_admin = true}) then
			if minetest.get_player_by_name(sender):get_attribute("beerchat:muted:" .. sender) then
				minetest.chat_send_player(sender, S("You are not allowed to send requests because you're muted."))
				if minetest.get_modpath("chat2") then
					chat2.send_message(minetest.get_player_by_name(sender), S("You are not allowed to send requests because you're muted."), 0xFFFFFF)
				end
			return
		end
	end
	if minetest.check_player_privs(sender, {tp_admin = true}) and tp.enable_immediate_teleport then
	if receiver == "" then
		minetest.chat_send_player(sender, S("Usage: /tpr <Player name>"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("Usage: /tpr <Player name>"), 0xFFFFFF)
		end
            return
	end
	if not minetest.get_player_by_name(receiver) then
		minetest.chat_send_player(sender, S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"), 0xFFFFFF)
		end
	    return
	end
		tp.tpr_list[receiver] = sender
	tp.tpr_accept(receiver)
			minetest.chat_send_player(sender, S("You are teleporting to @1.", receiver))
			if minetest.get_modpath("chat2") then
				chat2.send_message(minetest.get_player_by_name(sender), S("You are teleporting to @1.", receiver), 0xFFFFFF)
			end
		return
	end

	if receiver == "" then
		minetest.chat_send_player(sender, S("Usage: /tpr <Player name>"))
			if minetest.get_modpath("chat2") then
				chat2.send_message(minetest.get_player_by_name(sender), S("Usage: /tpr <Player name>"), 0xFFFFFF)
			end
		return
	end

	if not minetest.get_player_by_name(receiver) then
		minetest.chat_send_player(sender, S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"), 0xFFFFFF)
		end
		return
	end
	if minetest.get_modpath("chat2") then
		chat2.send_message(minetest.get_player_by_name(receiver), S("@1 is requesting to teleport to you. /tpy to accept", sender), 0xFFFFFF)
		chat2.send_message(minetest.get_player_by_name(sender), S("Teleport request sent! It will timeout in @1 seconds", tp.timeout_delay), 0xFFFFFF)
	end
	minetest.chat_send_player(receiver, S("@1 is requesting to teleport to you. /tpy to accept", sender))
	minetest.chat_send_player(sender, S("Teleport request sent! It will timeout in @1 seconds", tp.timeout_delay))
	-- Write name values to list and clear old values.
		tp.tpr_list[receiver] = sender
		-- Teleport timeout delay
		minetest.after(tp.timeout_delay, function(name)
		if tp.tpr_list[name] then
			tp.tpr_list[name] = nil
			minetest.chat_send_player(sender, S("Request timed-out."))
			minetest.chat_send_player(receiver, S("Request timed-out."))
			if minetest.get_modpath("chat2") then
				chat2.send_message(minetest.get_player_by_name(sender), S("Request timed-out."), 0xFFFFFF)
				chat2.send_message(minetest.get_player_by_name(receiver), S("Request timed-out."), 0xFFFFFF)
			end
			return
		end
	end, receiver)
end

function tp.tphr_send(sender, receiver)
	-- Compatibility with beerchat (UNTESTED)
		if minetest.get_modpath("beerchat") and not minetest.check_player_privs(sender, {tp_admin = true}) then
			if minetest.get_player_by_name(sender):get_attribute("beerchat:muted:" .. sender) then
				minetest.chat_send_player(sender, S("You are not allowed to send requests because you're muted."))
				if minetest.get_modpath("chat2") then
					chat2.send_message(minetest.get_player_by_name(sender), S("You are not allowed to send requests because you're muted."), 0xFFFFFF)
				end
			return
		end
	end
	if minetest.check_player_privs(sender, {tp_admin = true}) and tp.enable_immediate_teleport then
	if receiver == "" then
		minetest.chat_send_player(sender, S("Usage: /tphr <Player name>"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("Usage. /tphr <Player name>"), 0xFFFFFF)
		end
	    return
	end
	if not minetest.get_player_by_name(receiver) then
		minetest.chat_send_player(sender, S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"), 0xFFFFFF)
		end
	    return
	end
		tp.tphr_list[receiver] = sender
	tp.tpr_accept(receiver)
		minetest.chat_send_player(sender, S("@1 is teleporting to you.", receiver))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("@1 is teleporting to you.", receiver), 0xFFFFFF)
		end
		return
	end
	if receiver == "" then
		minetest.chat_send_player(sender, S("Usage: /tphr <Player name>"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(sender), S("Usage. /tphr <Player name>"), 0xFFFFFF)
		end
		return
	end

	if not minetest.get_player_by_name(receiver) then
		minetest.chat_send_player(sender, S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"))
		if minetest.get_modpath("chat2") then
				chat2.send_message(minetest.get_player_by_name(sender), S("There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"), 0xFFFFFF)
			end
		return
	end
	if minetest.get_modpath("chat2") then
		chat2.send_message(minetest.get_player_by_name(receiver), S("@1 is requesting that you teleport to them. /tpy to accept; /tpn to deny", sender), 0xFFFFFF)
		chat2.send_message(minetest.get_player_by_name(sender), S("Teleport request sent! It will timeout in @1 seconds", tp.timeout_delay), 0xFFFFFF)
	end
	minetest.chat_send_player(receiver, S("@1 is requesting that you teleport to them. /tpy to accept; /tpn to deny", sender))
	minetest.chat_send_player(sender, S("Teleport request sent! It will timeout in @1 seconds", tp.timeout_delay))
	-- Write name values to list and clear old values.
		tp.tphr_list[receiver] = sender
		-- Teleport timeout delay
		minetest.after(tp.timeout_delay, function(name)
		if tp.tphr_list[name] then
			tp.tphr_list[name] = nil
			minetest.chat_send_player(sender, S("Request timed-out."))
			minetest.chat_send_player(receiver, S("Request timed-out."))
				if minetest.get_modpath("chat2") then
					chat2.send_message(minetest.get_player_by_name(sender), S("Request timed-out"), 0xFFFFFF)
					chat2.send_message(minetest.get_player_by_name(receiver), S("Request timed-out"), 0xFFFFFF)
				end
			return
		end
	end, receiver)
end

function tp.tpc_send(player, coordinates)

	local posx,posy,posz = string.match(coordinates, "^(-?%d+), (-?%d+), (-?%d+)$")
	local pname = minetest.get_player_by_name(player)

	if posx ~= nil or posy ~= nil or posz ~= nil then
	  posx = tonumber(posx) + 0.0
	  posy = tonumber(posy) + 0.0
	  posz = tonumber(posz) + 0.0
	end

	if posx==nil or posy==nil or posz==nil or string.len(posx) > 6 or string.len(posy) > 6 or string.len(posz) > 6 then
		minetest.chat_send_player(player, S("Usage: /tpc <x, y, z>"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(player), S("Usage: /tpc <x, y, z>"), 0xFFFFFF)
		end
		return nil
	end

	target_coords = {x=posx, y=posy, z=posz}

	if tp.can_teleport(target_coords) == false then
		minetest.chat_send_player(player, S("You cannot teleport to a location outside the map!"))
	if minetest.get_modpath("chat2") then
		chat2.send_message(minetest.get_player_by_name(player), S("You cannot teleport to a location outside the map!"), 0xFFFFFF)
	end
		return nil
	end

	-- If the area is protected, reject the user's request to teleport to these coordinates
	-- In future release we'll actually query the player who owns the area, if they're online, and ask for their permission.
	-- Admin user (priv "tp_admin") overrides all protection
	if minetest.check_player_privs(pname, {tp_admin = true}) then
		tp.tpc_teleport_player(player)
		minetest.chat_send_player(player, S("Teleporting to: @1, @2, @3", posx, posy, posz))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(player), S("Teleporting to: @1, @2, @3", posx, posy, posz), 0xFFFFFF)
		end
	else
		if minetest.check_player_privs(pname, {tp_tpc = true}) then
			local protected = minetest.is_protected(target_coords,pname)
			if protected and minetest.get_modpath("areas") then
				if not areas:canInteract(target_coords, player) then
					local owners = areas:getNodeOwners(target_coords)
					minetest.chat_send_player(player, S("Error: @1 is protected by @2.", minetest.pos_to_string(target_coords), table.concat(owners, ", ")))
					if minetest.get_modpath("chat2") then
						chat2.send_message(minetest.get_player_by_name(player), S("Error: @1 is protected by @2.", minetest.pos_to_string(target_coords), table.concat(owners, ", ")), 0xFFFFFF)
					end
					return
				end
			end
			tp.tpc_teleport_player(player)
			minetest.chat_send_player(player, S("Teleporting to: @1, @2, @3", posx, posy, posz))
			if minetest.get_modpath("chat2") then
				chat2.send_message(minetest.get_player_by_name(player), S("Teleporting to: @1, @2, @3", posx, posy, posz), 0xFFFFFF)
			end
		else
			minetest.chat_send_player(player, S("Error: You do not have permission to teleport to those coordinates."))
			if minetest.get_modpath("chat2") then
				chat2.send_message(minetest.get_player_by_name(player), S("Error: You do not have permission to teleport to those coordinates."), 0xFFFFFF)
			end
			return
		end
	end
end

function tp.tpr_deny(name)
	if tp.tpr_list[name] then
		name2 = tp.tpr_list[name]
		minetest.chat_send_player(name2, S("Teleport request denied."))
		minetest.chat_send_player(name, S("You denied the request @1 sent you.", name2))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(name2), S("Teleport request denied."), 0xFFFFFF)
			chat2.send_message(minetest.get_player_by_name(name), S("You denied the request @1 sent you.", name2), 0xFFFFFF)
		end
		tp.tpr_list[name] = nil
	elseif tp.tphr_list[name] then
		name2 = tp.tphr_list[name]
		minetest.chat_send_player(name2, S("Teleport request denied."))
		minetest.chat_send_player(name, S("You denied the request @1 sent you.", name2))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(name2), S("Teleport request denied."), 0xFFFFFF)
			chat2.send_message(minetest.get_player_by_name(name), S("You denied the request @1 sent you.", name2), 0xFFFFFF)
		end
		tp.tphr_list[name] = nil
	else
		minetest.chat_send_player(name, S("Usage: /tpn allows you to deny teleport requests sent to you by other players."))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(name), S("Usage: /tpn allows you to deny teleport requests sent to you by other players."), 0xFFFFFF)
		end
		return
	end
end

-- Teleport Accept Systems
function tp.tpr_accept(name, param)
	-- Check to prevent constant teleporting.
	if not tp.tpr_list[name] and not tp.tphr_list[name] then
		minetest.chat_send_player(name, S("Usage: /tpy allows you to accept teleport requests sent to you by other players"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(name), S("Usage: /tpy allows you to accept teleport requests sent to you by other players"), 0xFFFFFF)
		end
		return
	end

	if tp.tpr_list[name] then
		name2 = tp.tpr_list[name]
		source = minetest.get_player_by_name(name)
		target = minetest.get_player_by_name(name2)
		chatmsg = S("@1 is teleporting to you.", name2)
		tp.tpr_list[name] = nil
	elseif tp.tphr_list[name] then
		name2 = tp.tphr_list[name]
		source = minetest.get_player_by_name(name2)
		target = minetest.get_player_by_name(name)
		chatmsg = S("You are teleporting to @1.", name2)
		tp.tphr_list[name] = nil
	else
		return
	end

	-- Could happen if either player disconnects (or timeout); if so just abort
	if not source
	or not target then
		minetest.chat_send_player(name, S("@1 doesn't exist, or just disconnected/left (by timeout).", name2))
		return
	end
	tp.tpr_teleport_player()
	minetest.chat_send_player(name2, S("Request Accepted!"))
	minetest.chat_send_player(name, chatmsg)
	if minetest.get_modpath("chat2") then
		chat2.send_message(minetest.get_player_by_name(name2), S("Request Accepted!"), 0xFFFFFF)
		chat2.send_message(minetest.get_player_by_name(name), chatmsg, 0xFFFFFF)
	end
end

-- Teleport Jump - Relative Position Teleportation by number of nodes
function tp.tpj(player, param)
	local pname = minetest.get_player_by_name(player)

	if param == "" then
		minetest.chat_send_player(player, S("Usage: <x|y|z> <number>"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(player), S("Usage: <x|y|z> <number>"), 0xFFFFFF)
		end
		return false
	end

	local args = param:split(" ") -- look into this. Can it crash if the player does not have two parameters?
	if #args < 2 then
		minetest.chat_send_player(player, S("Usage: <x|y|z> <number>"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(player), S("Usage: <x|y|z> <number>"), 0xFFFFFF)
		end
		return false
	end

	if not tonumber(args[2]) then
		return false, S("Not a number!")
	end

	-- Initially generate the target coords from the player's current position (since it's relative) and then perform the math.
	target_coords = minetest.get_player_by_name(player):get_pos()
	if args[1] == "x" then
		target_coords["x"] = target_coords["x"] + tonumber(args[2])
	elseif args[1] == "y" then
		target_coords["y"] = target_coords["y"] + tonumber(args[2])
	elseif args[1] == "z" then
		target_coords["z"] = target_coords["z"] + tonumber(args[2])
	else
		minetest.chat_send_player(player, S("Not a valid axis. Valid options are X, Y or Z"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(player), S("Not a valid axis. Valid options are X, Y or Z"), 0xFFFFFF)
		end
		return
	end
	if tp.can_teleport(target_coords) == false then
		minetest.chat_send_player(player, S("You cannot teleport to a location outside the map!"))
		if minetest.get_modpath("chat2") then
			chat2.send_message(minetest.get_player_by_name(player), S("You cannot teleport to a location outside the map!"), 0xFFFFFF)
		end
		return
	end
	tp.tpc_teleport_player(player)
end

-- Evade
function tp.tpe(player)
	if minetest.get_modpath("chat2") then
		chat2.send_message(minetest.get_player_by_name(player), S("EVADE!"), 0xFFFFFF)
	end
	minetest.chat_send_player(player, S("EVADE!"))
	local mindistance = 15
	local maxdistance = 50
	local times = math.random(6,20) -- how many times to jump - minimum,maximum
	local negatives = { '-','' } -- either it's this way or that way: the difference between -10 and 10
	local options = { 'x', 'y', 'z' }
	local isnegative = ''
	local distance = 0
	local axis = ''
	local iteration = 0
	for i = 1,times do
		-- do this every 1 second
		minetest.after(iteration,
			function()
				isnegative = negatives[math.random(2)] -- choose randomly whether this is this way or that
				distance = isnegative .. math.random(mindistance,maxdistance) -- the distance to jump
				axis = options[math.random(3)]
				local command = axis .. " " .. distance
				tp.tpj(player, command)
			end
		)
		iteration = iteration + 0.5
	end
end

-- Register chatcommands
if tp.enable_tpp_command then
	minetest.register_chatcommand("tpp", {
		description = S("Teleport to a place (i.e., spawn, shop)."),
		params = S("<place> | leave empty to see available places"),
		privs = {},
		func = function(player, param)
			local pname = minetest.get_player_by_name(player)

			-- Show the available places to the player (taken from shivajiva101's POI mod, thanks!).
			if param == "" then
			    local places = {}
				if not tp.available_places then tp.available_places = {} end
				for key, value in pairs(tp.available_places) do
					if minetest.get_modpath("chat2") then
						chat2.send_message(minetest.get_player_by_name(player), key, 0xFFFFFF)
					end
					table.insert(places, key)
				end
				if #places == 0 then
					if minetest.get_modpath("chat2") then
						chat2.send_message(minetest.get_player_by_name(player), S("There are no places yet."), 0xFFFFFF)
					end
					return true, S("There are no places yet.")
				end
					if minetest.get_modpath("chat2") then
						chat2.send_message(minetest.get_player_by_name(player), S("Usage: /tpp <place>"), 0xFFFFFF)
					end
					table.insert(places, S("Usage: /tpp <place>"))
					return true, table.concat(places, "\n")
			-- Teleport player to the specified place (taken from shivajiva101's POI mod, thanks!).
			elseif tp.available_places[param] then
				pos = {x = tp.available_places[param].x, y = tp.available_places[param].y, z = tp.available_places[param].z}
				tp.tpp_teleport_player(player)
				minetest.chat_send_player(player, S("Teleporting to @1.", param))
				if minetest.get_modpath("chat2") then
					chat2.send_message(minetest.get_player_by_name(player), S("Teleporting to @1.", param), 0xFFFFFF)
				end
			-- Check if the place exists.
			elseif not tp.available_places[param] then
				minetest.chat_send_player(player, S("There is no place by that name. Keep in mind this is case-sensitive."))
				if minetest.get_modpath("chat2") then
					chat2.send_message(minetest.get_player_by_name(player), S("There is no place by that name. Keep in mind this is case-sensitive."), 0xFFFFFF)
				end
			    return
			end
		end,
	})
end

minetest.register_chatcommand("tpr", {
	description = S("Request teleport to another player"),
	params = S("<playername> | leave playername empty to see help message"),
	privs = {interact = true, tp = true},
	func = tp.tpr_send
})

minetest.register_chatcommand("tphr", {
	description = S("Request player to teleport to you"),
	params = S("<playername> | leave playername empty to see help message"),
	privs = {interact = true, tp = true},
	func = tp.tphr_send
})

minetest.register_chatcommand("tpc", {
	description = S("Teleport to coordinates"),
	params = S("<coordinates> | leave coordinates empty to see help message"),
	privs = {interact = true, tp_tpc = true, tp = true},
	func = tp.tpc_send
})

minetest.register_chatcommand("tpj", {
	description = S("Teleport to relative position"),
	params = S("<axis> <distance> | leave empty to see help message"),
	privs = {interact = true, tp_tpc = true, tp = true},
	func = tp.tpj
})

minetest.register_chatcommand("tpe", {
	description = S("Evade Enemy"),
	privs = {interact = true, tp_tpc = true, tp = true},
	func = tp.tpe
})

minetest.register_chatcommand("tpy", {
	description = S("Accept teleport requests from another player"),
	privs = {interact = true, tp = true},
	func = tp.tpr_accept
})

minetest.register_chatcommand("tpn", {
	description = S("Deny teleport requests from another player"),
	privs = {interact = true, tp = true},
	func = tp.tpr_deny
})

-- Log
if minetest.settings:get_bool("log_mods") then
	minetest.log("action", S("[Teleport Request] TPS Teleport v@1 Loaded!", tp.version))
end


code:
-- Fallback functions for when `intllib` is not installed.
-- Code released under Unlicense <http://unlicense.org>.

-- Get the latest version of this file at:
--   https://raw.githubusercontent.com/minetest-mods/intllib/master/lib/intllib.lua

local function format(str, ...)
	local args = { ... }
	local function repl(escape, open, num, close)
		if escape == "" then
			local replacement = tostring(args[tonumber(num)])
			if open == "" then
				replacement = replacement..close
			end
			return replacement
		else
			return "@"..open..num..close
		end
	end
	return (str:gsub("(@?)@(%(?)(%d+)(%)?)", repl))
end

local gettext, ngettext
if minetest.get_modpath("intllib") then
	if intllib.make_gettext_pair then
		-- New method using gettext.
		gettext, ngettext = intllib.make_gettext_pair()
	else
		-- Old method using text files.
		gettext = intllib.Getter()
	end
end

-- Fill in missing functions.

gettext = gettext or function(msgid, ...)
	return format(msgid, ...)
end

ngettext = ngettext or function(msgid, msgid_plural, n, ...)
	return format(n==1 and msgid or msgid_plural, ...)
end

return gettext, ngettext


code:
# Spanish translation for Teleport Request.
# Copyright (C) 2015-2019 ChaosWormz and contributors.
# This file is distributed under under the same license as the Teleport Request package.
# Panquesito7, 2019.

msgid ""
msgstr ""
"Project-Id-Version: Teleport Request\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-12 5:07+0200\n"
"PO-Revision-Date: \n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: config.lua
msgid "Let players teleport to other players (request will be sent)"
msgstr "Permite que los jugadores se teletransporten a otros jugadores (se enviará una solicitud)"

#: config.lua
msgid "Gives full admin-access to a player."
msgstr "Da acceso total de administrador a un jugador."

#: config.lua
msgid "Allow player to teleport to coordinates (if allowed by area protection)"
msgstr "Permite a los jugadores teletransportarse a las coordenadas especificadas (si esta permitido por la protección de la área)"

#: init.lua
msgid "You are not allowed to send requests because you're muted."
msgstr "No tienes permiso para mandar solicitudes de teletransporte porque estás silenciado."

#: init.lua
msgid "Usage: /tpr <Player name>"
msgstr "Uso: /tpr <jugador>"

#: init.lua
msgid "There is no player by that name. Keep in mind this is case-sensitive, and the player must be online"
msgstr "No hay jugador con ese nombre. Tenga en cuenta que esto es caso-sensitivo, y el jugador debe de estar én linea."

#: init.lua
msgid "You are teleporting to @1."
msgstr "Te estas teletransportando a @1."

#: init.lua
msgid "@1 is requesting to teleport to you. /tpy to accept"
msgstr "@1 esta pidiendo teletransportarse a ti. /tpy para aceptar"

#: init.lua
msgid "Teleport request sent! It will timeout in @1 seconds"
msgstr "¡Solicitud enviada! Se agotara en @1 segundos"

#: init.lua
msgid "Request timed-out."
msgstr "La solicitud enviada expiró."

#: init.lua
msgid "@1 is teleporting to you."
msgstr "@1 se esta teletransportando a ti."

#: init.lua
msgid "Usage: /tphr <Player name>"
msgstr "Uso: /tphr <jugador>"

#: init.lua
msgid "@1 is requesting that you teleport to them. /tpy to accept; /tpn to deny"
msgstr "@1 esta pidiendo que tu te teletransportes a el/ella. /tpy para aceptar, /tpn para denegar"

#: init.lua
msgid "Usage: /tpc <x, y, z>"
msgstr "Uso: /tpc <x, y, z>"

#: init.lua
msgid "You cannot teleport to a location outside the map!"
msgstr "¡No puedes teletransportarte afuera del mundo!"

#: init.lua
msgid "Teleporting to: @1, @2, @3"
msgstr "Teletransportandose a: @1, @2, @3"

#: init.lua
msgid "Error: @1 is protected by @2."
msgstr "Error: @1 esta protegido por @2."

#: init.lua
msgid "Error: You do not have permission to teleport to those coordinates."
msgstr "Error: No tienes permiso para teletransportarte a esas coordenadas."

#: init.lua
msgid "Teleport request denied."
msgstr "Solicitud denegada."

#: init.lua
msgid "You denied the request @1 sent you."
msgstr "Tú denegaste la solicitud de teletransporte que @1 te mando."

#: init.lua
msgid "Usage: /tpn allows you to deny teleport requests sent to you by other players."
msgstr "Uso: /tpn te permite denegar solicitudes enviadas para ti de otros jugadores."

#: init.lua
msgid "Usage: /tpy allows you to accept teleport requests sent to you by other players"
msgstr "Uso: /tpy te permite aceptar solicitudes enviadas para ti de otros jugadores"

#: init.lua
msgid "@1 doesn't exist, or just disconnected/left (by timeout)."
msgstr "@1 no existe, o se desconecto/fue."

#: init.lua
msgid "Request Accepted!"
msgstr "¡Solicitud aceptada!"

#: init.lua
msgid "Usage: <x|y|z> <number>"
msgstr "Uso: <x|y|z> <numero>"

#: init.lua
msgid "Not a number!"
msgstr "¡No un número!"

#: init.lua
msgid "Not a valid axis. Valid options are X, Y or Z"
msgstr "Eje invalido. Opciones validas son x, y, o z"

#: init.lua
msgid "EVADE!"
msgstr "¡EVADIR!"

#: init.lua
msgid "Request teleport to another player."
msgstr "Enviar solicitud para teletransportarte a otro jugador."

#: init.lua
msgid "<playername> | leave playername empty to see help message"
msgstr "<jugador> | Deje el nombre del jugador vacío para ver el mensaje de ayuda"

#: init.lua
msgid "Request player to teleport to you"
msgstr "Solicita al jugador que se teletransporte a ti."

#: init.lua
msgid "Teleport to coordinates"
msgstr "Teletransportarse a las coordenadas especificadas."

#: init.lua
msgid "<coordinates> | leave coordinates empty to see help message"
msgstr "<coordenadas> | Deje las coordenadas vacías para ver el mensaje de ayuda"

#: init.lua
msgid "Teleport to relative position"
msgstr "Teletransportarse a la posición relativa."

#: init.lua
msgid "<axis> <distance> | leave empty to see help message"
msgstr "<eje> <distancia> | Deje vacío para ver el mensaje de ayuda"

#: init.lua
msgid "Evade Enemy"
msgstr "Evadir enemigo."

#: init.lua
msgid "Teleport to a place (i.e., spawn, shop)."
msgstr "Teletransportarse a un lugar (p.ej., la tienda, la ciudad)."

#: init.lua
msgid "<place> | leave empty to see available places"
msgstr "<lugar> | Deje vacío para ver los lugares disponibles"

#: init.lua
msgid "There are no places yet."
msgstr "Todavia no hay lugares."

#: init.lua
msgid "Usage: /tpp <place>"
msgstr "Uso: /tpp <lugar>"

#: init.lua
msgid "Teleporting to @1."
msgstr "Teletransportandose a @1."

#: init.lua
msgid "There is no place by that name. Keep in mind this is case-sensitive."
msgstr "No hay lugar con ese nombre. Tenga en cuenta que esto es caso-sensitivo."

#: init.lua
msgid "Accept teleport requests from another player"
msgstr "Aceptar solicitudes de otro jugador."

#: init.lua
msgid "Deny teleport requests from another player"
msgstr "Denegar solicitudos de otro jugador."

#: init.lua
msgid "[Teleport Request] TPS Teleport v@1 Loaded!"
msgstr "[TPS] Solicitud de teletransporte v@1 Cargado!"


code:
# Template translation for Teleport Request.
# Copyright (C) 2015-2019 ChaosWormz and contributors.
# This file is distributed under under the same license as the Teleport Request package.
# Panquesito7, 2019.

msgid ""
msgstr ""
"Project-Id-Version: Teleport Request\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-07-12 5:07+0200\n"
"PO-Revision-Date: \n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: \n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: config.lua
msgid "Let players teleport to other players (request will be sent)"
msgstr ""

#: config.lua
msgid "Gives full admin-access to a player."
msgstr ""

#: config.lua
msgid "Allow player to teleport to coordinates (if allowed by area protection)"
msgstr ""

#: init.lua
msgid "You are not allowed to send requests because you're muted."
msgstr ""

#: init.lua
msgid "Usage: /tpr <Player name>"
msgstr ""

#: init.lua
msgid "There is no player by that name. Keep in mind this is case sensitive, and the player must be online"
msgstr ""

#: init.lua
msgid "You are teleporting to @1."
msgstr ""

#: init.lua
msgid "@1 is requesting to teleport to you. /tpy to accept"
msgstr ""

#: init.lua
msgid "Teleport request sent! It will timeout in @1 seconds"
msgstr ""

#: init.lua
msgid "Request timed-out."
msgstr ""

#: init.lua
msgid "@1 is teleporting to you."
msgstr ""

#: init.lua
msgid "Usage: /tphr <Player name>"
msgstr ""

#: init.lua
msgid "@1 is requesting that you teleport to them. /tpy to accept; /tpn to deny"
msgstr ""

#: init.lua
msgid "Usage: /tpc <x, y, z>"
msgstr ""

#: init.lua
msgid "You cannot teleport to a location outside the map!"
msgstr ""

#: init.lua
msgid "Teleporting to: @1, @2, @3"
msgstr ""

#: init.lua
msgid "Error: @1 is protected by @2."
msgstr ""

#: init.lua
msgid "Error: You do not have permission to teleport to those coordinates."
msgstr ""

#: init.lua
msgid "Teleport request denied."
msgstr ""

#: init.lua
msgid "You denied the request @1 sent you."
msgstr ""

#: init.lua
msgid "Usage: /tpn allows you to deny teleport requests sent to you by other players."
msgstr ""

#: init.lua
msgid "Usage: /tpy allows you to accept teleport requests sent to you by other players"
msgstr ""

#: init.lua
msgid "@1 doesn't exist, or just disconnected/left (by timeout)."
msgstr ""

#: init.lua
msgid "Request Accepted!"
msgstr ""

#: init.lua
msgid "Usage: <x|y|z> <number>"
msgstr ""

#: init.lua
msgid "Not a number!"
msgstr ""

#: init.lua
msgid "Not a valid axis. Valid options are X, Y or Z"
msgstr ""

#: init.lua
msgid "EVADE!"
msgstr ""

#: init.lua
msgid "Teleport to a place (i.e., spawn, shop)."
msgstr ""

#: init.lua
msgid "<place> | leave empty to see available places"
msgstr ""

#: init.lua
msgid "There are no places yet."
msgstr ""

#: init.lua
msgid "Usage: /tpp <place>"
msgstr ""

#: init.lua
msgid "Teleporting to @1."
msgstr ""

#: init.lua
msgid "There is no place by that name. Keep in mind this is case-sensitive."
msgstr ""

#: init.lua
msgid "Request teleport to another player."
msgstr ""

#: init.lua
msgid "<playername> | leave playername empty to see help message"
msgstr ""

#: init.lua
msgid "Request player to teleport to you"
msgstr ""

#: init.lua
msgid "Teleport to coordinates"
msgstr ""

#: init.lua
msgid "<coordinates> | leave coordinates empty to see help message"
msgstr ""

#: init.lua
msgid "Teleport to relative position"
msgstr ""

#: init.lua
msgid "<axis> <distance> | leave empty to see help message"
msgstr ""

#: init.lua
msgid "Evade Enemy"
msgstr ""

#: init.lua
msgid "Accept teleport requests from another player"
msgstr ""

#: init.lua
msgid "Deny teleport requests from another player"
msgstr ""

#: init.lua
msgid "[Teleport Request] TPS Teleport v@1 Loaded!"
msgstr ""


code:
name = tpr
optional_depends = areas, intllib, beerchat, chat2
description = Allows players to send a request to other players to teleport to them, and do much more.
release = 2152
title = Teleport Request
author = Traxie21


code:
# Timeout delay (default is 60)
tp.timeout_delay (Timeout delay after a request is sent) int 60

# Enables immediate teleport to players for those who have tp_admin privilege (enabled by default)
tp.enable_immediate_teleport (Immediate teleport for those with tp_admin privilege) bool true

# Enables Teleport To Place command (disabled by default)
tp.enable_tpp_command (Enable Teleport To Place command) bool false


code:
# TravelNet

How this works:

- craft it by filling the right and left row with glass; place in the middle row (from top to bottom): steel, mese, steel
- place the travelnet box somewhere
- right-click on it; enter name of the station (e.g. "my house", "center of desert city") and name of the network (e.g. "intresting towns","my buildings")
- punch it to update the list of stations on that network
- right-click to use the travelbox

An unconfigured travelnet box can be configured by anyone. If it is misconfigured, just dig it and place it anew.
All stations that have the same network name set and are owned by the same user connect to the same network.

LICENSE

The mod was written by me, Sokomine, and includes small contributions from other contributors.
License: GPLv3 (see file LICENSE)

The models and textures as found in the textures/ and models/ folders where created by VanessaE
and are provided under the CC0 license.


code:
travelnet.MAX_STATIONS_PER_NETWORK = 128;

-- set this to true if you want a simulated beam effect
travelnet.travelnet_effect_enabled = true;
-- set this to true if you want a sound to be played when the travelnet is used
travelnet.travelnet_sound_enabled  = true;

-- if you set this to false, travelnets cannot be created
-- (this may be useful if you want nothing but the elevators on your server)
travelnet.travelnet_enabled        = true;
-- if you set travelnet.elevator_enabled to false, you will not be able to
-- craft, place or use elevators
travelnet.elevator_enabled         = true;
-- if you set this to false, doors will be disabled
travelnet.doors_enabled            = true;

-- starts an abm which re-adds travelnet stations to networks in case the savefile got lost
travelnet.abm_enabled              = true;

-- change these if you want other receipes for travelnet or elevator
travelnet.travelnet_recipe = {
                {"default:glass", "default:steel_ingot", "default:glass", },
                {"default:glass", "default:mese",        "default:glass", },
                {"default:glass", "default:steel_ingot", "default:glass", }
}
travelnet.elevator_recipe = {
	        {"default:steel_ingot", "default:glass", "default:steel_ingot", },
		{"default:steel_ingot", "",              "default:steel_ingot", },
		{"default:steel_ingot", "default:glass", "default:steel_ingot", }
}
travelnet.tiles_travelnet = {
		"travelnet_travelnet_front.png",  -- backward view
		"travelnet_travelnet_back.png", -- front view
		"travelnet_travelnet_side.png", -- sides :)
		"default_steel_block.png",  -- view from top
		"default_clay.png",  -- view from bottom
		}
travelnet.tiles_elevator = {
		"travelnet_elevator_front.png",
		"travelnet_elevator_inside_controls.png",
		"travelnet_elevator_sides_outside.png",
		"travelnet_elevator_inside_ceiling.png",
		"travelnet_elevator_inside_floor.png",
		"default_steel_block.png"
		}
travelnet.travelnet_inventory_image = "travelnet_inv.png"
travelnet.elevator_inventory_image  = "travelnet_elevator_inv.png"

if( minetest.registered_nodes["mcl_core:wood"]) then
	local w_texture = "default_wood.png^[transformR90"; -- "mcl_doors_door_spruce_lower.png";
	travelnet.travelnet_recipe = {
                {"mcl_stairs:slab_wood", "mcl_stairs:slab_wood", "mcl_stairs:slab_wood",},
		{"mesecons_torch:mesecon_torch_on", "mcl_chests:chest", "mesecons_torch:mesecon_torch_on"},
		{"mesecons_torch:mesecon_torch_on", "mcl_chests:chest", "mesecons_torch:mesecon_torch_on"},
--		  {"core:glass", "mcl_core:iron_ingot",           "mcl_core:glass", },
--                {"mcl_core:glass", "mesecons_torch:redstoneblock", "mcl_core:glass", },
--                {"mcl_core:glass", "mcl_core:iron_ingot",           "mcl_core:glass", }
	}
	travelnet.elevator_recipe = {
                {"mcl_stairs:slab_wood", "mcl_stairs:slab_wood", "mcl_stairs:slab_wood",},
		{"mesecons_torch:mesecon_torch_on", "", "mesecons_torch:mesecon_torch_on"},
		{"mesecons_torch:mesecon_torch_on", "", "mesecons_torch:mesecon_torch_on"},
--	        {"mcl_core:iron_ingot", "mcl_core:glass", "mcl_core:iron_ingot", },
--		{"mcl_core:iron_ingot", "",               "mcl_core:iron_ingot", },
--		{"mcl_core:iron_ingot", "mcl_core:glass", "mcl_core:iron_ingot", }
	}
	travelnet.tiles_travelnet = {
		w_texture,  -- backward view
		w_texture, -- front view
		w_texture, -- sides :)
		w_texture,  -- view from top
		w_texture,  -- view from bottom
	}
	travelnet.tiles_elevator = {
		"mcl_core_planks_big_oak.png^[transformR90", -- front
		"mcl_core_planks_big_oak.png^[transformR90", -- inside
		"mcl_core_planks_big_oak.png^[transformR90", -- sides outside
		"mcl_core_planks_big_oak.png^[transformR90", -- inside ceiling
		"mcl_core_planks_big_oak.png^[transformR90", -- inside floor
		"mcl_core_planks_big_oak.png^[transformR90", -- top
		}
	travelnet.travelnet_inventory_image = nil
	travelnet.elevator_inventory_image  = nil
end

-- if this function returns true, the player with the name player_name is
-- allowed to add a box to the network named network_name, which is owned
-- by the player owner_name;
-- if you want to allow *everybody* to attach stations to all nets, let the
-- function always return true;
-- if the function returns false, players with the travelnet_attach priv
-- can still add stations to that network

travelnet.allow_attach = function( player_name, owner_name, network_name )
   return false;
end

-- if this returns true, a player named player_name can remove a travelnet station
-- from network_name (owned by owner_name) even though he is neither the owner nor
-- has the travelnet_remove priv
travelnet.allow_dig    = function( player_name, owner_name, network_name )
   return false;
end

-- if this function returns false, then player player_name will not be allowed to use
-- the travelnet station_name_start on networ network_name owned by owner_name to travel to
-- the station station_name_target on the same network;
-- if this function returns true, the player will be transfered to the target station;
-- you can use this code to i.e. charge the player money for the transfer or to limit
-- usage of stations to players in the same fraction on PvP servers
travelnet.allow_travel = function( player_name, owner_name, network_name, station_name_start, station_name_target )

   --minetest.chat_send_player( player_name, "Player "..tostring( player_name ).." tries to use station "..tostring( station_name_start )..
   --    " on network "..tostring( network_name ).." owned by "..tostring( owner_name ).." in order to travel to "..
   --    tostring( station_name_target )..".");

   return true;
end

travelnet.travelnet_sound_enabled = true


code:
mesecons?
intllib?


code: Network of teleporter-boxes that allow easy travelling to other boxes on the same network.


code:
-- Doors that are especially useful for travelnet elevators but can also be used in other situations.
-- All doors (not only these here) in front of a travelnet or elevator are opened automaticly when a player arrives
-- and are closed when a player departs from the travelnet or elevator.
-- Autor: Sokomine
local S = travelnet.S;

travelnet.register_door = function( node_base_name, def_tiles, material )

	minetest.register_node( node_base_name.."_open", {
		description = S("elevator door (open)"),
		drawtype = "nodebox",
                -- top, bottom, side1, side2, inner, outer
		tiles = def_tiles,
		paramtype = "light",
		paramtype2 = "facedir",
		is_ground_content = true,
		-- only the closed variant is in creative inventory
		groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2,not_in_creative_inventory=1},
                -- larger than one node but slightly smaller than a half node so that wallmounted torches pose no problem
		node_box = {
			type = "fixed",
			fixed = {
				{-0.90, -0.5,  0.4, -0.49, 1.5,  0.5},
				{ 0.49, -0.5,  0.4,  0.9, 1.5,  0.5},
			},
		},
		selection_box = {
			type = "fixed",
			fixed = {
				{-0.9, -0.5,  0.4,  0.9, 1.5,  0.5},
			},
		},
		drop = node_base_name.."_closed",
                on_rightclick = function(pos, node, puncher)
                    minetest.add_node(pos, {name = node_base_name.."_closed", param2 = node.param2})
                end,
	})

	minetest.register_node(node_base_name.."_closed", {
		description = S("elevator door (closed)"),
		drawtype = "nodebox",
                -- top, bottom, side1, side2, inner, outer
		tiles = def_tiles,
		paramtype = "light",
		paramtype2 = "facedir",
		is_ground_content = true,
		groups = {snappy=2,choppy=2,oddly_breakable_by_hand=2},
		node_box = {
			type = "fixed",
			fixed = {
				{-0.5,  -0.5,  0.4, -0.01, 1.5,  0.5},
				{ 0.01, -0.5,  0.4,  0.5,  1.5,  0.5},
			},
		},
		selection_box = {
			type = "fixed",
			fixed = {
				{-0.5, -0.5,  0.4,  0.5, 1.5,  0.5},
			},
		},
                on_rightclick = function(pos, node, puncher)
                    minetest.add_node(pos, {name = node_base_name.."_open", param2 = node.param2})
                end,
	})

	-- add a craft receipe for the door
	minetest.register_craft({
	        output = node_base_name.."_closed",
	        recipe = {
		        {material, '', material },
			{material, '', material },
			{material, '', material }
		        }
	})

	-- Make doors reacts to mesecons
	if minetest.get_modpath("mesecons") then
		local mesecons = {effector = {
			action_on = function(pos, node)
			minetest.add_node(pos, {name = node_base_name.."_open", param2 = node.param2})
		end,
		action_off = function(pos, node)
			minetest.add_node(pos, {name = node_base_name.."_closed", param2 = node.param2})
		end,
		rules = mesecon.rules.pplate
	}}

	minetest.override_item( node_base_name.."_closed", { mesecons = mesecons })
	minetest.override_item( node_base_name.."_open", { mesecons = mesecons })
   end
end

-- actually register the doors
-- (but only if the materials for them exist)
if( minetest.registered_nodes["default:glass"]) then
   travelnet.register_door( "travelnet:elevator_door_steel", {"default_stone.png"}, "default:steel_ingot");
   travelnet.register_door( "travelnet:elevator_door_glass", {"travelnet_elevator_door_glass.png"}, "default:glass");
   travelnet.register_door( "travelnet:elevator_door_tin", {"default_clay.png"}, "default:tin_ingot");
end