C#:
using System.Collections.Generic;
using ProtoBuf;
using UnityEngine;
namespace Oxide.Plugins;
[Info("FAdminTeleport", "fufeldev", "1.0.0")]
public class FAdminTeleport : RustPlugin {
private readonly HashSet<ulong> mapTeleportEnabled = new HashSet<ulong>();
[ChatCommand("tp")]
private void TpCommand(BasePlayer player, string command, string[] args) {
if (!CanUse(player)) return;
string query = GetQuery(args);
if (string.IsNullOrWhiteSpace(query)) {
SendReply(player, "Используй: /tp ник/steamid/часть_ника");
return;
}
string error;
BasePlayer target = FindTarget(query, out error);
if (target == null) {
SendReply(player, error);
return;
}
if (!CanTeleport(player)) {
SendReply(player, "Ты мертв или сейчас не можешь телепортироваться.");
return;
}
TeleportPlayer(player, target);
SendReply(player, $"Ты телепортировался к {target.displayName}.");
}
[ChatCommand("tphere")]
private void TpHereCommand(BasePlayer player, string command, string[] args) {
if (!CanUse(player)) return;
string query = GetQuery(args);
if (string.IsNullOrWhiteSpace(query)) {
SendReply(player, "Используй: /tphere ник/steamid/часть_ника");
return;
}
string error;
BasePlayer target = FindTarget(query, out error);
if (target == null) {
SendReply(player, error);
return;
}
if (!CanTeleport(target)) {
SendReply(player, "Игрок мертв или сейчас не может быть телепортирован.");
return;
}
TeleportPlayer(target, player);
SendReply(player, $"Игрок {target.displayName} телепортирован к тебе.");
SendReply(target, $"Админ {player.displayName} телепортировал тебя к себе.");
}
[ChatCommand("tpgmap")]
private void TpGMapCommand(BasePlayer player) {
if (!CanUse(player)) return;
if (!mapTeleportEnabled.Add(player.userID)) {
mapTeleportEnabled.Remove(player.userID);
SendReply(player, "Телепорт по карте выключен.");
return;
}
SendReply(player, "Телепорт по карте включен. Поставь метку на карте ПКМ.");
}
private object OnMapMarkerAdd(BasePlayer player, MapNote note) {
if (!CanUseMapTeleport(player, note)) return null;
if (!CanTeleport(player)) {
SendReply(player, "Ты мертв или сейчас не можешь телепортироваться.");
return true;
}
Vector3 position = note.worldPosition;
position.y = GetGroundPosition(position) + 0.3f;
TeleportPlayer(player, position);
SendReply(player, "Ты телепортировался по карте.");
return true;
}
private bool CanUse(BasePlayer player) {
if (player == null) return false;
if (player.IsAdmin || player.net?.connection != null && player.net.connection.authLevel > 0) return true;
SendReply(player, "Нет доступа.");
return false;
}
private bool CanUseMapTeleport(BasePlayer player, MapNote note) {
return note != null && player != null && mapTeleportEnabled.Contains(player.userID) && (player.IsAdmin || player.net?.connection != null && player.net.connection.authLevel > 0);
}
private bool CanTeleport(BasePlayer player) {
return player != null && player.IsAlive() && !player.IsSpectating();
}
private string GetQuery(string[] args) {
return args == null || args.Length == 0 ? string.Empty : string.Join(" ", args).Trim();
}
private void TeleportPlayer(BasePlayer player, BasePlayer target) {
TeleportPlayer(player, target.transform.position);
}
private void TeleportPlayer(BasePlayer player, Vector3 position) {
player.EnsureDismounted();
player.SetParent(null, true, true);
player.SetServerFall(true);
try {
player.Teleport(position);
}
finally {
player.SetServerFall(false);
}
}
private float GetGroundPosition(Vector3 position) {
float terrain = TerrainMeta.HeightMap != null ? TerrainMeta.HeightMap.GetHeight(position) : position.y;
return Physics.Raycast(new Vector3(position.x, position.y + 200f, position.z), Vector3.down, out RaycastHit hit, float.MaxValue, Rust.Layers.Mask.Vehicle_Large | Rust.Layers.Solid | Rust.Layers.Mask.Water) ? Mathf.Max(hit.point.y, terrain) : terrain;
}
private BasePlayer FindTarget(string query, out string error) {
error = "Игрок не найден.";
ulong userId;
if (ulong.TryParse(query, out userId)) {
BasePlayer byId = BasePlayer.FindAwakeOrSleepingByID(userId);
if (byId != null) return byId;
}
List<BasePlayer> matches = new List<BasePlayer>();
foreach (BasePlayer candidate in BasePlayer.allPlayerList) {
if (candidate == null || string.IsNullOrEmpty(candidate.displayName)) continue;
if (candidate.UserIDString == query || candidate.displayName.Equals(query, System.StringComparison.OrdinalIgnoreCase)) return candidate;
if ((!string.IsNullOrEmpty(candidate.UserIDString) && candidate.UserIDString.Contains(query)) || candidate.displayName.IndexOf(query, System.StringComparison.OrdinalIgnoreCase) >= 0) matches.Add(candidate);
}
if (matches.Count == 1) return matches[0];
if (matches.Count > 1) error = $"Найдено несколько игроков: {FormatMatches(matches)}.";
return null;
}
private string FormatMatches(List<BasePlayer> matches) {
int limit = matches.Count > 5 ? 5 : matches.Count;
string result = string.Empty;
for (int i = 0; i < limit; i++) {
if (i > 0) result += ", ";
result += $"{matches[i].displayName} ({matches[i].UserIDString})";
}
if (matches.Count > limit) result += $", еще {matches.Count - limit}";
return result;
}
}