C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Text;
using UnityEngine;
using Oxide.Core.Libraries.Covalence;
using Net = Network.Net;
using Oxide.Core.Libraries;
using Pool = Facepunch.Pool;
using ConVar;
using Oxide.Core;
using Newtonsoft.Json.Linq;
using System;
using Network;
using System.Text.RegularExpressions;
using UnityEngine.Networking;
using UnityEngine.UI;
using Oxide.Core.Plugins;
using System.Linq;
using Newtonsoft.Json;
using Time = UnityEngine.Time;
using Facepunch.Utility;
using Oxide.Game.Rust.Cui;
using System.Collections.Generic;
using Object = System.Object;
using System.Collections;
namespace Oxide.Plugins {
[Info("IQReportSystem", "Mercury", "2.27.98")]
[Description("One love IQReportSystem")]
internal class IQReportSystem : RustPlugin {
private void SendNotifyReporter(BasePlayer reporter) {
if (!config.NotifyChatSettings.UseNotifyVerdictBanned) return;
if (reporter == null) return;
if (!alertBanned.ContainsKey(reporter.userID)) return;
SendChat(GetLang("NOTIFY_BANNED_USER", reporter.UserIDString, alertBanned[reporter.userID].nameBannedUser), reporter);
alertBanned.Remove(reporter.userID);
}
private void CheckStatusModerator(BasePlayer Moderator, String ReasonDisconnected = null) {
if (Moderator == null) return;
KeyValuePair<UInt64, ProcessCheckRepository> ModeratorCheckeds = PlayerChecks.FirstOrDefault(m => m.Value.ModeratorID.Equals(Moderator.userID));
if (ModeratorCheckeds.Value == null) return;
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifyStatusPlayerOrModerator;
UInt64 TargetID = ModeratorCheckeds.Key;
BasePlayer Target = BasePlayer.FindByID(TargetID);
if (ReasonDisconnected != null) {
if (Target == null) {
StopCheckedPlayer(TargetID, Moderator);
return;
}
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_DISCONNECTED", Target.UserIDString), Target);
Timer WaitModerator = timer.Once(600f, () => {
StopCheckedPlayer(Target.userID, null, true);
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_DISCONNECTED_FULL_LEAVE", Target.UserIDString), Target);
}
);
if (!TimerWaitChecked.ContainsKey(Target.userID)) TimerWaitChecked.Add(Target.userID, WaitModerator);
else TimerWaitChecked[Target.userID] = WaitModerator;
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, ReasonDisconnected);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, ReasonDisconnected));
return;
}
if (!TimerWaitChecked.ContainsKey(TargetID)) return;
if (TimerWaitChecked[TargetID].Destroyed) return;
TimerWaitChecked[TargetID].Destroy();
TimerWaitChecked.Remove(TargetID);
DrawUI_Moderator_Checked_Menu(Moderator, TargetID);
String TargetStatus = GetLang("TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_STATUS_DEFAULT", Moderator.UserIDString);
if (Target == null || !Target.IsConnected) {
TargetStatus = "Disconnected";
SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_PLAYER_ALERT_MODERATOR", Moderator.UserIDString, TargetStatus), Moderator);
}
DrawUI_Moderator_Checked_Menu_Status(Moderator, TargetStatus);
DrawUI_Moderator_Checked_Menu_Discord(Moderator, String.IsNullOrWhiteSpace(PlayerChecks[TargetID].DiscordTarget) ? GetLang("TITLE_PROFILE_MODERATOR_CHECKED_MENU_TITLE_DISCORD_EMPTY", Moderator.UserIDString) : PlayerChecks[TargetID].DiscordTarget);
if (Target != null) SendChat(GetLang("FUNCIONAL_CHANGE_STATUS_MODERATOR_RECONNECTED", Target.UserIDString), Target);
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, "Online");
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_ChangeStatus(true, Moderator.displayName, Moderator.UserIDString, "Online"));
}
private List<Fields> DT_PlayerSendContact(BasePlayer Sender, String Contact) {
List<Fields> fields = new List<Fields> {
new Fields(LanguageEn ? "Information about the sender :" : "Информация об отправителе :", "", false), new Fields("", "", false), new Fields(LanguageEn ? "Nick" : "Ник", $"{Sender.displayName}", true), new Fields("Steam64ID", $"[{Sender.userID}](https://steamcommunity.com/profiles/{Sender.userID})", true), new Fields(LanguageEn ? "Contacts for communication :" : "Контакты для связи :", Contact, false),
}
;
return fields;
}
private Boolean IsWhiteListReported(String targetID) {
if (!config.lastCheckedSetting.noReportWhiteList) return false;
if (!PlayerInfo._players.ContainsKey(targetID)) return false;
PlayerInfo pInfo = PlayerInfo.Get(targetID);
if (pInfo.lastCheckedDate == null) return false;
DateTime currentDate = DateTime.Now;
Int32 leftDays = (currentDate - pInfo.lastCheckedDate.Value).Days;
return leftDays <= config.lastCheckedSetting.daysLastChecked;
}
private void AlertModerator(BasePlayer Moderator, String PlayerName, Int32 ReportCount) {
if (!config.ReportContollerModerationSettings.AlertModerationSettings.AlertModerator) return;
SendChat(GetLang("NOTIFY_MODERATOR_MAX_REPORT", Moderator.UserIDString, PlayerName, ReportCount), Moderator);
RunEffect(Moderator);
}
private Boolean IsRaidBlock(BasePlayer player) {
if (player == null) return false;
if (RaidBlock) return RaidBlock.Call<Boolean>("IsRaidBlocked", player);
return NoEscape && NoEscape.Call<Boolean>("IsRaidBlocked", player);
}
private static StringBuilder sb = new StringBuilder();
object OnItemCraft(ItemCraftTask task, BasePlayer player, Item item) {
if (!PlayerChecks.ContainsKey(player.userID)) return null;
if (config.CheckControllerSettings.TrackCrafting) {
BasePlayer Moderator = BasePlayer.FindByID(PlayerChecks[player.userID].ModeratorID);
if (Moderator != null) SendChat(GetLang("FUNCIONAL_MESSAGE_CHECK_AFK_PLAYER_START_CRAFTING", Moderator.UserIDString), Moderator);
}
player.ResetInputIdleTime();
return null;
}
private void DrawUI_TemplatePlayer_Moderator(BasePlayer player, Int32 Y, String UserID, String NickName) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_TEMPLATE_PLAYER_MODERATOR");
if (Interface == null) return;
Interface = Interface.Replace("%AVATAR%", UserID);
Interface = Interface.Replace("%NAME%", CorrectedNick(NickName));
Interface = Interface.Replace("%STEAMID%", UserID);
Interface = Interface.Replace("%OFFSET_MIN%", $"-219.212 {174.147 - (Y * 62)}");
Interface = Interface.Replace("%OFFSET_MAX%", $"219.215 {210.147 - (Y * 62)}");
Interface = Interface.Replace("%REPORT_COUNTS%", $"{PlayerInfo.Get(UserID).Reports}");
Interface = Interface.Replace("%COMMAND%", $"report.panel select.player {UserID} true");
Interface = Interface.Replace("%TITLE_PLAYER_NICK_NAME%", GetLang("TITLE_PLAYER_NICK_NAME", player.UserIDString));
Interface = Interface.Replace("%TITLE_PLAYER_STEAMID%", GetLang("TITLE_PLAYER_STEAMID", player.UserIDString));
Interface = Interface.Replace("%TITLE_PLAYER_REPORTS%", GetLang("TITLE_PLAYER_REPORTS", player.UserIDString));
AddUI(player, Interface);
if (config.ReferenceSettings.MultiFightingSetting.UseSteamCheck && MultiFighting != null) DrawUI_TemplatePlayer_Moderator_IsSteam(player, UserID);
}
public class FancyMessage {
public String content {
get;
set;
}
public Boolean tts {
get;
set;
}
public Embeds[] embeds {
get;
set;
}
public class Embeds {
public String title {
get;
set;
}
public Int32 color {
get;
set;
}
public List<Fields> fields {
get;
set;
}
public Authors author {
get;
set;
}
public Embeds(String title, Int32 color, List<Fields> fields, Authors author) {
this.title = title;
this.color = color;
this.fields = fields;
this.author = author;
}
}
public FancyMessage(String content, bool tts, Embeds[] embeds) {
this.content = content;
this.tts = tts;
this.embeds = embeds;
}
public String toJSON() => JsonConvert.SerializeObject(this);
}
private Boolean IsModerator(BasePlayer moderator, Boolean checkStaff = true) {
if (!permission.UserHasPermission(moderator.UserIDString, ModeratorPermissions)) return false;
if (!checkStaff) return true;
if (!IQStaff || IQStaff.Version <= new VersionNumber(2, 7, 13)) return true;
Boolean isUseStaff = IQStaff.Call<Boolean>("API_IsTurnedStaffMode", moderator);
return isUseStaff;
}
private void DrawUI_ModeratorStatistics(BasePlayer Moderator) {
if (!ModeratorInformations.ContainsKey(Moderator.userID)) ModeratorInformations.Add(Moderator.userID, new ModeratorInformation());
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_PROFILE_MODERATION_INFO_PANEL");
if (Interface == null) return;
Interface = Interface.Replace("%TITLE_PROFILE_MODERATOR_STATISTICS_TITLE%", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE", Moderator.UserIDString));
Interface = Interface.Replace("%TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_QUALITY_ASSESSMENT%", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_QUALITY_ASSESSMENT", Moderator.UserIDString));
DestroyUI(Moderator, InterfaceBuilder.UI_REPORT_MODERATOR_STATISTICS);
AddUI(Moderator, Interface);
ModeratorInformation ModeratorInformation = ModeratorInformations[Moderator.userID];
Int32 AllScoreModerator = ModeratorInformation.GetAverageRaiting();
DrawUI_ModeratorStitistics_Banner(Moderator, "-96.947 -98", "91.72 -44", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_CHECKED", Moderator.UserIDString), $"{ModeratorInformation.AmountChecked}", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_DESCRIPTION_BANS_AND_CHECHKED", Moderator.UserIDString));
DrawUI_ModeratorStitistics_Banner(Moderator, "-96.947 -166.733", "91.72 -112", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_BANS", Moderator.UserIDString), $"{ModeratorInformation.AmountBans}", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_DESCRIPTION_BANS_AND_CHECHKED", Moderator.UserIDString));
DrawUI_ModeratorStitistics_Banner(Moderator, "-96.947 -273.667", "91.72 -219.667", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_ALLSCORE", Moderator.UserIDString), $"{AllScoreModerator}", CountRaiting : AllScoreModerator);
DrawUI_ModeratorStitistics_Banner(Moderator, "-97 -342.533", "91.667 -288.533", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_ONE_ACHIVE", Moderator.UserIDString), $"{ModeratorInformation.GetAverageRaitingAchive(ModeratorInformation.OneScore)}", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_DESCRIPTION_ONE_ACHIVE", Moderator.UserIDString));
DrawUI_ModeratorStitistics_Banner(Moderator, "-97 -411.533", "91.667 -357.533", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_TWO_ACHIVE", Moderator.UserIDString), $"{ModeratorInformation.GetAverageRaitingAchive(ModeratorInformation.TwoScore)}", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_DESCRIPTION_TWO_ACHIVE", Moderator.UserIDString));
DrawUI_ModeratorStitistics_Banner(Moderator, "-96.947 -479.667", "91.72 -425.667", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_TITLE_THREE_ACHIVE", Moderator.UserIDString), $"{ModeratorInformation.GetAverageRaitingAchive(ModeratorInformation.ThreeScore)}", GetLang("TITLE_PROFILE_MODERATOR_STATISTICS_DESCRIPTION_THREE_ACHIVE", Moderator.UserIDString));
}
public class SpeakerEntityMgr {
private static List<SpeakerEntity> _Entities = new List<SpeakerEntity>();
public static SpeakerEntity Create(BasePlayer listeners) {
var speaker = new SpeakerEntity();
speaker.SetListeners(listeners);
_Entities.Add(speaker);
return speaker;
}
public static void Shutdown() {
if (_Entities != null && _Entities.Count != 0) _Entities.ForEach(entity => _.NextTick(() => {
entity?.Kill();
}
));
}
public static void Kill(SpeakerEntity entity) {
_Entities.Remove(entity);
}
public class SpeakerEntity {
public UInt64 UID_SPEAKER = Network.Net.sv.TakeUID();
private UInt64 UID_CHAIR = Network.Net.sv.TakeUID();
public BasePlayer Listeners {
get;
private set;
}
public void SetListeners(BasePlayer listeners) {
Listeners = listeners;
}
public void SendEntitities() {
SendEntity(GetEntityChair);
SendEntity(GetEntitySpeaker);
}
private ProtoBuf.Entity GetEntitySpeaker(BasePlayer player) => new ProtoBuf.Entity() {
baseNetworkable = new ProtoBuf.BaseNetworkable() {
prefabID = player.prefabID, @group = BaseNetworkable.GlobalNetworkGroup.ID, uid = new NetworkableId(UID_SPEAKER),
}
, baseEntity = new ProtoBuf.BaseEntity() {
flags = 0, pos = new Vector3(0, 0, 0), rot = new Vector3(0, 0, 0), skinid = 0, time = Time.time,
}
, baseCombat = new ProtoBuf.BaseCombat() {
health = 10000, state = (Int32)BaseCombatEntity.LifeState.Alive
}
, basePlayer = new ProtoBuf.BasePlayer() {
health = 10000, modelState = new ModelState() {
mounted = true, onground = true, ducked = true, prone = true
}
, userid = UID_SPEAKER, name = "VOICE_P", playerFlags = (Int32)0, mounted = new NetworkableId(UID_CHAIR),
}
, parent = new ProtoBuf.ParentInfo() {
uid = new NetworkableId(UID_CHAIR), bone = 0
}
}
;
private ProtoBuf.Entity GetEntityChair(BasePlayer player) => new ProtoBuf.Entity() {
baseNetworkable = new ProtoBuf.BaseNetworkable() {
prefabID = 624857933, // static chair
@group = BaseNetworkable.GlobalNetworkGroup.ID, uid = new NetworkableId(UID_CHAIR),
}
, baseEntity = new ProtoBuf.BaseEntity() {
flags = 0, pos = new Vector3(0, 0.5f, -2.3f), rot = new Vector3(90, 180, 180), skinid = 0, time = Time.time,
}
, parent = new ProtoBuf.ParentInfo() {
uid = player.net.ID, bone = 2822582055 // head
}
}
;
public void Kill() {
DestroyEntity(UID_SPEAKER);
DestroyEntity(UID_CHAIR);
SpeakerEntityMgr.Kill(this);
}
private void SendEntity(Func<BasePlayer, ProtoBuf.Entity> entityGetter) {
NetWrite write = Network.Net.sv.StartWrite();
write.PacketID(Message.Type.Entities);
write.UInt32(++Listeners.net.connection.validate.entityUpdates);
entityGetter(Listeners)?.WriteToStream(write);
write.Send(new SendInfo(Listeners.net.connection));
}
private void DestroyEntity(UInt64 uid) {
NetWrite write = Network.Net.sv.StartWrite();
write.PacketID(Message.Type.EntityDestroy);
write.UInt64(uid);
write.Send(new SendInfo(Listeners.Connection) {
priority = Priority.Immediate
}
);
}
}
}
private const String HideMenuPermissions = "iqreportsystem.hidemenu";
private Boolean IsClansSendReport(String userID, String targetID) => config.ReferenceSettings.ClansSetting.SendReportClan && IsClans(userID, targetID);
private void StopDamageAdd(BasePlayer player) {
if (StopDamageMan == null) return;
if (!config.ReferenceSettings.StopDamageManSetting.UseStopDamage) return;
StopDamageMan.CallHook("AddPlayerSDM", player);
SendChat(GetLang("FUNCIONAL_PLAYER_STOP_DAMAGE_MAN_ADD", player.UserIDString), player);
}
private void WriteData() {
SaveDataFiles();
Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject("IQSystem/IQReportSystem/Moderators/ModeratorInformations", ModeratorInformations);
Oxide.Core.Interface.Oxide.DataFileSystem.WriteObject("IQSystem/IQReportSystem/Moderators/AlertBannedsUser", alertBanned);
}
private void DrawUI_ModeratorStitistics_Banner_RaitingImage(BasePlayer Moderator, Int32 X) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_PROFILE_BANNER_TEMPLATE_ADDITIONAL_IMG");
if (Interface == null) return;
Interface = Interface.Replace("%OFFSET_MIN%", $"{-59.851 + (X * 12)} -13.933");
Interface = Interface.Replace("%OFFSET_MAX%", $"{-49.184 + (X * 12)} -3.933");
AddUI(Moderator, Interface);
}
private void StartPluginLoad() {
_ = this;
//AddCommands
cmd.AddChatCommand(config.CommandForContact, this, nameof(ChatCommandDiscord));
cmd.AddConsoleCommand(config.CommandForContact, this, nameof(ConsoleCommandDiscord));
//Validate DataFile
foreach (BasePlayer player in BasePlayer.activePlayerList) OnPlayerConnected(player);
InitNotifyReporters();
}
[PluginReference]
Plugin IQChat, IQFakeActive, IQStaff, NoEscape, EventHelper, Battles, Duel, Duelist, ArenaTournament, Friends, Clans, MultiFighting, StopDamageMan, RustApp, RaidBlock, CombatBlock;
void DiscordLogSteamData(Dictionary<String, Int32> playerAppIds, Action<List<PlayerGameTime>, String> callback, String langReason) {
List<PlayerGameTime> playtimeResults = new List<PlayerGameTime>();
Int32 receivedResponses = 0;
Int32 totalResponses = playerAppIds.Count;
foreach (KeyValuePair<String, Int32> entry in playerAppIds) {
String steamId = entry.Key;
Int32 appId = entry.Value;
playtimeResults.Add(new PlayerGameTime {
SteamID = steamId, PlaytimeMinutes = -1,
}
);
String url = $"https://api.steampowered.com/IPlayerService/GetOwnedGames/v1/?key={config.NotifyDiscordSettings.steamData.steamApiKey}&steamid={steamId}&include_played_free_games=1";
webrequest.Enqueue(url, string.Empty, (code, response) => {
if (code == 200 && response != null) {
try {
JObject json = JObject.Parse(response);
JToken games = json["response"]?["games"];
if (games != null) {
foreach (JToken game in games) {
if ((Int32)game["appid"] == appId) {
playtimeResults.FirstOrDefault(x => x.SteamID == steamId).PlaytimeMinutes = (Int32)game["playtime_forever"];
break;
}
}
}
}
catch (Exception ex) {
PrintWarning($"Failed to parse game times for SteamID {steamId}.Exception: {ex.Message}");
}
}
else {
PrintWarning($"Failed to get game times for SteamID {steamId}.HTTP Response Code: {code}");
}
receivedResponses++;
if (receivedResponses == totalResponses) {
callback(playtimeResults, langReason);
}
}
, this, RequestMethod.GET, null, 10f);
}
}
private class SoundFileConverter : JsonConverter {
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
JToken value = JToken.Load(reader);
return _.FromSaveData(Compression.Uncompress(Convert.FromBase64String(value.ToString())));
}
public override bool CanConvert(Type objectType) {
return typeof(List<Byte>) == objectType;
}
}
void OnItemCraftCancelled(ItemCraftTask task, ItemCrafter crafter) {
BasePlayer player = crafter.owner;
if (player == null) return;
if (!PlayerChecks.ContainsKey(player.userID)) return;
if (config.CheckControllerSettings.TrackCrafting) {
BasePlayer Moderator = BasePlayer.FindByID(PlayerChecks[player.userID].ModeratorID);
if (Moderator != null) SendChat(GetLang("FUNCIONAL_MESSAGE_CHECK_AFK_PLAYER_CANCELLED_CRAFTING", Moderator.UserIDString), Moderator);
}
player.ResetInputIdleTime();
;
}
private Boolean CanStartedChecked(BasePlayer Target) => IsValidStartChecked(Target, null);
public Boolean IsReadyIQFakeActive() {
if (IQFakeActive != null && config.ReferenceSettings.IQFakeActiveUse) return IQFakeActive.Call<Boolean>("IsReady");
return false;
}
private void PreLoadedPlugin() {
ImageUi = new ImageUI();
ImageUi.DownloadImage();
}
private Dictionary<UInt64, ModeratorInformation> ModeratorInformations = new Dictionary<UInt64, ModeratorInformation>();
public class OzResponse {
public int unixtime {
get;
set;
}
public string reason {
get;
set;
}
public string proofid {
get;
set;
}
public bool pirate {
get;
set;
}
public bool active {
get;
set;
}
public bool reliable {
get;
set;
}
public bool unnecessary {
get;
set;
}
public OzServer server {
get;
set;
}
public string admin {
get;
set;
}
public int game {
get;
set;
}
public string date {
get;
set;
}
public int bantime {
get;
set;
}
}
private void StopCheckedPlayer(UInt64 TargetID, BasePlayer Moderator, Boolean AutoStop = false, Boolean IsConsole = false) {
if (!PlayerChecks.ContainsKey(TargetID)) return;
StopDamageRemove(TargetID);
BasePlayer Target = BasePlayer.FindByID(TargetID);
if (Target != null) {
if(config.CheckControllerSettings.UseDemo) Target.StopDemoRecording();
if (!AutoStop) DrawUI_Raiting_Menu_Player(Target, PlayerChecks[TargetID].ModeratorID);
DestroyUI(Target, InterfaceBuilder.UI_REPORT_PLAYER_ALERT);
if (AfkCheckRoutine.ContainsKey(Target)) {
if (AfkCheckRoutine[Target] != null) {
ServerMgr.Instance.StopCoroutine(AfkCheckRoutine[Target]);
AfkCheckRoutine[Target] = null;
}
AfkCheckRoutine.Remove(Target);
}
}
if (!IsConsole) {
if (Moderator != null) {
DestroyUI(Moderator, InterfaceBuilder.UI_REPORT_MODERATOR_MENU_CHECKED);
ModeratorInformations[Moderator.userID].AmountChecked++;
PlayerInfo playerData = PlayerInfo.Get(TargetID.ToString());
if (playerData == null) return;
playerData.LastModerator = $"{Moderator.displayName} <size=10>({DateTime.Now:dd.MM HH:mm})</size>";
playerData.lastCheckedDate = DateTime.Now;
}
}
else Puts(LanguageEn ? "Player checked completed" : "Проверка игрока завершена");
if (!AutoStop) {
if (config.NotifyChatSettings.UseNotifyStopCheck) {
if (Moderator != null || !IsConsole) {
foreach (BasePlayer player in BasePlayer.activePlayerList) SendChat(GetLang("NOTIFY_PLAYERS_STOP_CHECK_MODERATOR", player.UserIDString, Moderator.displayName, PlayerChecks[TargetID].DisplayName), player);
}
else {
foreach (BasePlayer player in BasePlayer.activePlayerList) SendChat(GetLang("NOTIFY_PLAYERS_STOP_CHECK_NOT_MODERATOR", player.UserIDString, PlayerChecks[TargetID].DisplayName), player);
}
}
PlayerInfo playerData = PlayerInfo.Get(TargetID.ToString());
if (playerData == null) return;
playerData.AmountChecked++;
playerData.Reports = 0;
}
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifyStopCheck;
if (!String.IsNullOrWhiteSpace(TemplateDiscord.WebhookNotify)) {
List<Fields> fields = DT_StopCheck(TargetID, Moderator, AutoStop, IsConsole);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
SendVK(VKT_StopCheck(TargetID, Moderator, AutoStop, IsConsole));
if (PlayerChecks.ContainsKey(TargetID)) PlayerChecks.Remove(TargetID);
Interface.Call("OnStoppedChecked", Target, Moderator, AutoStop, IsConsole);
}
private void DrawUI_PageController(BasePlayer player, Int32 Page, Boolean IsModerator, String SearchName = "") {
List<FakePlayer> fakePlayers = null;
List<BasePlayer> playerList = null;
Int32 AllCountPlayers = 0;
Int32 MaxPlayerPage = IsModerator ? 7 : 27;
if (IsModerator) {
List<BasePlayer> moderatorSortedList = BasePlayer.activePlayerList.Where(x => x.userID != player.userID && !IsWhiteListReported(x.UserIDString) && !permission.UserHasPermission(x.UserIDString, HideMenuPermissions) && !PlayerChecks.ContainsKey(x.userID) && PlayerInfo.Get(x.UserIDString).Reports >= config.ReportContollerModerationSettings.ReportCountTrigger && x.displayName.ToLower().Contains(SearchName.ToLower())).OrderByDescending(x => PlayerInfo.Get(x.UserIDString).Reports).ToList();
playerList = moderatorSortedList.Skip(Page * MaxPlayerPage).Take(MaxPlayerPage).ToList();
AllCountPlayers = moderatorSortedList.Count;
}
else {
if (IsReadyIQFakeActive()) {
List<FakePlayer> combinedPlayers = GetCombinedPlayerList();
if (combinedPlayers != null) {
List<FakePlayer> fakePlayersSorted = combinedPlayers.Where(x => x.userId != player.UserIDString && !IsWhiteListReported(x.userId) && !permission.UserHasPermission(x.userId, HideMenuPermissions) && x.displayName.ToLower().Contains(SearchName.ToLower())).ToList();
fakePlayers = fakePlayersSorted.OrderByDescending(p => !IsFakeUser(p.userId)).ToList();
fakePlayers = fakePlayersSorted.Skip(Page * MaxPlayerPage).Take(MaxPlayerPage).ToList();
AllCountPlayers = fakePlayersSorted.Count;
}
}
else {
List<BasePlayer> sortedPlayers = BasePlayer.activePlayerList.Where(x => x.userID != player.userID && !IsWhiteListReported(x.UserIDString) && !permission.UserHasPermission(x.UserIDString, HideMenuPermissions) && x.displayName.ToLower().Contains(SearchName.ToLower()) && (!IsFriendSendReport(player.userID.Get(), x.userID.Get()) || !IsClansSendReport(player.UserIDString, x.UserIDString))).ToList();
playerList = sortedPlayers.Skip(Page * MaxPlayerPage).Take(MaxPlayerPage).ToList();
AllCountPlayers = sortedPlayers.Count;
}
}
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_PANEL_PLAYERS_PAGE_CONTROLLER");
if (Interface == null) return;
Interface = Interface.Replace("%AMOUNT_PAGE%", $"{Page}");
Interface = Interface.Replace("%COMMAND_PAGE_NEXT%", AllCountPlayers < MaxPlayerPage ? "" : $"report.panel page.controller {(AllCountPlayers >= (Page + 1) * MaxPlayerPage ? (Page + 1) : 0)} {IsModerator}");
Interface = Interface.Replace("%COMMAND_PAGE_BACK%", AllCountPlayers < MaxPlayerPage ? "" : $"report.panel page.controller {(Page <= 0 ? AllCountPlayers / MaxPlayerPage : Page - 1)} {IsModerator}");
DestroyUI(player, "ActionPageCount");
DestroyUI(player, "ButtonNextPage");
DestroyUI(player, "ButtonBackPage");
AddUI(player, Interface);
ShowPlayersList(player, playerList, fakePlayers, IsModerator);
}
private void Unload() {
WriteData();
InterfaceBuilder.DestroyAll();
if (ImageUi != null) {
ImageUi.UnloadImages();
ImageUi = null;
}
if (config.CheckControllerSettings.UseSoundAlert) {
if (RoutineSounds != null && RoutineSounds.Count != 0) {
foreach (KeyValuePair<BasePlayer, Coroutine> routineSound in RoutineSounds.Where(x => x.Value != null)) ServerMgr.Instance.StopCoroutine(routineSound.Value);
}
SpeakerEntityMgr.Shutdown();
}
if (AfkCheckRoutine != null && AfkCheckRoutine.Count != 0) {
foreach (KeyValuePair<BasePlayer, Coroutine> coroutineList in AfkCheckRoutine.Where(x => x.Value != null)) ServerMgr.Instance.StopCoroutine(coroutineList.Value);
AfkCheckRoutine.Clear();
AfkCheckRoutine = null;
}
if (PlayerRepositories != null && PlayerRepositories.Count != 0) {
PlayerRepositories.Clear();
PlayerRepositories = null;
}
if (TimerWaitChecked != null && TimerWaitChecked.Count != 0) {
foreach (Timer timer in TimerWaitChecked.Values.Where(t => !t.Destroyed)) timer.Destroy();
TimerWaitChecked.Clear();
TimerWaitChecked = null;
}
if (config.CheckControllerSettings.StopCheckLeavePlayer) {
if (TimerWaitPlayer != null && TimerWaitPlayer.Count != 0) {
foreach (Timer timer in TimerWaitPlayer.Values.Where(t => !t.Destroyed)) timer.Destroy();
TimerWaitPlayer.Clear();
TimerWaitPlayer = null;
}
}
demoRecordesAfterReport.Clear();
demoRecordesAfterReport = null;
_interface = null;
_ = null;
}
private String VKT_PlayerMaxReport(String PlayerName, Int32 Reports, UInt64 TargetID) {
String Message = LanguageEn ? $"▣ EXCESS OF COMPLAINTS ▣\nInformation about the suspect:\n• Nickname: {PlayerName}\n• Steam64ID : {TargetID} (https://steamcommunity.com/profiles/{TargetID})\nNumber of reports: {Reports}" : $"▣ ПРЕВЫШЕНИЕ КОЛИЧЕСТВА ЖАЛОБ ▣\nИнформация об подозреваемом :\n• Ник : {PlayerName}\n• Steam64ID : {TargetID} (https://steamcommunity.com/profiles/{TargetID})\nКоличество репортов : {Reports}";
return Message;
}
void OnPlayerCommand(BasePlayer player, string command, string[] args) {
if (!PlayerChecks.ContainsKey(player.userID)) return;
if (config.CheckControllerSettings.TrackCommand) {
BasePlayer Moderator = BasePlayer.FindByID(PlayerChecks[player.userID].ModeratorID);
if (Moderator != null) SendChat(GetLang("FUNCIONAL_MESSAGE_CHECK_AFK_PLAYER_SEND_COMMAND", Moderator.UserIDString, command), Moderator);
}
player.ResetInputIdleTime();
}
private Dictionary<UInt64, Timer> TimerWaitPlayer = new Dictionary<UInt64, Timer>();
private void DrawUI_LeftMenu_Button(BasePlayer player, String TitleButton, String IconButton, String ColorButton, String OffsetMin, String OffsetMax, String Command) {
String Interface = InterfaceBuilder.GetInterface($"{InterfaceBuilder.UI_LAYER}_LEFT_MENU_BUTTON");
if (Interface == null) return;
Interface = Interface.Replace("%OFFSET_MIN%", OffsetMin);
Interface = Interface.Replace("%OFFSET_MAX%", OffsetMax);
Interface = Interface.Replace("%TITLE_BUTTON%", TitleButton);
Interface = Interface.Replace("%ICON_BUTTON%", IconButton);
Interface = Interface.Replace("%COLOR_BUTTON%", ColorButton);
Interface = Interface.Replace("%COMMAND_BUTTON%", Command);
AddUI(player, Interface);
}
private static InterfaceBuilder _interface;
void OnGamePlaytimesCollected(List<PlayerGameTime> gameTimes, String reasonLanguage) {
PlayerGameTime targetPlayer = gameTimes[0];
if (targetPlayer == null) return;
PlayerGameTime senderPlayer = gameTimes[1];
if (senderPlayer == null) return;
String timeTargetResult = targetPlayer.PlaytimeMinutes == -1 ? LanguageEn ? "Unknown" : "Неизвестно" : $"{targetPlayer.PlaytimeMinutes / 60}";
String timeSenderResult = senderPlayer.PlaytimeMinutes == -1 ? LanguageEn ? "Unknown" : "Неизвестно" : $"{senderPlayer.PlaytimeMinutes / 60}";
Configuration.NotifyDiscord.Webhooks.TemplatesNotify TemplateDiscord = config.NotifyDiscordSettings.WebhooksList.NotifySendReport;
List<Fields> fields = DT_PlayerSendReportSteamData(senderPlayer.SteamID, targetPlayer.SteamID, reasonLanguage, timeSenderResult, timeTargetResult);
SendDiscord(TemplateDiscord.WebhookNotify, fields, GetAuthorDiscord(TemplateDiscord), TemplateDiscord.Color);
}
private String VKT_PlayerSendContact(BasePlayer Sender, String Contact) {
String Message = LanguageEn ? $"▣ PLAYER CONTACTS ▣\nInformation about the sender:\n• Nickname: {Sender.displayName}\n• Steam64ID: {Sender.userID} (https://steamcommunity.com/profiles/{Sender.userID})\nContact information: {Contact}" : $"▣ КОНТАКТЫ ИГРОКА ▣\nИнформация об отправителе :\n• Ник : {Sender.displayName}\n• Steam64ID : {Sender.userID} (https://steamcommunity.com/profiles/{Sender.userID})\nКонтакты для связи : {Contact}";
return Message;
}
private String GetFakeName(String idOrName) {
if (!IsReadyIQFakeActive()) return String.Empty;
return (String)IQFakeActive.Call("GetFakeName", idOrName);
}
private void AutoClearData() {
Int32 settingClear = default;
List<String> keysPlayersSetting = Pool.Get<List<String>>();
keysPlayersSetting.AddRange(PlayerInfo._players.Keys);
DateTime currentDate = DateTime.Now;
foreach (String keyPlayer in keysPlayersSetting) {
PlayerInfo pInfo = PlayerInfo.Get(keyPlayer);
DateTime dataShowAlert = pInfo.lastConnection;
Int32 leftDays = (currentDate - dataShowAlert).Days;
if (leftDays < 7) continue;
PlayerInfo.Remove(keyPlayer);
settingClear++;
}
Pool.FreeUnmanaged(ref keysPlayersSetting);
if(settingClear != default) Puts(LanguageEn ? $"Automatic cleaning of information about old users.{settingClear} users have been deleted" : $"Автоматическая очистка информации о старых пользователях.Было удалено {settingClear} пользователей");
}
private Boolean IsCombatBlock(BasePlayer player) {
if (player == null) return false;
Object result = RaidBlock?.Call("IsCombatBlocked", player);
if (result is Boolean booleanResult) return booleanResult;
return CombatBlock && CombatBlock.Call<Boolean>("IsCombatBlocked", player);
}
private class PlayerInfo : SplitDatafile<PlayerInfo> {
private const String BaseFolder = "IQSystem" + "/" + "IQReportSystem" + "/";
public static PlayerInfo Save(String id) => Save(BaseFolder, id);
public static void Import(String id, PlayerInfo data) => Import(BaseFolder, id, data);
public static void Remove(String id) => Remove(BaseFolder, id);
public static PlayerInfo Get(String id) => Get(BaseFolder, id);
public static PlayerInfo Load(String id) => Load(BaseFolder, id);
public static PlayerInfo Clear(String id) => ClearAndSave(BaseFolder, id);
public static PlayerInfo GetOrLoad(String id) => GetOrLoad(BaseFolder, id);
public static PlayerInfo GetOrCreate(String id) => GetOrCreate(BaseFolder, id);
public static String[] GetFiles() => GetFiles(BaseFolder);
public Int32 Reports;
public Int32 SendReports;
public Int32 AmountChecked;
public String LastModerator;
public DateTime? lastCheckedDate;
public DateTime lastConnection;
public Dictionary<UInt64, List<Configuration.LangText>> ReasonHistory = new();
}
private void OnNewSave(String filename) => AutoClearData();
private void StartCheckOzProtect(UInt64 TargetID, UInt64 ModerID) {
if (ModerID == 0) return;
if (String.IsNullOrWhiteSpace(config.ReferenceSettings.OzProtectSettings.OzProtectKey)) return;
String API = $"https://api.ozliginus.ru/methods/ozprotect.call?checking={ModerID}&suspect={TargetID}&ozprotectid={config.ReferenceSettings.OzProtectSettings.OzProtectKey}&minutes=30";
try {
webrequest.Enqueue(API, null, (code, response) => {
}
, this);
}
catch (Exception e) {
PrintError(LanguageEn ? "OzProtect : We were unable to get the player to check with OzProtect, please check if your key is up to date or if OzProtect is available" : "OzProtect : Мы не смогли вызвать игрока на проверку с помощью OzProtect, проверьте актуальность вашего ключа или доступность OzProtect");
}
}
private class Configuration {
[JsonProperty(LanguageEn ? "Additional plugin configuration" : "Дополнительная настройка плагина")]
public LastChecked lastCheckedSetting = new LastChecked();
[JsonProperty(LanguageEn ? "Setting up compatibility with IQReportSystemr" : "Настройка совместимостей с IQReportSystem")]
public References ReferenceSettings = new References();
[JsonProperty(LanguageEn ? "Color setting" : "Настройка цветов")]
public Colors ColorsSettings = new Colors();
[JsonProperty(LanguageEn ? "List of reports and reasons for blocking" : "Список жалоб и причин блокировки")]
public List<ReasonReport> ReasonList = new List<ReasonReport>();
[JsonProperty(LanguageEn ? "Setting up sending complaints via F7 or the RUST game menu" : "Настройка отправки жалоб через F7 или игровое меню RUST")]
public ReportF7AndGameMenu ReportF7AndGameMenuSettings = new ReportF7AndGameMenu();
[JsonProperty(LanguageEn ? "Setting up the Player check process" : "Настройка процесса проверки игрока")]
public CheckController CheckControllerSettings = new CheckController();
[JsonProperty(LanguageEn ? "Setting up moderator notifications and the maximum number of reports" : "Настройка уведомления модераторов и максимального количества репортов")]
public ReportContollerModeration ReportContollerModerationSettings = new ReportContollerModeration();
[JsonProperty(LanguageEn ? "Setting up sending complaints by players" : "Настройка отправки жалоб игроками")]
public ReportSendController ReportSendControllerSettings = new ReportSendController();
[JsonProperty(LanguageEn ? "Additional verdict setting" : "Дополнительная настройка вынесения вердикта")]
public VerdictController VerdictControllerSettings = new VerdictController();
[JsonProperty(LanguageEn ? "Setting up an automatic ban based on the number of reports" : "Настройка автома-бана по кол-во репортов")]
public AutoBan AutoBanSettings = new AutoBan();
[JsonProperty(LanguageEn ? "Configuring notifications for all players about actions in the plugin" : "Настройка уведомлений для всех игроков о действиях в плагине")]
public NotifyChat NotifyChatSettings = new NotifyChat();
[JsonProperty(LanguageEn ? "Setting up notifications in Discord" : "Настройка уведомлений в Discord")]
public NotifyDiscord NotifyDiscordSettings = new NotifyDiscord();
[JsonProperty(LanguageEn ? "Setting up notifications in VK" : "Настройка уведомлений в VK")]
public NotifyVK NotifyVKSettings = new NotifyVK();
[JsonProperty(LanguageEn ? "Command to send data when calling for verification (console and chat)" : "Команда для отправки данных при вызове на проверку (консольная и чатовая)")]
public String CommandForContact;
internal class LastChecked {
[JsonProperty(LanguageEn ? "Display to players the last check date of the player they wish to report" : "Отображать игрокам дату последней проверки игрока на которого они хотят пожаловаться")]
public Boolean showLastCheckedDate;
[JsonProperty(LanguageEn ? "Disallow sending reports for a player if they were recently checked (the player will not be displayed in the UI)" : "Запретить отправлять репорты на игрока если он был недавно проверен (игрок не будет отображен в UI)")]
public Boolean noReportWhiteList;
[JsonProperty(LanguageEn ? "Number of days during which a player is considered to have been recently checked" : "Количество дней, в течение которых игрок считается недавно проверенным")]
public Int32 daysLastChecked;
}
internal class AutoBan {
[JsonProperty(LanguageEn ? "Use auto-bans based on the number of reports" : "Использовать авто-баны по количеству репортов")]
public Boolean UseAutoBan;
[JsonProperty(LanguageEn ? "Auto-bans will ONLY apply to pirates (Luma) - true, otherwise to all players - false" : "Авто-баны будут действовать ТОЛЬКО на пиратов (Luma) - true, иначе на всех игроков - false")]
public Boolean UseOnlyLuma;
[JsonProperty(LanguageEn ? "Maximum number of reports for issuing automatic blocking" : "Максимальное количество репортов для выдачи автоматической блокировки")]
public Int32 MaxReports;
[JsonProperty(LanguageEn ? "Index from the list of complaints when a player is blocked (From your list - starts from 0)" : "Индекс из списка жалоб при блокировки игрока (Из вашего списка - начинается от 0)")]
public Int32 IndexBanned;
}
internal class VerdictController {
[JsonProperty(LanguageEn ? "Banned all the `Friends` of a player who has been given a verdict by a moderator (true - yes/false - no)" : "Блокировать всех `Друзей` игрока, которому вынес вердикт модератор (true - да/false - нет)")]
public Boolean UseBanAllTeam;
[JsonProperty(LanguageEn ? "Index from the list of complaints when blocking a player's `Friends` (From your list - starts from 0)" : "Индекс из списка жалоб при блокировки `Друзей` игрока (Из вашего списка - начинается от 0)")]
public Int32 IndexBanReason;
}
internal class CheckController {
[JsonProperty(LanguageEn ? "Use sound notification for players when calling for verification (true - yes / false - no) [You must upload sound files to the IQSystem/IQReportSystem/Sounds folder]" : "Использовать звуковое оповещение для игроков при вызове на проверку (true - да/false - нет)
// ... [Code preview truncated due to length. Full source in attached file] ...