C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Core.Configuration;
using Facepunch.Unity;
using Facepunch;
using System.Linq;
using UnityEngine;
namespace Oxide.Plugins
{
[Info( "Sign Checker", "Scarylaggy", "1.1.5" )]
[Description( "Provides a way to check the last editor of signs" )]
class SignChecker : RustPlugin
{
private static readonly string PERMISSION_USE = "signchecker.use";
private static readonly string PERMISSION_CLEAN = "signchecker.clean";
StoredData storedData;
void Init()
{
registerPermissions();
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>( "SignChecker" );
}
/// <summary>
/// Registers the Permissions on Plugin initilation
/// </summary>
private void registerPermissions()
{
permission.RegisterPermission( PERMISSION_USE, this );
permission.RegisterPermission( PERMISSION_CLEAN, this );
}
/// <summary>
/// Server hook wich gets called on every edit of an Signage
/// </summary>
/// <param name="sign"></param>
/// <param name="player"></param>
/// <param name="text"></param>
void OnSignUpdated(Signage sign, BasePlayer player, string text)
{
//Quick check if the Called sign is already in the Datafile
if (!isAlreadyInStorageData( sign ))
{
//If not, it gets added
storedData.signCheckerDatas.Add( new SignCheckerData( player, sign ) );
}
else
{
//If it is, we get it from the list, and Edit it to the new "Last editor"-Data
foreach (SignCheckerData data in FindSignById( sign.ToString() ))
{
data.userId = player.UserIDString;
data.name = player.UserIDString;
}
}
Interface.Oxide.DataFileSystem.WriteObject( this.Name, storedData );
}
/// <summary>
/// Gets an IEnumerable<SignCheckerData> wich will only contain the needed Part of our stored Data
/// </summary>
/// <param name="id"></param> The ID is specified by the Signage#ToString() Method
/// <returns>IEnumerable<SignCheckerData></returns>
private IEnumerable<SignCheckerData> FindSignById(string id)
{
return storedData.signCheckerDatas.Where( item => item.signId.Equals( id ) );
}
private bool hasPermissionUse(BasePlayer player, string perm)
{
return permission.UserHasPermission( player.UserIDString, perm );
}
/// <summary>
/// Gets the Last editor for a given Signage
/// </summary>
/// <param name="sign"></param>
/// <param name="caller"></param>
/// <returns></returns>
private string getPlayerDataForSign(Signage sign, string caller)
{
if (sign != null)
{
string playerData = "";
foreach (SignCheckerData data in FindSignById( sign.ToString() ))
{
playerData = data.ToString();
}
if (!string.IsNullOrEmpty(playerData))
{
return playerData;
}
}
return string.Format( GetLangValue( "NoOne", caller ) );
}
/// <summary>
/// Chatcommand to clean the File, as it is apropriate to clean it after a Wipe
/// </summary>
/// <param name="player"></param>
/// <param name="command"></param>
/// <param name="args"></param>
[ChatCommand( "signwipe" )]
private void wipeDataChatCommand(BasePlayer player, string command, string[] args)
{
if (!hasPermissionUse(player, PERMISSION_CLEAN))
{
player.ChatMessage( string.Format( GetLangValue( "NoPermission", player.UserIDString ) ) );
return;
}
storedData.signCheckerDatas.Clear();
Interface.Oxide.DataFileSystem.WriteObject( this.Name, storedData );
player.ChatMessage( string.Format( GetLangValue( "Wipe", player.UserIDString ) ) );
}
/// <summary>
/// Chat Command for Players with the signchecker.use Permission
/// Messages the user with an chatmessage about the last editor of an Signage
/// => Checks if the player has the needed Permission
/// => Checks if the player is looking at a Signage
/// </summary>
/// <param name="player"></param>
/// <param name="command"></param>
/// <param name="args"></param>
[ChatCommand( "check" )]
private void CheckChatCommand(BasePlayer player, string command, string[] args)
{
//Check for the Use Permission
if (!hasPermissionUse( player, PERMISSION_USE ))
{
player.ChatMessage( string.Format( GetLangValue( "NoPermission", player.UserIDString ) ) );
return;
}
Signage sign = null;
RaycastHit hit;
// Get the object that is in front of the player within the maximum distance set in the config.if (Physics.Raycast( player.eyes.HeadRay(), out hit, 3 ))
{
// Attempt to grab the Signage entity, if there is none this will set the sign to null,
// otherwise this will set it to the sign the player is looking at.sign = hit.GetEntity() as Signage;
}
else
{
player.ChatMessage( string.Format( GetLangValue( "NothingFound", player.UserIDString ) ) );
return;
}
//If everything is ok, here we actually get the needed Values
player.ChatMessage( string.Format( GetLangValue( "LastEdit", player.UserIDString ), getPlayerDataForSign( sign, player.UserIDString ) ) );
}
private string GetLangValue(string key, string userId) => lang.GetMessage( key, this, userId );
bool isAlreadyInStorageData(Signage sign) => storedData.signCheckerDatas.Any( item => item.signId.Equals( sign.ToString() ) );
protected override void LoadDefaultMessages()
{
// English
lang.RegisterMessages( new Dictionary<string, string>
{
{ "NoPermission", "You don't have the Permission to use this Command." },
{ "LastEdit", "Last editor was {0}" },
{ "NothingFound", "You are not looking at a Sign" },
{ "NoOne", "nobody" },
{ "Wipe", "Datafile has been wiped"}
}, this );
}
class StoredData
{
public HashSet<SignCheckerData> signCheckerDatas = new HashSet<SignCheckerData>();
public StoredData()
{
}
}
class SignCheckerData
{
public string userId;
public string name;
public string signId;
public SignCheckerData()
{
}
public SignCheckerData(BasePlayer player, Signage sign)
{
signId = sign.ToString();
userId = player.UserIDString;
name = player.displayName;
}
public override string ToString()
{
return name + " - " + userId;
}
}
}
}