Skip to content

Commit 92f4c68

Browse files
authoredFeb 24, 2021
Restructure teleport command code (#9706)
1 parent 8272246 commit 92f4c68

File tree

1 file changed

+82
-92
lines changed

1 file changed

+82
-92
lines changed
 

Diff for: ‎builtin/game/chat.lua

+82-92
Original file line numberDiff line numberDiff line change
@@ -418,121 +418,111 @@ core.register_chatcommand("remove_player", {
418418
end,
419419
})
420420

421+
422+
-- pos may be a non-integer position
423+
local function find_free_position_near(pos)
424+
local tries = {
425+
{x=1, y=0, z=0},
426+
{x=-1, y=0, z=0},
427+
{x=0, y=0, z=1},
428+
{x=0, y=0, z=-1},
429+
}
430+
for _, d in ipairs(tries) do
431+
local p = vector.add(pos, d)
432+
local n = core.get_node_or_nil(p)
433+
if n then
434+
local def = core.registered_nodes[n.name]
435+
if def and not def.walkable then
436+
return p
437+
end
438+
end
439+
end
440+
return pos
441+
end
442+
443+
-- Teleports player <name> to <p> if possible
444+
local function teleport_to_pos(name, p)
445+
local lm = 31000
446+
if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm
447+
or p.z < -lm or p.z > lm then
448+
return false, "Cannot teleport out of map bounds!"
449+
end
450+
local teleportee = core.get_player_by_name(name)
451+
if not teleportee then
452+
return false, "Cannot get player with name " .. name
453+
end
454+
if teleportee:get_attach() then
455+
return false, "Cannot teleport, " .. name ..
456+
" is attached to an object!"
457+
end
458+
teleportee:set_pos(p)
459+
return true, "Teleporting " .. name .. " to " .. core.pos_to_string(p, 1)
460+
end
461+
462+
-- Teleports player <name> next to player <target_name> if possible
463+
local function teleport_to_player(name, target_name)
464+
if name == target_name then
465+
return false, "One does not teleport to oneself."
466+
end
467+
local teleportee = core.get_player_by_name(name)
468+
if not teleportee then
469+
return false, "Cannot get teleportee with name " .. name
470+
end
471+
if teleportee:get_attach() then
472+
return false, "Cannot teleport, " .. name ..
473+
" is attached to an object!"
474+
end
475+
local target = core.get_player_by_name(target_name)
476+
if not target then
477+
return false, "Cannot get target player with name " .. target_name
478+
end
479+
local p = find_free_position_near(target:get_pos())
480+
teleportee:set_pos(p)
481+
return true, "Teleporting " .. name .. " to " .. target_name .. " at " ..
482+
core.pos_to_string(p, 1)
483+
end
484+
421485
core.register_chatcommand("teleport", {
422-
params = "<X>,<Y>,<Z> | <to_name> | (<name> <X>,<Y>,<Z>) | (<name> <to_name>)",
486+
params = "<X>,<Y>,<Z> | <to_name> | <name> <X>,<Y>,<Z> | <name> <to_name>",
423487
description = "Teleport to position or player",
424488
privs = {teleport=true},
425489
func = function(name, param)
426-
-- Returns (pos, true) if found, otherwise (pos, false)
427-
local function find_free_position_near(pos)
428-
local tries = {
429-
{x=1,y=0,z=0},
430-
{x=-1,y=0,z=0},
431-
{x=0,y=0,z=1},
432-
{x=0,y=0,z=-1},
433-
}
434-
for _, d in ipairs(tries) do
435-
local p = {x = pos.x+d.x, y = pos.y+d.y, z = pos.z+d.z}
436-
local n = core.get_node_or_nil(p)
437-
if n and n.name then
438-
local def = core.registered_nodes[n.name]
439-
if def and not def.walkable then
440-
return p, true
441-
end
442-
end
443-
end
444-
return pos, false
445-
end
446-
447490
local p = {}
448-
p.x, p.y, p.z = string.match(param, "^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
449-
p.x = tonumber(p.x)
450-
p.y = tonumber(p.y)
451-
p.z = tonumber(p.z)
491+
p.x, p.y, p.z = param:match("^([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
492+
p = vector.apply(p, tonumber)
452493
if p.x and p.y and p.z then
453-
454-
local lm = 31000
455-
if p.x < -lm or p.x > lm or p.y < -lm or p.y > lm or p.z < -lm or p.z > lm then
456-
return false, "Cannot teleport out of map bounds!"
457-
end
458-
local teleportee = core.get_player_by_name(name)
459-
if teleportee then
460-
if teleportee:get_attach() then
461-
return false, "Can't teleport, you're attached to an object!"
462-
end
463-
teleportee:set_pos(p)
464-
return true, "Teleporting to "..core.pos_to_string(p)
465-
end
494+
return teleport_to_pos(name, p)
466495
end
467496

468497
local target_name = param:match("^([^ ]+)$")
469-
local teleportee = core.get_player_by_name(name)
470-
471-
p = nil
472498
if target_name then
473-
local target = core.get_player_by_name(target_name)
474-
if target then
475-
p = target:get_pos()
476-
end
499+
return teleport_to_player(name, target_name)
477500
end
478501

479-
if teleportee and p then
480-
if teleportee:get_attach() then
481-
return false, "Can't teleport, you're attached to an object!"
482-
end
483-
p = find_free_position_near(p)
484-
teleportee:set_pos(p)
485-
return true, "Teleporting to " .. target_name
486-
.. " at "..core.pos_to_string(p)
487-
end
502+
local has_bring_priv = core.check_player_privs(name, {bring=true})
503+
local missing_bring_msg = "You don't have permission to teleport " ..
504+
"other players (missing bring privilege)"
488505

489-
if not core.check_player_privs(name, {bring=true}) then
490-
return false, "You don't have permission to teleport other players (missing bring privilege)"
491-
end
492-
493-
teleportee = nil
494-
p = {}
495506
local teleportee_name
496507
teleportee_name, p.x, p.y, p.z = param:match(
497508
"^([^ ]+) +([%d.-]+)[, ] *([%d.-]+)[, ] *([%d.-]+)$")
498-
p.x, p.y, p.z = tonumber(p.x), tonumber(p.y), tonumber(p.z)
499-
if teleportee_name then
500-
teleportee = core.get_player_by_name(teleportee_name)
501-
end
502-
if teleportee and p.x and p.y and p.z then
503-
if teleportee:get_attach() then
504-
return false, "Can't teleport, player is attached to an object!"
509+
p = vector.apply(p, tonumber)
510+
if teleportee_name and p.x and p.y and p.z then
511+
if not has_bring_priv then
512+
return false, missing_bring_msg
505513
end
506-
teleportee:set_pos(p)
507-
return true, "Teleporting " .. teleportee_name
508-
.. " to " .. core.pos_to_string(p)
514+
return teleport_to_pos(teleportee_name, p)
509515
end
510516

511-
teleportee = nil
512-
p = nil
513517
teleportee_name, target_name = string.match(param, "^([^ ]+) +([^ ]+)$")
514-
if teleportee_name then
515-
teleportee = core.get_player_by_name(teleportee_name)
516-
end
517-
if target_name then
518-
local target = core.get_player_by_name(target_name)
519-
if target then
520-
p = target:get_pos()
521-
end
522-
end
523-
if teleportee and p then
524-
if teleportee:get_attach() then
525-
return false, "Can't teleport, player is attached to an object!"
518+
if teleportee_name and target_name then
519+
if not has_bring_priv then
520+
return false, missing_bring_msg
526521
end
527-
p = find_free_position_near(p)
528-
teleportee:set_pos(p)
529-
return true, "Teleporting " .. teleportee_name
530-
.. " to " .. target_name
531-
.. " at " .. core.pos_to_string(p)
522+
return teleport_to_player(teleportee_name, target_name)
532523
end
533524

534-
return false, 'Invalid parameters ("' .. param
535-
.. '") or player not found (see /help teleport)'
525+
return false
536526
end,
537527
})
538528

0 commit comments

Comments
 (0)
Please sign in to comment.