C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using UnityEngine;
using Time = UnityEngine.Time;
namespace Oxide.Plugins
{
[Info("PlayerTracker", "redBDGR", "1.0.1", ResourceId = 2584)]
[Description("Easily track the movements of players")]
class PlayerTracker : RustPlugin
{
private static PlayerTracker plugin;
private bool Changed;
private float intervalTime = 1f;
private float drawLength = 120f;
private bool clearPositionsOnCheck = true;
private bool trackAllPlayers;
private float startDeleteTime = 600f;
// Arrows
private float arrowHead = 0.5f;
private const string permissionName = "playertracker.admin";
private void Init()
{
plugin = this;
LoadVariables();
permission.RegisterPermission(permissionName, this);
lang.RegisterMessages(new Dictionary<string, string>
{
//chat
["No Permission"] = "You are not allowed to use this command",
["Invalid Syntax"] = "Invalid Syntax! /track <start | stop | show> <playername | id> <length>",
["Starttrack Invalid Syntax"] = "Invalid Syntax! /starttrack <playername | id>",
["Tracker Started"] = "You have started tracking {0}",
["Tracker Stopped"] = "You have stopped tracking {0}",
["Not Being Tracked"] = "This player is not currently being tracked",
["No Player Found"] = "No players were found with this name/id",
["Already Being Tracked"] = "This player is already being tacked",
}, this);
if (!trackAllPlayers) return;
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
Tracker tracker = player.GetComponent<Tracker>();
if (tracker)
return;
player.gameObject.AddComponent<Tracker>();
}
}
protected override void LoadDefaultConfig()
{
Config.Clear();
LoadVariables();
}
void LoadVariables()
{
// General Settings
intervalTime = Convert.ToSingle(GetConfig("Settings", "Position Interval Time", 2f));
trackAllPlayers = Convert.ToBoolean(GetConfig("Settings", "Track All Players", false)); // Can cause lag on larger servers, especially when viewing a players locations
startDeleteTime = Convert.ToSingle(GetConfig("Settings", "Remove Entries after x seconds", 600f)); // Can help reduce lag by shrinking list sizes
// Arrow Settings
arrowHead = Convert.ToSingle(GetConfig("Arrow Settings", "Arrow Head Size", 0.5f));
drawLength = Convert.ToSingle(GetConfig("Arrow Settings", "Default Display Length", 120f));
if (!Changed) return;
SaveConfig();
Changed = false;
}
private void Unload()
{
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
Tracker tracker = player.GetComponent<Tracker>();
if (tracker)
UnityEngine.Object.Destroy(tracker);
return;
}
}
private void OnPlayerSleepEnded(BasePlayer player)
{
if (!trackAllPlayers) return;
Tracker tracker = player.GetComponent<Tracker>();
if (!tracker)
player.gameObject.AddComponent<Tracker>();
}
[ChatCommand("track")]
private void TrackCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionName))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
switch (args.Length)
{
case 0:
{
player.ChatMessage(msg("Invalid Syntax", player.UserIDString));
return;
}
case 1:
{
player.ChatMessage(msg("Invalid Syntax", player.UserIDString));
break;
}
case 2:
{
BasePlayer target = BasePlayer.Find(args[1]);
if (target == null)
{
player.ChatMessage(msg("No Player Found", player.UserIDString));
return;
}
switch (args[0])
{
case "start":
{
Tracker tracker = target.GetComponent<Tracker>();
if (!tracker)
{
target.gameObject.AddComponent<Tracker>();
player.ChatMessage(string.Format(msg("Tracker Started", player.UserIDString), target.displayName));
}
break;
}
case "stop":
{
Tracker tracker = target.GetComponent<Tracker>();
if (tracker)
{
UnityEngine.Object.Destroy(tracker);
player.ChatMessage(string.Format(msg("Tracker Stopped", player.UserIDString), target.displayName));
return;
}
player.ChatMessage(msg("Not Being Tracked", player.UserIDString));
break;
}
case "show":
{
Tracker tracker = target.GetComponent<Tracker>();
if (!tracker)
{
player.ChatMessage(msg("Not Being Tracked", player.UserIDString));
return;
}
for (int i = 0; i < tracker.locationList.Count - 1; i++)
DoDraws(player, drawLength, tracker.locationList[i], tracker.locationList[i + 1]);
if (clearPositionsOnCheck)
tracker.locationList.Clear();
break;
}
default:
{
player.ChatMessage(msg("Invalid Syntax", player.UserIDString));
return;
}
}
break;
}
case 3:
{
BasePlayer target = BasePlayer.Find(args[1]);
if (target == null)
{
player.ChatMessage(msg("No Player Found", player.UserIDString));
return;
}
switch (args[0])
{
case "start":
{
Tracker tracker = target.GetComponent<Tracker>();
if (!tracker)
{
target.gameObject.AddComponent<Tracker>();
player.ChatMessage(msg("Tracker Started", player.UserIDString));
}
}
break;
case "stop":
{
Tracker tracker = target.GetComponent<Tracker>();
if (tracker)
{
UnityEngine.Object.Destroy(tracker);
player.ChatMessage(string.Format(msg("Tracker Stopped", player.UserIDString), target.displayName));
return;
}
player.ChatMessage(msg("Not Being Tracked", player.UserIDString));
}
break;
case "show":
{
Tracker tracker = target.GetComponent<Tracker>();
if (!tracker)
{
player.ChatMessage(msg("Not Being Tracked", player.UserIDString));
return;
}
for (int i = 0; i < tracker.locationList.Count - 1; i++)
DoDraws(player, Convert.ToSingle(args[1]), tracker.locationList[i], tracker.locationList[i + 1]);
if (clearPositionsOnCheck)
tracker.locationList.Clear();
}
break;
default:
{
player.ChatMessage(msg("Invalid Syntax", player.UserIDString));
return;
}
}
break;
}
default:
{
player.ChatMessage(msg("No Player Found", player.UserIDString));
return;
}
}
}
private class Tracker : MonoBehaviour
{
private BasePlayer player;
private float nextTime;
private readonly float intervalTime = plugin.intervalTime;
public List<Vector3> locationList = new List<Vector3>();
private float startDeleteTime;
private Vector3 lastPos;
private void Awake()
{
player = gameObject.GetComponent<BasePlayer>();
lastPos = player.transform.position;
if (plugin.startDeleteTime == 0)
startDeleteTime = Mathf.Infinity;
else
startDeleteTime = Time.time + plugin.startDeleteTime;
}
private void Update()
{
if (Time.time < nextTime) return;
if (locationList.Count > 0)
{
if (Vector3.Distance(lastPos, player.transform.position) < 1f)
return;
}
lastPos = player.transform.position;
locationList.Add(player.transform.position + new Vector3(0f, 0.6f, 0f));
nextTime = Time.time + intervalTime;
if (!(Time.time > startDeleteTime)) return;
locationList.Remove(locationList[0]);
}
}
private void DoDraws(BasePlayer player, float length, Vector3 pos1, Vector3 pos2)
{
if (player.IsAdmin)
{
player.SendConsoleCommand("ddraw.arrow", length, Color.red, pos1, pos2, arrowHead);
}
else
{
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendNetworkUpdateImmediate();
player.SendConsoleCommand("ddraw.arrow", length, Color.red, pos1, pos2, arrowHead);
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
player.SendNetworkUpdateImmediate();
}
}
private object GetConfig(string menu, string datavalue, object defaultValue)
{
var data = Config[menu] as Dictionary<string, object>;
if (data == null)
{
data = new Dictionary<string, object>();
Config[menu] = data;
Changed = true;
}
object value;
if (data.TryGetValue(datavalue, out value)) return value;
value = defaultValue;
data[datavalue] = value;
Changed = true;
return value;
}
string msg(string key, string id = null) => lang.GetMessage(key, this, id);
}
}