C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Oxide.Core;
using System.Collections.Generic;
using UnityEngine;
using System;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using System.Linq;
namespace Oxide.Plugins
{
[Info("Door Logs", "mvrb", "0.2.1")]
[Description("Check who opens/closes doors.")]
class DoorLogs : RustPlugin
{
private const string PermissionUse = "doorlogs.allowed";
private StoredData storedData = new StoredData();
private void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["NoDoorFound"] = "No door found.",
["NoDataFound"] = "No data found for this door.",
["DoorData"] = "Data for this door [{0}]: \n",
["Error: NoPermission"] = "You do not have permission to use this command."
}, this);
}
private void OnServerInitialized()
{
LoadData();
LoadVariables();
permission.RegisterPermission(PermissionUse, this);
}
[ChatCommand("door")]
private void ChatCmdCheckDoor(BasePlayer player)
{
if (!permission.UserHasPermission(player.UserIDString, PermissionUse))
{
player.ChatMessage(Lang("Error: NoPermission", player.UserIDString));
return;
}
RaycastHit hit;
var raycast = Physics.Raycast(player.eyes.HeadRay(), out hit, 15f, 2097409);
BaseEntity door = raycast ? hit.GetEntity() : null;
if (door == null || door as Door == null)
{
player.ChatMessage(Lang("NoDoorFound", player.UserIDString));
return;
}
if (!storedData.Doors.ContainsKey(door.net.ID.Value) || storedData.Doors[door.net.ID.Value].Entries.Count == 0)
{
player.ChatMessage(Lang("NoDataFound", player.UserIDString));
return;
}
int entries = 1;
string msg1 = Lang("DoorData", player.UserIDString, door.net.ID);
string msg2 = string.Empty;
foreach (KeyValuePair<ulong, PlayerData> entry in storedData.Doors[door.net.ID.Value].Entries.Reverse())
{
string last = string.Empty;
if (entry.Value.L > 0) last = $"L: <color=#FFA500>{UnixToDateTime(entry.Value.L)}</color>";
if (entries < 6)
{
msg1 += $"[{entries}] <color=#FFFF00>{GetNameFromId(entry.Key.ToString())}</color> ({entry.Key})\n ";
msg1 += $"F: <color=#FFA500>{UnixToDateTime(entry.Value.F)}</color> {last}\n";
}
else
{
msg2 += $"[{entries}] <color=#FFFF00>{GetNameFromId(entry.Key.ToString())}</color> ({entry.Key})\n ";
msg2 += $"F: <color=#FFA500>{UnixToDateTime(entry.Value.F)}</color> {last}\n";
}
entries++;
}
player.ChatMessage(msg1);
if (!string.IsNullOrEmpty(msg2)) player.ChatMessage(msg2);
if (!configData.LogToConsole) return;
msg1 = Regex.Replace(msg1, @"<color=#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})>|<\/color>", "");
Puts(msg1);
if (string.IsNullOrEmpty(msg2)) return;
msg2 = Regex.Replace(msg2, @"<color=#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})>|<\/color>", "");
Puts(msg2);
}
private void OnDoorClosed(Door door, BasePlayer player) => UpdateDoor(door, player);
private void OnDoorOpened(Door door, BasePlayer player) => UpdateDoor(door, player);
private void UpdateDoor(Door door, BasePlayer player)
{
if (door.OwnerID == 0) return;
int timestamp = GetUnix();
PlayerData playerData = new PlayerData();
playerData.F = timestamp;
if (!storedData.Doors.ContainsKey(door.net.ID.Value))
{
DoorData doorData = new DoorData();
doorData.Entries.Add(player.userID, playerData);
storedData.Doors.Add(door.net.ID.Value, doorData);
}
else
{
if (!storedData.Doors[door.net.ID.Value].Entries.ContainsKey(player.userID))
{
storedData.Doors[door.net.ID.Value].Entries.Add(player.userID, playerData);
}
else
{
storedData.Doors[door.net.ID.Value].Entries[player.userID].L = timestamp;
}
if (storedData.Doors[door.net.ID.Value].Entries.Count >= configData.MaxEntries)
{
storedData.Doors[door.net.ID.Value].Entries.Remove(storedData.Doors[door.net.ID.Value].Entries.Keys.First());
}
}
}
private class StoredData
{
public readonly Dictionary<ulong, DoorData> Doors = new Dictionary<ulong, DoorData>();
}
private class DoorData
{
public readonly Dictionary<ulong, PlayerData> Entries = new Dictionary<ulong, PlayerData>();
}
private class PlayerData
{
public Int32 F, L;
}
#region Config
private ConfigData configData;
class ConfigData
{
[JsonProperty(PropertyName = "Log /door output to console")]
public bool LogToConsole { get; set; }
[JsonProperty(PropertyName = "Max entries to log per door")]
public int MaxEntries { get; set; }
}
private void LoadVariables()
{
LoadConfigVariables();
SaveConfig();
}
protected override void LoadDefaultConfig()
{
var config = new ConfigData
{
LogToConsole = false,
MaxEntries = 10
};
SaveConfig(config);
}
private void LoadConfigVariables() => configData = Config.ReadObject<ConfigData>();
void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
#endregion
private string UnixToDateTime(double unixTimeStamp) => new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(unixTimeStamp).ToLocalTime().ToString("MM/dd HH:mm:ss");
private Int32 GetUnix() => (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
private string GetNameFromId(string id) => covalence.Players.FindPlayer(id)?.Name;
private void LoadData() => storedData = Interface.GetMod().DataFileSystem.ReadObject<StoredData>(this.Name);
private void SaveData() => Interface.GetMod().DataFileSystem.WriteObject(this.Name, storedData);
private void OnNewSave(string name)
{
PrintWarning("Map wipe detected - clearing DoorLogs...");
storedData.Doors.Clear();
SaveData();
}
private void OnServerSave() => SaveData();
private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
}
}