C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Stash Marker", "supreme", "1.1.0")]
[Description("Marks the hidden stashes on the ingame map")]
public class StashMarker : RustPlugin
{
//credits to nivex for improvements
const string permUse = "stashmarker.use";
const string permAdmin = "stashmarker.admin";
#region Class Variables
private readonly Hash<ulong, List<MapMarkerGenericRadius>> _mapMarker = new Hash<ulong, List<MapMarkerGenericRadius>>();
private WaitForEndOfFrame _cachedWaitForEndOfFrame = new WaitForEndOfFrame();
private HashSet<StashContainer> _stashes = new HashSet<StashContainer>();
private Coroutine _stashRoutine;
#endregion
#region Configuration
private Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Marker Radius")]
public float markerRadius = 0.1f;
[JsonProperty(PropertyName = "Marker Alpha")]
public float markerAlpha = 0.8f;
[JsonProperty(PropertyName = "Marker Color")]
public string markerColor = "ACFA58";
[JsonProperty(PropertyName = "Marker Color Outline")]
public string markerColorOutline = "000000";
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
SaveConfig();
}
catch
{
PrintError("Your configuration file contains an error.Using default configuration values.");
LoadDefaultConfig();
}
}
protected override void SaveConfig() => Config.WriteObject(_config);
protected override void LoadDefaultConfig() => _config = new Configuration();
#endregion
#region Setup & Loading
private void OnServerInitialized()
{
Subscribe(nameof(OnEntitySpawned));
Subscribe(nameof(OnEntityKill));
Subscribe(nameof(OnPlayerSleepEnded));
Subscribe(nameof(CanNetworkTo));
foreach (BasePlayer player in BasePlayer.activePlayerList)
{
OnPlayerSleepEnded(player);
}
_stashRoutine = ServerMgr.Instance.StartCoroutine(StashRoutine());
}
IEnumerator StashRoutine()
{
int total = 0;
foreach (var e in BaseNetworkable.serverEntities)
{
if (e is StashContainer)
{
_stashes.Add(e as StashContainer);
}
if (++total % 50 == 0)
{
yield return _cachedWaitForEndOfFrame;
}
}
_stashRoutine = null;
}
void Init()
{
Unsubscribe(nameof(OnEntitySpawned));
Unsubscribe(nameof(OnEntityKill));
Unsubscribe(nameof(OnPlayerSleepEnded));
Unsubscribe(nameof(CanNetworkTo));
permission.RegisterPermission(permUse, this);
permission.RegisterPermission(permAdmin, this);
}
private void Unload()
{
if (_stashRoutine != null)
{
ServerMgr.Instance.StopCoroutine(_stashRoutine);
}
foreach (MapMarkerGenericRadius marker in _mapMarker.SelectMany(mm => mm.Value))
{
marker.Kill();
}
}
#endregion
#region uMod Hooks
private void OnEntitySpawned(StashContainer stash)
{
if (stash != null)
{
_stashes.Add(stash);
}
}
private void OnPlayerSleepEnded(BasePlayer player)
{
if (!permission.UserHasPermission(player.UserIDString, permUse)) return;
List<MapMarkerGenericRadius> playerMarkers;
if (!_mapMarker.TryGetValue(player.userID, out playerMarkers))
_mapMarker.Add(player.userID, playerMarkers = new List<MapMarkerGenericRadius>());
foreach (StashContainer stash in _stashes.Where(s => s.OwnerID == player.userID))
if (stash.IsHidden())
{
MapMarkerGenericRadius marker = GetOrAddMarker(player, stash.transform.position);
marker.SendUpdate();
}
}
private void OnEntityKill(StashContainer stash)
{
_stashes.Remove(stash);
List<MapMarkerGenericRadius> playerMarkers = _mapMarker[stash.OwnerID];
MapMarkerGenericRadius marker = playerMarkers?.FirstOrDefault(m => m.transform.position == stash.transform.position);
if (marker == null || marker.IsDestroyed) return;
marker.Kill();
playerMarkers.Remove(marker);
}
void CanSeeStash(BasePlayer player, StashContainer stash)
{
List<MapMarkerGenericRadius> playerMarkers;
if (!_mapMarker.TryGetValue(player.userID, out playerMarkers))
_mapMarker.Add(player.userID, playerMarkers = new List<MapMarkerGenericRadius>());
MapMarkerGenericRadius marker = playerMarkers?.FirstOrDefault(m => m.transform.position == stash.transform.position);
if (marker == null || marker.IsDestroyed) return;
marker.Kill();
playerMarkers.Remove(marker);
}
void CanHideStash(BasePlayer player, StashContainer stash)
{
if (!permission.UserHasPermission(player.UserIDString, permUse)) return;
MapMarkerGenericRadius marker = GetOrAddMarker(player, stash.transform.position);
marker.SendUpdate();
}
private object CanNetworkTo(MapMarkerGenericRadius marker, BasePlayer target)
{
if (marker == null) return null;
List<MapMarkerGenericRadius> playerMarkers;
if (!_mapMarker.TryGetValue(marker.OwnerID, out playerMarkers) || !playerMarkers.Contains(marker)) return null;
return marker.OwnerID == target.userID || permission.UserHasPermission(target.UserIDString, permAdmin) ? (object)true : false;
}
#endregion
#region Marker Methods
private MapMarkerGenericRadius GetOrAddMarker(BasePlayer player, Vector3 pos)
{
if (!permission.UserHasPermission(player.UserIDString, permUse)) return null;
List<MapMarkerGenericRadius> playerMarkers;
if (!_mapMarker.TryGetValue(player.userID, out playerMarkers))
_mapMarker.Add(player.userID, playerMarkers = new List<MapMarkerGenericRadius>());
MapMarkerGenericRadius marker = playerMarkers.FirstOrDefault(m => m.transform.position == pos);
marker = GameManager.server.CreateEntity("assets/prefabs/tools/map/genericradiusmarker.prefab", pos) as MapMarkerGenericRadius;
if (marker == null) return null;
marker.alpha = _config.markerAlpha;
string colorMarker = _config.markerColor;
string colorOutline = _config.markerColorOutline;
ColorUtility.TryParseHtmlString($"#{colorMarker}", out marker.color1);
ColorUtility.TryParseHtmlString($"#{colorOutline}", out marker.color2);
marker.radius = _config.markerRadius;
marker.OwnerID = player.userID;
playerMarkers.Add(marker);
marker.Spawn();
return marker;
}
#endregion
}
}