C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Checkpoints", "Ryan", "1.0.1")]
[Description("Restore points for players to teleport to when the server restarts")]
class Checkpoints : RustPlugin
{
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
private static StoredData sData;
private static Checkpoints Instance;
private const string Perm = "checkpoints.allow";
#region Data
private class StoredData
{
public Dictionary<ulong, PlayerData> Players = new Dictionary<ulong, PlayerData>();
}
private class PlayerData
{
public float PosX { get; set; }
public float PosY { get; set; }
public float PosZ { get; set; }
public uint ID { get; set; }
public PlayerData()
{
}
public PlayerData(SleepingBag bag)
{
PosX = bag.transform.position.x;
PosY = bag.transform.position.y;
PosZ = bag.transform.position.z;
ID = bag.net.ID;
}
}
private class Data
{
public static void Add(BasePlayer player, PlayerData data)
{
if (!Exists(player.userID))
{
sData.Players.Add(player.userID, data);
Save();
}
}
public static void Remove(ulong id)
{
if (Exists(id))
{
sData.Players.Remove(id);
Save();
}
}
public static bool Exists(ulong id)
{
return sData.Players.ContainsKey(id);
}
private static void Save() => Interface.Oxide.DataFileSystem.WriteObject(Instance.Name, sData);
}
#endregion
#region Lang
private new void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["Checkpoint_NotExist"] = "You have no checkpoint set, to set a checkpoint use <color=#55aaff>/checkpoint set</color> at your desired position.",
["Checkpoint_Exists"] = "Your checkpoint is <color=#55aaff>{0}</color>m away",
["Checkpoint_AlreadyExists"] = "You already have a checkpoint set, it's <color=#55aaff>{0}</color>m away",
["Checkpoint_Set"] = "You've set your checkpoint at <color=#55aaff>X</color>: {0}, <color=#55aaff>Y</color>: {1}, <color=#55aaff>Z</color>: {2}",
["Checkpoint_NotFound"] = "You don't seem to have a checkpoint to remove",
["Checkpoint_Removed"] = "You've removed your checkpoint at <color=#55aaff>X</color>: {0}, <color=#55aaff>Y</color>: {1}, <color=#55aaff>Z</color>: {2} (<color=#55aaff>{3}</color>m away)",
["Checkpoint_Killed"] = "Your checkpoint <color=#55aaff>{0}</color>m away from you has been reset because your bag has been removed!",
["NoPermission"] = "You don't have permission to use that command",
["SleepingBag_NotOwner"] = "You do not own the sleeping bag you're looking at",
["Raycast_NotFound"] = "Didn't find a valid sleeping bag"
}, this);
}
#endregion
#region Methods
private class Checks
{
public static bool HasPermission(string id)
{
return Instance.permission.UserHasPermission(id, Perm);
}
public static bool CanUseSleepingBag(BasePlayer player, SleepingBag bag)
{
if (player.userID == bag.deployerUserID)
return true;
return false;
}
}
private SleepingBag FindBag(BasePlayer player)
{
RaycastHit hit;
if (!Physics.Raycast(player.eyes.HeadRay(), out hit, Mathf.Infinity))
{
PrintToChat(player, Lang("Raycast_NotFound", player.UserIDString));
return null;
}
if (hit.GetEntity() is SleepingBag)
return hit.GetEntity() as SleepingBag;
PrintToChat(player, Lang("Raycast_NotFound", player.UserIDString));
return null;
}
#endregion
#region Hooks
private void Init()
{
Instance = this;
sData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>(Name);
permission.RegisterPermission(Perm, this);
}
private void OnPlayerDisconnected(BasePlayer player, string reason)
{
if (reason.ToLower().Contains("restarting") && Data.Exists(player.userID))
{
var data = sData.Players[player.userID];
player.Teleport(new Vector3(data.PosX, data.PosY, data.PosZ));
}
}
private void OnEntityKill(BaseNetworkable networkable)
{
var bag = networkable as SleepingBag;
if (bag != null && Data.Exists(bag.OwnerID) && sData.Players[bag.OwnerID].ID == bag.net.ID)
{
Data.Remove(bag.OwnerID);
var player = BasePlayer.FindByID(bag.OwnerID);
if (player != null && player.IsConnected)
{
var data = sData.Players[player.userID];
PrintToChat(player, Lang("Checkpoint_Killed", player.UserIDString,
Vector3.Distance(player.transform.position, new Vector3(data.PosX, data.PosY, data.PosZ))));
}
}
}
#endregion
#region Commands
[ChatCommand("checkpoint")]
private void checkpointCmd(BasePlayer player, string command, string[] args)
{
if (!Checks.HasPermission(player.UserIDString))
{
PrintToChat(player, Lang("NoPermission", player.UserIDString));
return;
}
if (args.Length == 0)
{
if (Data.Exists(player.userID))
{
var data = sData.Players[player.userID];
PrintToChat(player, Lang("Checkpoint_Exists", player.UserIDString,
Math.Round(Vector3.Distance(player.transform.position, new Vector3(data.PosX, data.PosY, data.PosZ)))));
return;
}
PrintToChat(player, Lang("Checkpoint_NotExist", player.UserIDString));
return;
}
switch (args[0].ToLower())
{
case "set":
if (!Data.Exists(player.userID))
{
var bag = FindBag(player);
if (bag == null)
return;
if (!Checks.CanUseSleepingBag(player, bag))
{
PrintToChat(player, Lang("SleepingBag_NotOwner", player.UserIDString));
return;
}
Data.Add(player, new PlayerData(bag));
PrintToChat(player, Lang("Checkpoint_Set", player.UserIDString, Math.Round(bag.transform.position.x, 2),
Math.Round(bag.transform.position.y, 2), Math.Round(bag.transform.position.z, 2)));
}
PrintToChat(player, Lang("Checkpoint_AlreadyExists", player.UserIDString, Math.Round(Vector3.Distance(player.transform.position,
new Vector3(sData.Players[player.userID].PosX, sData.Players[player.userID].PosY, sData.Players[player.userID].PosZ)))));
return;
case "remove":
if (Data.Exists(player.userID))
{
var data = sData.Players[player.userID];
Data.Remove(player.userID);
PrintToChat(player, Lang("Checkpoint_Removed", player.UserIDString, Math.Round(data.PosX, 2), Math.Round(data.PosY, 2), Math.Round(data.PosZ, 2),
Math.Round(Vector3.Distance(player.transform.position, new Vector3(data.PosX, data.PosY, data.PosZ)))));
return;
}
PrintToChat(player, Lang("Checkpoint_NotFound", player.UserIDString));
return;
}
}
#endregion
}
}