C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Collections.Generic;
using System;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Configuration;
using System.Text;
//
// Credit to the original author, Mordenak / HighTower 2
//
namespace Oxide.Plugins
{
[Info("PersonalBeacon", "redBDGR", "2.0.4")]
[Description("Displays a beacon at a marked location for easier navigation")]
class PersonalBeacon : RustPlugin
{
#region Data
private DynamicConfigFile exampleData;
WaypointDataStorage storedData;
void SaveData()
{
storedData.playerWaypoints = playerWaypointsCache;
storedData.globalWaypoints = globalWaypointCache;
exampleData.WriteObject(storedData);
}
void LoadData()
{
try
{
storedData = exampleData.ReadObject<WaypointDataStorage>();
LoadPlayerWaypoints();
LoadGlobalWaypoints();
}
catch
{
Puts("Failed to load data, creating new file");
storedData = new WaypointDataStorage();
}
}
void LoadPlayerWaypoints()
{
foreach (var entry in storedData.playerWaypoints)
{
playerWaypointsCache.Add(entry.Key, new List<WaypointData>());
foreach (var _entry in entry.Value)
playerWaypointsCache[entry.Key].Add(new WaypointData() { name = _entry.name, x = _entry.x, y = _entry.y, z = _entry.z });
}
}
void LoadGlobalWaypoints()
{
foreach (var entry in storedData.globalWaypoints)
globalWaypointCache.Add(new WaypointData() { name = entry.name, x = entry.x, y = entry.y, z = entry.z });
}
#endregion
#region Config
protected override void LoadDefaultConfig()
{
Config.Clear();
LoadVariables();
}
void LoadVariables()
{
// Arrow settings
arrowHeight = Convert.ToSingle(GetConfig("Arrow Settings", "Height", 100f));
arrowLevitation = Convert.ToSingle(GetConfig("Arrow Settings", "Levitation from ground", 3f));
arrowHeadSize = Convert.ToSingle(GetConfig("Arrow Settings", "Arrow Head Size", 3f));
// General settings
playerWaypointDisplaytime = Convert.ToSingle(GetConfig("Settings", "Player Display Time", 60f));
globalRefreshTime = Convert.ToSingle(GetConfig("Settings", "Global Waypoint Refresh Time", 60f));
maxWaypoints = Convert.ToInt32(GetConfig("Settings", "Max Waypoints", 5));
if (!Changed) return;
SaveConfig();
Changed = false;
}
#endregion
bool Changed = false;
private const string permissionName = "personalbeacon.use";
private const string permissionNameADMIN = "personalbeacon.admin";
Dictionary<string, List<WaypointData>> playerWaypointsCache = new Dictionary<string, List<WaypointData>>();
List<WaypointData> globalWaypointCache = new List<WaypointData>();
List<TimerData> timers = new List<TimerData>();
public float arrowHeight = 50f;
public float arrowLevitation = 3f;
public float arrowHeadSize = 3;
public float playerWaypointDisplaytime = 60;
public float globalRefreshTime = 60f;
public int maxWaypoints = 5;
class WaypointDataStorage
{
public Dictionary<string, List<WaypointData>> playerWaypoints;
public List<WaypointData> globalWaypoints;
}
class WaypointData
{
public string name;
public float x;
public float y;
public float z;
}
class TimerData
{
public string name;
public Timer timer;
public WaypointData data;
}
void Loaded()
{
lang.RegisterMessages(new Dictionary<string, string>
{
//chat
["No Permission"] = "You cannot use this command!",
["/setwp Invalid Syntax"] = "Invalid syntax! /setwp <waypoint name>",
["/wp Invalid Syntax"] = "Invalid syntax! /wp <waypoint name>",
["/setglobalwp Invalid Syntax"] = "Invalid syntax! /setglobalwp <waypoint name>",
["/hideglobalwp Invalid Syntax"] = "Invalid syntax! /hideglobalwp <waypoint name>",
["/removewp Invalid Syntax"] = "Invalid syntax! /removewp <waypoint name>",
["Waypoint Removed"] = "This waypoint has been removed!",
["Waypoint Already Exists"] = "This waypoint name already exists!",
["Waypoint Added"] = "You successfully created a new waypoint!",
["Waypoint Not Found"] = "Waypoint was not found",
["Max Waypoints Allowed"] = "You already have the maxiumum amount of waypoints allowed!",
["Global Waypoint Hidden"] = "This waypoint will disapear on the next update cycle",
["Global Waypoint Already Showing"] = "This waypoint is already being broadcasted",
["No Waypoints"] = "You do not have any waypoints!",
["List 1st Line"] = "Your current waypoints are:",
["List Entry"] = "- {0}",
}, this);
exampleData = Interface.Oxide.DataFileSystem.GetFile("PersonalBeacon");
NextTick(() =>
{
foreach (var entry in globalWaypointCache)
InitGlobalWaypoint(entry);
});
}
void OnServerInitialized() => LoadData();
void Unload() => SaveData();
void OnServerSave() => SaveData();
void Init()
{
permission.RegisterPermission("personalbeacon.use", this);
permission.RegisterPermission("personalbeacon.admin", this);
LoadVariables();
}
[ChatCommand("setwp")]
void setwpCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionName))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/setwp Invalid Syntax", player.UserIDString));
return;
}
if (!playerWaypointsCache.ContainsKey(player.UserIDString))
playerWaypointsCache.Add(player.UserIDString, new List<WaypointData>());
if (playerWaypointsCache[player.UserIDString].Count == maxWaypoints)
{
player.ChatMessage(msg("Max Waypoints Allowed", player.UserIDString));
return;
}
foreach (var entry in playerWaypointsCache[player.UserIDString])
if (args[0] == entry.name)
{
player.ChatMessage(msg("Waypoint Already Exists", player.UserIDString));
return;
}
WaypointData data = new WaypointData() { name = args[0], x = player.transform.position.x, y = player.transform.position.y, z = player.transform.position.z };
playerWaypointsCache[player.UserIDString].Add(data);
DrawWaypoint(player, new Vector3(data.x, data.y, data.z), playerWaypointDisplaytime, false, data.name);
}
[ChatCommand("wp")]
void wpCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionName))
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/wp Invalid Syntax", player.UserIDString));
return;
}
if (!playerWaypointsCache.ContainsKey(player.UserIDString))
playerWaypointsCache.Add(player.UserIDString, new List<WaypointData>());
WaypointData data = null;
foreach (var entry in playerWaypointsCache[player.UserIDString])
if (entry.name == args[0])
data = entry;
if (data == null)
{
player.ChatMessage(msg("Waypoint Not Found", player.UserIDString));
return;
}
DrawWaypoint(player, new Vector3(data.x, data.y, data.z), playerWaypointDisplaytime, false, data.name);
player.ChatMessage(msg("Waypoint Added", player.UserIDString));
}
[ChatCommand("removewp")]
void removewp(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionName))
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/removewp Invalid Syntax", player.UserIDString));
return;
}
if (!playerWaypointsCache.ContainsKey(player.UserIDString))
playerWaypointsCache.Add(player.UserIDString, new List<WaypointData>());
foreach (var entry in playerWaypointsCache[player.UserIDString])
if (args[0] == entry.name)
{
playerWaypointsCache[player.UserIDString].Remove(entry);
player.ChatMessage(msg("Waypoint Removed", player.UserIDString));
return;
}
}
[ChatCommand("wplist")]
void wplistCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionName))
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (!playerWaypointsCache.ContainsKey(player.UserIDString))
{
player.ChatMessage(msg("No Waypoints", player.UserIDString));
return;
}
else
{
StringBuilder x = new StringBuilder();
x.AppendLine(msg("List 1st Line", player.UserIDString));
foreach (var entry in playerWaypointsCache[player.UserIDString])
x.AppendLine(string.Format(msg("List Entry", player.UserIDString), entry.name.ToString()));
player.ChatMessage(x.ToString().TrimEnd());
}
}
// Admin commands:
[ChatCommand("setglobalwp")]
void globalwpCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permissions", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/setglobalwp Invalid Syntax", player.UserIDString));
return;
}
foreach(var entry in globalWaypointCache)
if (entry.name == args[0])
{
player.ChatMessage(msg("Waypoint Already Exists", player.UserIDString));
return;
}
WaypointData data = new WaypointData() { name = args[0], x = player.transform.position.x, y = player.transform.position.y, z = player.transform.position.z };
globalWaypointCache.Add(data);
InitGlobalWaypoint(data);
}
[ChatCommand("removeglobalwp")]
private void RemoveGlobalWPCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permissions", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/setglobalwp Invalid Syntax", player.UserIDString));
return;
}
bool x = false;
WaypointData data = null;
foreach (var entry in globalWaypointCache)
if (entry.name == args[0])
{
x = true;
data = entry;
return;
}
if (x == true && data != null)
{
TimerData tData = null;
foreach (var _entry in timers)
if (args[0] == _entry.name)
tData = _entry;
if (tData != null)
{
tData.timer.Destroy();
tData.timer = null;
timers.Remove(tData);
}
globalWaypointCache.Remove(data);
player.ChatMessage("Waypoint was removed");
}
else
{
player.ChatMessage("That waypoint does not exist");
}
}
[ChatCommand("hideglobalwp")]
void hideglobalwpCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/hideglobalwp Invalid Syntax", player.UserIDString));
return;
}
TimerData data = null;
foreach (var entry in timers)
if (args[0] == entry.name)
data = entry;
if (data == null)
{
player.ChatMessage(msg("Waypoint Not Found", player.UserIDString));
return;
}
data.timer.Destroy();
data.timer = null;
player.ChatMessage(msg("Global Waypoint Hidden", player.UserIDString));
}
[ChatCommand("showglobalwp")]
void showglobalwpCMD(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
if (args.Length != 1)
{
player.ChatMessage(msg("/hideglobalwp Invalid Syntax", player.UserIDString));
return;
}
TimerData data = null;
foreach (var entry in timers)
if (entry.name == args[0])
data = entry;
if (data == null)
{
player.ChatMessage(msg("Waypoint Not Found", player.UserIDString));
return;
}
if (data.timer != null)
{
player.ChatMessage(msg("Global Waypoint Already Showing", player.UserIDString));
return;
}
foreach (BasePlayer _player in BasePlayer.activePlayerList)
DrawWaypoint(_player, new Vector3(data.data.x, data.data.y, data.data.z), globalRefreshTime, true, data.name);
data.timer = timer.Repeat(globalRefreshTime, 0, () =>
{
foreach (BasePlayer _player in BasePlayer.activePlayerList)
DrawWaypoint(_player, new Vector3(data.data.x, data.data.y, data.data.z), globalRefreshTime, true, data.name);
});
}
[ChatCommand("wpshowall")]
void cmdShowAllBeacons(BasePlayer player, string command, string[] args)
{
if (!permission.UserHasPermission(player.UserIDString, permissionNameADMIN))
{
player.ChatMessage(msg("No Permission", player.UserIDString));
return;
}
foreach (var entry in playerWaypointsCache)
foreach (var _entry in playerWaypointsCache[entry.Key])
DrawWaypoint(player, new Vector3(_entry.x, _entry.y, _entry.z), playerWaypointDisplaytime, false, _entry.name);
}
void InitGlobalWaypoint(WaypointData data)
{
foreach (BasePlayer _player in BasePlayer.activePlayerList)
DrawWaypoint(_player, new Vector3(data.x, data.y, data.z), globalRefreshTime, true, data.name);
Timer repeat = timer.Repeat(globalRefreshTime, 0, () =>
{
foreach (BasePlayer _player in BasePlayer.activePlayerList)
DrawWaypoint(_player, new Vector3(data.x, data.y, data.z), globalRefreshTime, true, data.name);
});
timers.Add(new TimerData() { timer = repeat, name = data.name, data = data });
}
void DrawWaypoint(BasePlayer player, Vector3 pos, float time, bool isGlobal, string name)
{
var color = Color.blue;
if (isGlobal)
color = Color.red;
if (!player.HasPlayerFlag(BasePlayer.PlayerFlags.IsAdmin))
{
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendNetworkUpdateImmediate();
player.SendConsoleCommand("ddraw.arrow", time, color, new Vector3(pos.x, pos.y + arrowHeight + arrowLevitation, pos.z), new Vector3(pos.x, pos.y + arrowLevitation, pos.z), arrowHeadSize);
player.SendConsoleCommand("ddraw.text", time, color, new Vector3(pos.x, pos.y + arrowHeight + arrowLevitation + 5f, pos.z), name);
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
player.SendNetworkUpdate();
}
else
{
player.SendConsoleCommand("ddraw.arrow", time, color, new Vector3(pos.x, pos.y + arrowHeight + arrowLevitation, pos.z), new Vector3(pos.x, pos.y + arrowLevitation, pos.z), arrowHeadSize);
player.SendConsoleCommand("ddraw.text", time, color, new Vector3(pos.x, pos.y + arrowHeight + arrowLevitation + 5f, pos.z), name);
}
return;
}
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))
{
value = defaultValue;
data[datavalue] = value;
Changed = true;
}
return value;
}
string msg(string key, string id = null) => lang.GetMessage(key, this, id);
}
}