summaryrefslogtreecommitdiff
path: root/teleport_request/init.lua
blob: e57b5925b3a1a5137d52357442bc1f0ee26fa3a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
-- Originally Teleport Request by Traxie21 and released with the WTFPL license
-- https://forum.minetest.net/viewtopic.php?id=4457
-- Updates by Zeno and ChaosWormz
-- New release by RobbieF under new mod: tps_teleport - http://blog.minetest.tv/teleport-request/

local timeout_delay = 60

local version = "1.3"

local tpr_list = {}
local tphr_list = {}

minetest.register_privilege("tp_admin", {
	description = "Admin overrides for tps_teleport.",
	give_to_singleplayer=false
})
minetest.register_privilege("tp_tpc", {
	description = "Allow player to teleport to coordinates (if permitted by area protection).",
	give_to_singleplayer=true
})

local function 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

local function 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

local function 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
local function tpr_send(sender, receiver)
	if receiver == "" then
		minetest.chat_send_player(sender, "Usage: /tpr <Player name>")
		return
	end

	--If paremeter is valid, Send teleport message and set the table.
	if not minetest.get_player_by_name(receiver) then
		return
	end

	minetest.chat_send_player(receiver, sender ..' is requesting to teleport to you. /tpy to accept.')
	minetest.chat_send_player(sender, 'Teleport request sent! It will time out in '.. timeout_delay ..' seconds.')

	--Write name values to list and clear old values.
	tpr_list[receiver] = sender
	--Teleport timeout delay
	minetest.after(timeout_delay, function(name)
		if tpr_list[name] then
			tpr_list[name] = nil
		end
	end, sender)
end

local function tphr_send(sender, receiver)
	if receiver == "" then
		minetest.chat_send_player(sender, "Usage: /tphr <Player name>")
		return
	end

	--If paremeter is valid, Send teleport message and set the table.
	if not minetest.get_player_by_name(receiver) then
		return
	end

	minetest.chat_send_player(receiver, sender ..' is requesting that you teleport to them. /tpy to accept; /tpn to deny')
	minetest.chat_send_player(sender, 'Teleport request sent! It will time out in '.. timeout_delay ..' seconds.')

	--Write name values to list and clear old values.
	tphr_list[receiver] = sender
	--Teleport timeout delay
	minetest.after(timeout_delay, function(name)
		if tphr_list[name] then
			tphr_list[name] = nil
		end
	end, sender)
end

local function 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, "Usage: /tpc <x,y,z>")
		return nil
	end
	
	if posx > 32765 or posx < -32765 or posy > 32765 or posy < -32765 or posz > 32765 or posz < -32765 then
		minetest.chat_send_player(player, "Error: Invalid coordinates.")
		return nil
	end

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

	-- 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
		minetest.chat_send_player(player, 'Teleporting to '..posx..','..posy..','..posz)
		pname:setpos(find_free_position_near(target_coords))
		minetest.sound_play("whoosh", {pos = target_coords, gain = 0.5, max_hear_distance = 10})
		parti2(target_coords)
	else
		if minetest.check_player_privs(pname, {tp_tpc=true}) then
			local protected = minetest.is_protected(target_coords,pname)
			if protected then
				if not areas:canInteract(target_coords, player) then
					local owners = areas:getNodeOwners(target_coords)
					minetest.chat_send_player(player,("Error: %s is protected by %s."):format(minetest.pos_to_string(target_coords),table.concat(owners, ", ")))
					return
				end
			end
			minetest.chat_send_player(player, 'Teleporting to '..posx..','..posy..','..posz)
			pname:setpos(find_free_position_near(target_coords))
			minetest.sound_play("whoosh", {pos = target_coords, gain = 0.5, max_hear_distance = 10})
			parti2(target_coords)
		else
			minetest.chat_send_player(player, "Error: You do not have permission to teleport to coordinates.")	
			return
		end
	end
end

local function tpr_deny(name)
	if tpr_list[name] then
		minetest.chat_send_player(tpr_list[name], 'Teleport request denied.')
		tpr_list[name] = nil
	end
	if tphr_list[name] then
		minetest.chat_send_player(tphr_list[name], 'Teleport request denied.')
		tphr_list[name] = nil
	end
end

--Teleport Accept Systems
local function tpr_accept(name, param)

	--Check to prevent constant teleporting.
	if not tpr_list[name]
	and not tphr_list[name] then
		minetest.chat_send_player(name, "Usage: /tpy allows you to accept teleport requests sent to you by other players.")
		return
	end

	local chatmsg, source, target, name2

	if tpr_list[name] then
		name2 = tpr_list[name]
		source = minetest.get_player_by_name(name)
		target = minetest.get_player_by_name(name2)
		chatmsg = name2 .. " is teleporting to you."
		tpr_list[name] = nil
	elseif tphr_list[name] then
		name2 = tphr_list[name]
		source = minetest.get_player_by_name(name2)
		target = minetest.get_player_by_name(name)
		chatmsg = "You are teleporting to " .. name2 .. "."
		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
		return
	end

	minetest.chat_send_player(name2, "Request Accepted!")
	minetest.chat_send_player(name, chatmsg)
	
	local target_coords=source:getpos()
	target:setpos(find_free_position_near(target_coords))
	minetest.sound_play("whoosh", {pos = target_coords, gain = 0.5, max_hear_distance = 10})
	parti2(target_coords)
end

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

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

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

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

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

minetest.log("info", "[Teleport Request] TPS Teleport v" .. version .. " Loaded.")