@@ -418,121 +418,111 @@ core.register_chatcommand("remove_player", {
418
418
end ,
419
419
})
420
420
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
+
421
485
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>" ,
423
487
description = " Teleport to position or player" ,
424
488
privs = {teleport = true },
425
489
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
-
447
490
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 )
452
493
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 )
466
495
end
467
496
468
497
local target_name = param :match (" ^([^ ]+)$" )
469
- local teleportee = core .get_player_by_name (name )
470
-
471
- p = nil
472
498
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 )
477
500
end
478
501
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)"
488
505
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 = {}
495
506
local teleportee_name
496
507
teleportee_name , p .x , p .y , p .z = param :match (
497
508
" ^([^ ]+) +([%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
505
513
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 )
509
515
end
510
516
511
- teleportee = nil
512
- p = nil
513
517
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
526
521
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 )
532
523
end
533
524
534
- return false , ' Invalid parameters ("' .. param
535
- .. ' ") or player not found (see /help teleport)'
525
+ return false
536
526
end ,
537
527
})
538
528
0 commit comments