C#:
using System;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using System.Collections;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Oxide.Core;
using UnityEngine;
using Random = UnityEngine.Random;
using System.Linq;
using Oxide.Core.Plugins;
namespace Oxide.Plugins {
[Info("IQFakeActive", "IQFakeActive", "2.5.31")]
[Description("Simulate activity for a server with support for other plugins")]
public class IQFakeActive : RustPlugin {
private Timer initializationTimer;
private Dictionary<TypeInitialize, InitializedStatus> statusInitialized = new() {
[TypeInitialize.Messages]
= new InitializedStatus() {
IsInit = false, IsSuccess = false,
}
, [TypeInitialize.Players] = new InitializedStatus() {
IsInit = false, IsSuccess = false,
}
, [TypeInitialize.Online] = new InitializedStatus {
IsInit = false, IsSuccess = false,
}
, [TypeInitialize.Networks] = new InitializedStatus {
IsInit = false, IsSuccess = false,
}
, [TypeInitialize.ChatInformation] = new InitializedStatus {
IsInit = false, IsSuccess = false,
}
, [TypeInitialize.Avatars] = new InitializedStatus {
IsInit = false, IsSuccess = false,
}
,
}
;
private String GetWeaponDeathNote() {
if (config.deathNoteController.weaponDeathNote == null || config.deathNoteController.weaponDeathNote.Count == 0) return String.Empty;
List<Configuration.DeathNoteController.WeaponDeathNote> listWeapon = config.deathNoteController.weaponDeathNote.Where(x => TimeUnblockWeaponDeath(x.secondWipeTime) <= 0).ToList();
return listWeapon.Count == 0 ? String.Empty : listWeapon.GetRandom().weapon.GetRandom();
}
private String GetCountryConnected() => config.networkFakeController.countryConnectedList != null && config.networkFakeController.countryConnectedList.Count != 0 ? config.networkFakeController.countryConnectedList[Random.Range(0, config.networkFakeController.countryConnectedList.Count)] : null;
private enum TypeInitialize {
Messages, Players, Online, Networks, ChatInformation, Avatars,
}
private void Unload() {
if (initializationTimer != null) {
initializationTimer.Destroy();
initializationTimer = null;
}
if (timerRefreshDatabase != null) {
timerRefreshDatabase.Destroy();
timerRefreshDatabase = null;
}
if (timerChatMessages != null) {
timerChatMessages.Destroy();
timerChatMessages = null;
}
if (timerChatPmMessages != null) {
timerChatPmMessages.Destroy();
timerChatPmMessages = null;
}
if (timerNetworking != null) {
timerNetworking.Destroy();
timerNetworking = null;
}
if (timerDeathMessages != null) {
timerDeathMessages.Destroy();
timerDeathMessages = null;
}
if (routineAddedAvatars != null) {
ServerMgr.Instance.StopCoroutine(routineAddedAvatars);
routineAddedAvatars = null;
}
}
/// <summary>
/// - Исправлена работа с API DeathMessages by Voodoo после его обновления
/// </summary>
[PluginReference]
Plugin IQChat, ImageLibrary, DeathMessages, DeathMessage;
private void CheckFullInitialized() {
if(timerCheckInitialized is {
Destroyed : false
}
) timerCheckInitialized.Destroy();
if (statusInitialized[TypeInitialize.Messages].IsSuccess && statusInitialized[TypeInitialize.Online].IsSuccess && statusInitialized[TypeInitialize.Players].IsSuccess && statusInitialized[TypeInitialize.Networks].IsInit) {
IsFullInitialized = true;
Puts(LanguageEn ? "The plugin is fully initialized, and its functions are running" : "Плагин полностью инициализирован, функции запущены");
timerRefreshDatabase = timer.Once(600, RefresgDataBase);
if (IQChat && config.networkFakeController.useNetwork) timerNetworking = timer.Once(Random.Range(config.networkFakeController.minTimeUpdateNetwork, config.networkFakeController.maxTimeUpdateNetwork), StartNetworking);
if (config.messageFakeController.useMessageChat) timerChatMessages = timer.Once(Random.Range(config.messageFakeController.minTimeUpdateChat, config.messageFakeController.maxTimeUpdateChat), MessageImmitation);
if (config.messageFakeController.usePmMessage && IQChat) timerChatPmMessages = timer.Once(Random.Range(config.messageFakeController.minTimeUpdatePmChat, config.messageFakeController.maxTimeUpdatePmChat), MessagePmImmitation);
if (config.deathNoteController.useFakeDeathMessages && (DeathMessages || DeathMessage)) timerDeathMessages = timer.Once(GetTimeUpdateDeathNote(), SendDeathNote);
return;
}
timerCheckInitialized = timer.Once(5f, CheckFullInitialized);
}
public FakeDatabase fakeDatabase = new();
Boolean MuteAction(String idOrName, Boolean isMuted) {
if (!IsActiveAPIPlayers()) return false;
FakeDatabase.FakePlayer fakePlayer = fakeDatabase.fakePlayerList.FirstOrDefault(x => x.userId.Equals(idOrName) || x.displayName.Equals(idOrName));
if (fakePlayer == null) return false;
fakePlayer.isMuted = isMuted;
return true;
}
private readonly Dictionary<String, Int32> averageOnlineDataPattern = new() {
{
"00:00", 44
}
, {
"00:10", 41
}
, {
"00:20", 33
}
, {
"00:30", 27
}
, {
"00:40", 26
}
, {
"00:50", 25
}
, {
"01:00", 23
}
, {
"01:10", 18
}
, {
"01:20", 14
}
, {
"01:30", 11
}
, {
"01:40", 11
}
, {
"01:50", 12
}
, {
"02:00", 12
}
, {
"02:10", 8
}
, {
"02:20", 8
}
, {
"02:30", 8
}
, {
"02:40", 9
}
, {
"02:50", 9
}
, {
"03:00", 7
}
, {
"03:10", 7
}
, {
"03:20", 8
}
, {
"03:30", 6
}
, {
"03:40", 8
}
, {
"03:50", 8
}
, {
"04:00", 5
}
, {
"04:10", 5
}
, {
"04:20", 5
}
, {
"04:30", 4
}
, {
"04:40", 3
}
, {
"04:50", 3
}
, {
"05:00", 3
}
, {
"05:10", 3
}
, {
"05:20", 4
}
, {
"05:30", 5
}
, {
"05:40", 4
}
, {
"05:50", 4
}
, {
"06:00", 4
}
, {
"06:10", 4
}
, {
"06:20", 4
}
, {
"06:30", 2
}
, {
"06:40", 3
}
, {
"06:50", 2
}
, {
"07:00", 1
}
, {
"07:10", 3
}
, {
"07:20", 4
}
, {
"07:30", 4
}
, {
"07:40", 5
}
, {
"07:50", 6
}
, {
"08:00", 5
}
, {
"08:10", 7
}
, {
"08:20", 6
}
, {
"08:30", 4
}
, {
"08:40", 10
}
, {
"08:50", 9
}
, {
"09:00", 11
}
, {
"09:10", 10
}
, {
"09:20", 12
}
, {
"09:30", 13
}
, {
"09:40", 15
}
, {
"09:50", 17
}
, {
"10:00", 21
}
, {
"10:10", 21
}
, {
"10:20", 21
}
, {
"10:30", 23
}
, {
"10:40", 24
}
, {
"10:50", 25
}
, {
"11:00", 25
}
, {
"11:10", 24
}
, {
"11:20", 30
}
, {
"11:30", 31
}
, {
"11:40", 30
}
, {
"11:50", 32
}
, {
"12:00", 35
}
, {
"12:10", 37
}
, {
"12:20", 40
}
, {
"12:30", 38
}
, {
"12:40", 38
}
, {
"12:50", 35
}
, {
"13:00", 39
}
, {
"13:10", 41
}
, {
"13:20", 41
}
, {
"13:30", 44
}
, {
"13:40", 48
}
, {
"13:50", 50
}
, {
"14:00", 51
}
, {
"14:10", 56
}
, {
"14:20", 59
}
, {
"14:30", 67
}
, {
"14:40", 65
}
, {
"14:50", 67
}
, {
"15:00", 67
}
, {
"15:10", 74
}
, {
"15:20", 71
}
, {
"15:30", 71
}
, {
"15:40", 73
}
, {
"15:50", 73
}
, {
"16:00", 73
}
, {
"16:10", 74
}
, {
"16:20", 78
}
, {
"16:30", 78
}
, {
"16:40", 80
}
, {
"16:50", 79
}
, {
"17:00", 75
}
, {
"17:10", 78
}
, {
"17:20", 81
}
, {
"17:30", 84
}
, {
"17:40", 79
}
, {
"17:50", 69
}
, {
"18:00", 72
}
, {
"18:10", 71
}
, {
"18:20", 75
}
, {
"18:30", 75
}
, {
"18:40", 72
}
, {
"18:50", 69
}
, {
"19:00", 72
}
, {
"19:10", 66
}
, {
"19:20", 65
}
, {
"19:30", 71
}
, {
"19:40", 70
}
, {
"19:50", 72
}
, {
"20:00", 70
}
, {
"20:10", 69
}
, {
"20:20", 67
}
, {
"20:30", 69
}
, {
"20:40", 64
}
, {
"20:50", 62
}
, {
"21:00", 60
}
, {
"21:10", 62
}
, {
"21:20", 62
}
, {
"21:30", 63
}
, {
"21:40", 64
}
, {
"21:50", 59
}
, {
"22:00", 61
}
, {
"22:10", 60
}
, {
"22:20", 59
}
, {
"22:30", 54
}
, {
"22:40", 53
}
, {
"22:50", 50
}
, {
"23:00", 47
}
, {
"23:10", 46
}
, {
"23:20", 44
}
, {
"23:30", 45
}
, {
"23:40", 42
}
, {
"23:50", 43
}
}
;
private DateTime TimeCreatedSave;
private enum NetworkType {
Connected, Disconnected
}
private String GetNameDeathNote() => fakeDatabase.fakePlayerList.Count > 0 ? fakeDatabase.fakePlayerList.GetRandom().displayName : String.Empty;
private void GeneratePlayers() {
Configuration.PlayerFakeController playerDbConfigure = config.playerFakeController;
if (playerDbConfigure.playersDbType == DatabaseType.Local) {
List<FakeDatabase.FakePlayer> localFakePlayers = new();
if (playerDbConfigure.localDatabaseNickName == null || playerDbConfigure.localDatabaseNickName.Count == 0) {
WarningAndUnloadPlugin(LanguageEn ? "The local database does not contain any nicknames, generation is impossible" : "В локальной базе данных не указаны ники, генерация невозможна");
return;
}
List<String> distinctNickList = playerDbConfigure.localDatabaseNickName.Distinct().ToList();
List<UInt64> distinctSteamIDsList = new();
if(playerDbConfigure.localDatabaseSteamIds != null) distinctSteamIDsList = playerDbConfigure.localDatabaseSteamIds.Distinct().ToList();
for (Int32 player = 0; player < distinctNickList.Count; player++) {
UInt64 steamId;
String displayName = playerDbConfigure.localDatabaseNickName[player];
if (distinctSteamIDsList.Count != 0 && player < distinctSteamIDsList.Count) steamId = distinctSteamIDsList[player];
else steamId = GenerateUniqueSteamID();
FakeDatabase.FakePlayer fakePlayer = new() {
displayName = displayName, userId = steamId.ToString(),
}
;
localFakePlayers.Add(fakePlayer);
}
fakeDatabase.fakePlayerList = localFakePlayers;
statusInitialized[TypeInitialize.Players].IsInit = true;
statusInitialized[TypeInitialize.Players].IsSuccess = true;
Puts(LanguageEn ? $"Generation of players from the local database - successful, {fakeDatabase.fakePlayerList.Count} players were obtained" : $"Генерация игроков с локальной базы - успешно, было получено : {fakeDatabase.fakePlayerList.Count} игроков");
return;
}
try {
webrequest.Enqueue(ApiPlayers, null, (code, response) => {
switch (code) {
case 503 : WarningAndUnloadPlugin(LanguageEn ? "An update for the plugin is available.Please update the plugin version to allow database connection" : "Вышло обновление плагина, обновите версию плагина чтобы вы могли подключаться в базе-данных!");
return;
case 404 : case 500 : case 401 : WarningAndUnloadPlugin(LanguageEn ? "An error occurred in the database server.Please report this to the developer" : "Произошла ошибка на сервере базы-данных, сообщите разработчику об этом");
return;
case 429 : WarningAndUnloadPlugin(LanguageEn ? "The request limit to the cloud database has been exceeded! Your IP is blocked for 2 hours" : "Превышен лимит запросов к облачной базе данных! Ваш IP заблокирован на 2 часа");
return;
default : if (response == null) {
WarningAndUnloadPlugin(LanguageEn ? "An error occurred on the database server.The response came back empty (null).Please report this to the developer" : "Произошла ошибка на сервере базы-данных, ответ пришел пустым (null) сообщите разработчику об этом");
return;
}
fakeDatabase.fakePlayerList = JsonConvert.DeserializeObject<List<FakeDatabase.FakePlayer>>(response);
if (!statusInitialized[TypeInitialize.Players].IsSuccess) statusInitialized[TypeInitialize.Players].IsSuccess = true;
Puts(LanguageEn ? $"Players generation from the cloud - successful, {fakeDatabase.fakePlayerList.Count} player templates were received" : $"Генерация игроков с облака - успешно, было получено : {fakeDatabase.fakePlayerList.Count} шаблонов игроков");
break;
}
}
, this, timeout : 120f);
}
catch (Exception ex) {
PrintError(LanguageEn ? $"Unexpected error while generating the player database from the cloud, error:\n\n{ex.ToString()}" : $"Неожиданная ошибка генерации базы игроков с облака, ошибка\n\n{ex.ToString()}");
}
}
private void GenerateConnectionPlayer() {
if (!IQChat) {
PrintWarning(LanguageEn ? "You don't have IQChat installed, functions for connecting and disconnecting fake players will be unavailable" : "У вас не установлен IQChat, функции подключений и отключений фейковых игроков будут недоступны");
return;
}
if (fakeDatabase.fakePlayerList.Count < 80) {
PrintWarning(LanguageEn ? "Not enough fake players generated for simulating connections and disconnections; you should have at least 80 players in the database" : "Недостаточно сгенерировано фейковых игроков для генерации подключений и отключений, у вас должно быть не меньше 80 игроков в базе");
return;
}
Int32 conAmount = 0;
for (Int32 con = 0; con < 30; con++) {
if (fakeDatabase.fakePlayerList.Count < con) continue;
fakeDatabase.fakePlayerConnection.Add(fakeDatabase.fakePlayerList[con]);
fakeDatabase.fakePlayerList.RemoveAt(con);
conAmount = con;
}
Int32 disconAmount = 0;
for (Int32 con = 0; con < 30; con++) {
if (fakeDatabase.fakePlayerList.Count < con) continue;
fakeDatabase.fakePlayerDisconnection.Add(fakeDatabase.fakePlayerList[con]);
fakeDatabase.fakePlayerList.RemoveAt(con);
disconAmount = con;
}
statusInitialized[TypeInitialize.Networks].IsSuccess = true;
Puts(LanguageEn ? "60 users were generated from the player database for connections and disconnections on the server" : "Из базы игроков было сгенерировано 60 пользователей для подключений и отключений с сервера");
}
private readonly DateTime RealTime = DateTime.UtcNow.Date;
private HashSet<UInt64> usedSteamIds = new HashSet<UInt64>();
private void SendDeathNote() {
if (!IsFullInitialized) return;
if(timerDeathMessages is {
Destroyed : false
}
) timerDeathMessages.Destroy();
if (!DeathMessages && !DeathMessage) return;
String killerName = GetNameDeathNote();
if (String.IsNullOrWhiteSpace(killerName)) return;
String killedName = GetNameDeathNote();
if (String.IsNullOrWhiteSpace(killedName)) return;
if (killerName.Equals(killedName)) return;
String weapon = GetWeaponDeathNote();
if (String.IsNullOrWhiteSpace(weapon)) return;
Single distanceKilled = Random.Range(30f, 300f);
Boolean isHeadshot = Random.Range(0, 2) == 0;
if (DeathMessages) DeathMessages.CallHook("CreateNote", killerName, killedName, distanceKilled, "", "", weapon, new string[] {
}
, isHeadshot, false, false);
else if (DeathMessage) DeathMessage.Call("Send_Kill_Player_Note", "PlayerKillPlayer", killerName, weapon, killedName, $"{distanceKilled}");
timerDeathMessages = timer.Once(GetTimeUpdateDeathNote(), SendDeathNote);
}
private UInt64 GenerateUniqueSteamID(UInt64 randomAmount = 0) {
UInt64 steamId = (UInt64)Random.Range(76561100000000000, 76561199999999999) + randomAmount;
if (usedSteamIds.Contains(steamId)) return GenerateUniqueSteamID((UInt64)Random.Range(1, 20000));
usedSteamIds.Add(steamId);
return steamId;
}
private Dictionary<BasePlayer, String> lastPlayerPmMessage = new();
JObject GetOnlyListFakePlayers() {
if (!IsActiveAPIPlayers()) return null;
return JObject.FromObject(new {
players = fakeDatabase.fakePlayerList
}
);
}
private void GeneratePlayerPreset() {
if (IQChat) {
if (IQChat.Version < new Oxide.Core.VersionNumber(2, 39, 17)) {
WarningAndUnloadPlugin(LanguageEn ? "You have an outdated version of the IQChat plugin, the plugin cannot access the API, update the IQChat plugin to version 2.39.17 or higher" : "У вас устаревшая версия плагина IQChat, плагин не может получить доступ к API, обновите плагин IQChat до версии 2.39.17 или выше");
return;
}
fakeDatabase.chatPresetFakePlayer.chatColor = IQChat.Call<String>("API_GET_DEFAULT_MESSAGE_COLOR");
if (String.IsNullOrEmpty(fakeDatabase.chatPresetFakePlayer.chatColor)) fakeDatabase.chatPresetFakePlayer.chatColor = "#ffffff";
fakeDatabase.chatPresetFakePlayer.chatPrefix = IQChat.Call<String>("API_GET_DEFAULT_PREFIX");
fakeDatabase.chatPresetFakePlayer.nickColor = IQChat.Call<String>("API_GET_DEFAULT_NICK_COLOR");
if (String.IsNullOrEmpty(fakeDatabase.chatPresetFakePlayer.nickColor)) fakeDatabase.chatPresetFakePlayer.nickColor = "#55aafe";
fakeDatabase.chatPresetFakePlayer.sizeMessage = IQChat.Call<Int32>("API_GET_DEFAULT_SIZE_MESSAGE");
fakeDatabase.chatPresetFakePlayer.sizeNick = IQChat.Call<Int32>("API_GET_DEFAULT_SIZE_NICK");
}
else {
fakeDatabase.chatPresetFakePlayer.chatColor = "#ffffff";
fakeDatabase.chatPresetFakePlayer.chatPrefix = String.Empty;
fakeDatabase.chatPresetFakePlayer.nickColor = "#1F6BA0";
fakeDatabase.chatPresetFakePlayer.sizeMessage = 14;
fakeDatabase.chatPresetFakePlayer.sizeNick = 14;
}
statusInitialized[TypeInitialize.ChatInformation].IsSuccess = true;
Puts(LanguageEn ? "Chat presets for fake players have been created" : "Созданы пресеты в чате для фейковых игроков");
}
private Queue<String> lastMessages = new();
private Double TimeUnblockWeaponDeath(Int32 BlockTime) => (SaveRestore.SaveCreatedTime.ToUniversalTime().Subtract(epoch).TotalSeconds + BlockTime) - CurrentTime;
private readonly Regex _avatarRegex = new(@"<avatarFull><!\[CDATA\[(.*)\]\]></avatarFull>", RegexOptions.Compiled);
private void MessageImmitation() {
if (!IsFullInitialized) return;
if (!statusInitialized[TypeInitialize.ChatInformation].IsSuccess || !statusInitialized[TypeInitialize.Messages].IsSuccess || !statusInitialized[TypeInitialize.Players].IsSuccess) return;
if(timerChatMessages is {
Destroyed : false
}
) timerChatMessages.Destroy();
FakeDatabase.FakePlayer fakePlayer = GetRandomFakePlayer();
if (fakePlayer == null) return;
String fakeMessage = GetFakeMessage();
if (fakeMessage == null) return;
String fakeDisplayName = $"<size={fakeDatabase.chatPresetFakePlayer.sizeNick}><color={fakeDatabase.chatPresetFakePlayer.nickColor}>{fakePlayer.displayName}</color></size>";
String fakeFormatPlayer = $"{fakeDatabase.chatPresetFakePlayer.chatPrefix} {fakeDisplayName}";
String fakeMessageFormat = $"<size={fakeDatabase.chatPresetFakePlayer.sizeMessage}><color={fakeDatabase.chatPresetFakePlayer.chatColor}>{fakeMessage}</color></size>";
LogToConsole(LanguageEn ? $"Message sent in chat: [{fakeDatabase.chatPresetFakePlayer.chatPrefix}]{fakeDisplayName}: {fakeMessage}" : $"Отправлено сообщение в чат : [{fakeDatabase.chatPresetFakePlayer.chatPrefix}]{fakeDisplayName} : {fakeMessage}");
foreach (BasePlayer player in BasePlayer.activePlayerList) {
if (IQChat) IQChat.CallHook("API_SEND_PLAYER", player, fakeFormatPlayer, fakeMessageFormat, $"{fakePlayer.userId}");
else player.SendConsoleCommand("chat.add", 0, fakePlayer.userId, $"{fakeFormatPlayer}: {fakeMessageFormat}");
}
timerChatMessages = timer.Once(Random.Range(config.messageFakeController.minTimeUpdateChat, config.messageFakeController.maxTimeUpdateChat), MessageImmitation);
}
private void RefresgDataBase() {
if(timerRefreshDatabase is {
Destroyed : false
}
) timerRefreshDatabase.Destroy();
if (!IsFullInitialized) return;
GenerateMessages();
GenerateOnline();
timerRefreshDatabase = timer.Once(600, RefresgDataBase);
}
Int32 GetOnlyFakeOnline() => !IsActiveAPIPlayers() ? BasePlayer.activePlayerList.Count : fakeDatabase.onlineDatabase.currentFakeOnline;
private class InitializedStatus {
public Boolean IsInit;
public Boolean IsSuccess;
}
public class FakeDatabase {
public OnlineDatabase onlineDatabase = new();
public ChatPresetFakePlayer chatPresetFakePlayer = new();
public List<FakePlayer> fakePlayerList = new();
public List<FakePlayer> fakePlayerConnection = new();
public List<FakePlayer> fakePlayerDisconnection = new();
public List<FakePlayer> realAndFakePlayerList = new();
public List<Messages> fakeMessageList = new();
public class Messages {
[JsonProperty("message")]
public String message;
}
public class OnlineDatabase {
public Int32 currentFakeOnline;
public Int32 currentOnline;
}
public class FakePlayer {
[JsonProperty("userId")]
public String userId;
[JsonProperty("displayName")]
public String displayName;
public Boolean isMuted;
}
public class ChatPresetFakePlayer {
public String chatPrefix;
public String chatColor;
public String nickColor;
public Int32 sizeMessage;
public Int32 sizeNick;
}
}
private void GenerateOnline() {
fakeDatabase.onlineDatabase.currentFakeOnline = GenerateOnlineCount();
fakeDatabase.onlineDatabase.currentOnline = fakeDatabase.onlineDatabase.currentFakeOnline + BasePlayer.activePlayerList.Count;
}
String GetFakeName(String userId) {
if (!IsActiveAPIPlayers()) return "initializePlugin";
FakeDatabase.FakePlayer fakePlayer = fakeDatabase.fakePlayerList.FirstOrDefault(x => x.userId.Equals(userId));
return fakePlayer == null ? "notFindedUser" : fakePlayer.displayName;
}
Int32 GetOnline() => !IsActiveAPIPlayers() ? BasePlayer.activePlayerList.Count : fakeDatabase.onlineDatabase.currentOnline;
private IEnumerator GenerateAvatars() {
if (ImageLibrary is null) yield break;
foreach (FakeDatabase.FakePlayer fakePlayer in fakeDatabase.fakePlayerList) {
webrequest.Enqueue($"https://steamcommunity.com/profiles/{fakePlayer.userId}?xml=1", null, (code, response) => {
if (code != 200 || response is null) return;
String avatarUrl = _avatarRegex.Match(response).Groups[1].ToString();
if (!String.IsNullOrEmpty(avatarUrl) && !HasImage(fakePlayer.userId)) AddImage(avatarUrl, fakePlayer.userId);
}
, this, timeout : 2f);
yield return new WaitForSeconds(0.1f);
}
statusInitialized[TypeInitialize.Avatars].IsSuccess = true;
Puts(LanguageEn ? "Generating fake avatars for ImageLibrary - successful" : "Генерация фейковых аватарок для ImageLibrary - успешно");
}
private Int32 GetTimeUpdateDeathNote() {
Configuration.DeathNoteController deathController = config.deathNoteController;
Int32 interval = Random.Range(deathController.minTimeUpdateDeath, deathController.maxTimeUpdateDeath);
if (!deathController.useCorrectedInterval) return interval;
interval = (Int32)(interval * (1.0f - GetOnline() / ConVar.Server.maxplayers));
if (interval < deathController.limitCorrected) interval = deathController.limitCorrected;
return interval;
}
private static Double CurrentTime => Facepunch.Math.Epoch.Current;
private void InitializeProccess() {
if (!statusInitialized[TypeInitialize.ChatInformation].IsInit) {
GeneratePlayerPreset();
statusInitialized[TypeInitialize.ChatInformation].IsInit = true;
}
else if (!statusInitialized[TypeInitialize.Messages].IsInit) {
GenerateMessages();
statusInitialized[TypeInitialize.Messages].IsInit = true;
}
else if (!statusInitialized[TypeInitialize.Messages].IsSuccess) GenerateMessages();
else if (!statusInitialized[TypeInitialize.Players].IsInit) {
GeneratePlayers();
statusInitialized[TypeInitialize.Players].IsInit = true;
}
else if (!statusInitialized[TypeInitialize.Players].IsSuccess) GeneratePlayers();
else if (!statusInitialized[TypeInitialize.Online].IsInit) {
GenerateOnline();
statusInitialized[TypeInitialize.Online].IsInit = true;
statusInitialized[TypeInitialize.Online].IsSuccess = true;
Puts(LanguageEn ? $"Online initialized: number of fake players - {fakeDatabase.onlineDatabase.currentFakeOnline} : displayed online - {fakeDatabase.onlineDatabase.currentOnline}" : $"Онлайн инициализирован : количество фейковых игроков - {fakeDatabase.onlineDatabase.currentFakeOnline} : отображаемый онлайн - {fakeDatabase.onlineDatabase.currentOnline}");
}
else if (!statusInitialized[TypeInitialize.Avatars].IsInit && ImageLibrary) {
Puts(LanguageEn ? "The process of generating fake avatars for ImageLibrary has started, and this may take some time" : "Запущен процесс генерации фейковых аватарок для ImageLibrary, это может занять некоторое время");
if (routineAddedAvatars == null) routineAddedAvatars = ServerMgr.Instance.StartCoroutine(GenerateAvatars());
else {
ServerMgr.Instance.StopCoroutine(routineAddedAvatars);
routineAddedAvatars = ServerMgr.Instance.StartCoroutine(GenerateAvatars());
}
statusInitialized[TypeInitialize.Avatars].IsInit = true;
}
else if (!statusInitialized[TypeInitialize.Avatars].IsInit && !ImageLibrary) {
statusInitialized[TypeInitialize.Avatars].IsInit = true;
statusInitialized[TypeInitialize.Avatars].IsSuccess = true;
}
else if (!statusInitialized[TypeInitialize.Networks].IsInit && statusInitialized[TypeInitialize.Avatars].IsSuccess) {
if (config.networkFakeController.useNetwork) GenerateConnectionPlayer();
statusInitialized[TypeInitialize.Networks].IsInit = true;
if (initializationTimer != null) {
initializationTimer.Destroy();
initializationTimer = null;
}
}
}
private void DisconnectPlayer() {
if (fakeDatabase.fakePlayerConnection.Count == 0) return;
Int32 randomIndexDisconnected = Random.Range(0, fakeDatabase.fakePlayerConnection.Count);
FakeDatabase.FakePlayer playerDisconnected = fakeDatabase.fakePlayerConnection[randomIndexDisconnected];
String reason = GetReasonDisconnected();
if (reason == null) return;
IQChat.Call("API_SEND_PLAYER_DISCONNECTED", playerDisconnected.displayName, reason, playerDisconnected.userId);
fakeDatabase.fakePlayerConnection.Add(playerDisconnected);
fakeDatabase.fakePlayerDisconnection.RemoveAt(randomIndexDisconnected);
lastNetworkType = NetworkType.Disconnected;
LogToConsole(LanguageEn ? $"Simulating player disconnection: {playerDisconnected.displayName}" : $"Имитация отключения игрока : {playerDisconnected.displayName}");
}
private Single GetPercentWipeOnline(Int32 wipelocal) {
if (!config.onlineController.wipeTimeOnlineOffset.ContainsKey(wipelocal)) return 1.0f;
return 1.0f - (config.onlineController.wipeTimeOnlineOffset[wipelocal] / 100.0f);
}
private Coroutine routineAddedAvatars = null;
protected override void LoadConfig() {
base.LoadConfig();
try {
config = Config.ReadObject<Configuration>();
if (config == null) LoadDefaultConfig();
if (config.deathNoteController == null) {
config.deathNoteController = new Configuration.DeathNoteController() {
useFakeDeathMessages = false, weaponDeathNote = new List<Configuration.DeathNoteController.WeaponDeathNote>() {
new() {
secondWipeTime = 18000, weapon = new List<String>() {
"bow.hunting", "bone.club", "salvaged.sword", "spear.wooden", "spear.stone", "pistol.nailgun", "shotgun.waterpipe",
}
}
, new() {
secondWipeTime = 25200, weapon = new List<String>() {
"pistol.m92", "shotgun.double", "pistol.revolver", "pistol.semiauto", "pistol.python",
}
}
, new() {
secondWipeTime = 36000, weapon = new List<String>() {
"smg.2", "smg.thompson", "rifle.semiauto", "smg.mp5",
}
}
, new() {
secondWipeTime = 86400, weapon = new List<String>() {
"rifle.bolt", "rifle.lr300", "rifle.ak",
}
}
, new() {
secondWipeTime = 108000, weapon = new List<String>() {
"rifle.l96", "rifle.m39", "multiplegrenadelauncher", "lmg.m249",
}
}
,
}
, minTimeUpdateDeath = 60, maxTimeUpdateDeath = 120, useCorrectedInterval = false, limitCorrected = 30,
}
;
}
}
catch {
PrintWarning(LanguageEn ? $"Error reading #54327 configuration 'oxide/config/{Name}', creating a new configuration!!" : $"Ошибка чтения #54327 конфигурации 'oxide/config/{Name}', создаём новую конфигурацию!!");
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
private void OnServerInitialized() {
TimeCreatedSave = SaveRestore.SaveCreatedTime.Date;
WipeTime = RealTime.Subtract(TimeCreatedSave).Days;
CheckFullInitialized();
initializationTimer = timer.Every(5f, InitializeProccess);
}
private Boolean IsActiveAPIPlayers() {
if (!IsFullInitialized) return false;
return statusInitialized[TypeInitialize.Players].IsInit && statusInitialized[TypeInitialize.Players].IsSuccess;
}
private void GenerateMessages() {
if (config.messageFakeController.messageDbType == DatabaseType.Local) {
fakeDatabase.fakeMessageList = config.messageFakeController.localDatabaseMessages.Select(message => new FakeDatabase.Messages {
message = message
}
).ToList();
statusInitialized[TypeInitialize.Messages].IsInit = true;
statusInitialized[TypeInitialize.Messages].IsSuccess = true;
Puts(LanguageEn ? $"Generating messages from the local database - successful, received: {fakeDatabase.fakeMessageList.Count} messages" : $"Генерация сообщений с локальной базы - успешно, было получено : {fakeDatabase.fakeMessageList.Count} сообщений");
return;
}
try {
webrequest.Enqueue(ApiMessages, null, (code, response) => {
switch (code) {
case 503 : WarningAndUnloadPlugin(LanguageEn ? "An update for the plugin is available.Please update the plugin version to allow database connection" : "Вышло обновление плагина, обновите версию плагина чтобы вы могли подключаться в базе-данных!");
return;
case 404 : case 500 : case 401 : WarningAndUnloadPlugin(LanguageEn ? "An error occurred in the database server.Please report this to the developer" : "Произошла ошибка на сервере базы-данных, сообщите разработчику об этом");
return;
case 429 : WarningAndUnloadPlugin(LanguageEn ? "The request limit to the cloud database has been exceeded! Your IP is blocked for 2 hours" : "Превышен лимит запросов к облачной базе данных! Ваш IP заблокирован на 2 часа");
return;
default : if (response == null) {
WarningAndUnloadPlugin(LanguageEn ? "An error occurred on the database server.The response came back empty (null).Please report this to the developer" : "Произошла ошибка на сервере базы-данных, ответ пришел пустым (null) сообщите разработчику об этом");
return;
}
fakeDatabase.fakeMessageList = JsonConvert.DeserializeObject<List<FakeDatabase.Messages>>(response);
if (fakeDatabase.fakeMessageList.Count == 0) {
WarningAndUnloadPlugin(LanguageEn ? "No messages were received during generation! Report this issue to the developer" : "Во время генерации не было получено сообщений! Сообщите разработчику об этой проблеме");
return;
}
if (!statusInitialized[TypeInitialize.Messages].IsSuccess) statusInitialized[TypeInitialize.Messages].IsSuccess = true;
Puts(LanguageEn ? $"Generating messages from the cloud - successful, received: {fakeDatabase.fakeMessageList.Count} messages" : $"Генерация сообщений с облака - успешно, было получено : {fakeDatabase.fakeMessageList.Count} сообщений");
break;
}
}
, this, timeout : 5f);
}
catch (Exception ex) {
PrintError(LanguageEn ? $"Unexpected error while generating the player database from the cloud, error:\n\n{ex.ToString()}" : $"Неожиданная ошибка генерации базы игроков с облака, ошибка\n\n{ex.ToString()}");
}
}
private String GetFakeMessage() {
if (!IsFullInitialized) return null;
if (fakeDatabase.fakeMessageList == null || fakeDatabase.fakeMessageList.Count == 0) return null;
String message = null;
for (Int32 i = 0; i < maxAttemptsGetMessage; i++) {
Int32 randomIndex = Core.Random.Range(0, fakeDatabase.fakeMessageList.Count);
message = fakeDatabase.fakeMessageList[randomIndex].message;
if (!lastMessages.Contains(message)) {
lastMessages.Enqueue(message);
if (lastMessages.Count > 5) lastMessages.Dequeue();
break;
}
}
return message;
}
private Timer timerDeathMessages;
private const String ApiPlayers = "https://iqsystem.skyplugins.ru/iqsystem/iqfakeactive/getplayers/v5rsBqzl7wCvFqb45b56bb45/350";
private Boolean AddImage(String url, String shortname, UInt64 skin = 0) => (Boolean)ImageLibrary?.Call("AddImage", url, shortname, skin);
private void StartNetworking() {
if (!IsFullInitialized) return;
if (!statusInitialized[TypeInitialize.Networks].IsSuccess) return;
if(timerNetworking is {
Destroyed : false
}
) timerNetworking.Destroy();
if (!IQChat) return;
if (lastNetworkType == NetworkType.Disconnected) ConnectPlayer();
else DisconnectPlayer();
timerNetworking = timer.Once(Random.Range(config.networkFakeController.minTimeUpdateNetwork, config.networkFakeController.maxTimeUpdateNetwork), StartNetworking);
}
private Timer timerChatMessages;
private Single GetPercentMaxFake => 1.0f - (config.onlineController.onlineMaxPercent / 100.0f);
protected override void SaveConfig() => Config.WriteObject(config);
JObject GetDatabase() {
if (!IsFullInitialized) return null;
List<FakeDatabase.FakePlayer> realPlayers = GetFInPlayers();
List<FakeDatabase.FakePlayer> realAndFake = new();
realAndFake.AddRange(realPlayers);
realAndFake.AddRange(fakeDatabase.fakePlayerList);
fakeDatabase.realAndFakePlayerList = realAndFake;
return JObject.FromObject(fakeDatabase);
}
private const Int32 maxAttemptsGetRandomFakePlayer = 5;
private void WarningAndUnloadPlugin(String Message) {
PrintWarning(Message);
NextTick(() => {
Interface.Oxide.UnloadPlugin(Name);
}
);
}
protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
public Boolean HasImage(String imageName) => (Boolean)ImageLibrary?.Call("HasImage", imageName);
private enum DatabaseType {
Cloud, Local,
}
private String GetReasonDisconnected() => config.networkFakeController.reasonDisconnectedList != null && config.networkFakeController.reasonDisconnectedList.Count != 0 ? config.networkFakeController.reasonDisconnectedList[Random.Range(0, config.networkFakeController.reasonDisconnectedList.Count)] : null;
private String GetPmFakeMessage(BasePlayer player) {
if (!IsFullInitialized) return null;
if (config.messageFakeController.localDatabasePmMessage == null || config.messageFakeController.localDatabasePmMessage.Count == 0) return null;
String message = null;
if (!lastPlayerPmMessage.ContainsKey(player)) {
message = config.messageFakeController.localDatabasePmMessage[Core.Random.Range(0, config.messageFakeController.localDatabasePmMessage.Count)];
lastPlayerPmMessage.Add(player, message);
return message;
}
for (Int32 i = 0; i < maxAttemptsGetMessage; i++) {
Int32 randomIndex = Core.Random.Range(0, config.messageFakeController.localDatabasePmMessage.Count);
message = config.messageFakeController.localDatabasePmMessage[randomIndex];
if (!lastPlayerPmMessage[player].Equals(message)) {
lastPlayerPmMessage[player] = message;
break;
}
}
lastPlayerPmMessage[player] = message;
return message;
}
private readonly String ApiMessages = $"https://iqsystem.skyplugins.ru/iqsystem/iqfakeactive/getmessages/v5rsBqzl7wCvFqb45b56bb45/600/{LanguageEn}";
private void MessagePmImmitation() {
if (!IsFullInitialized) return;
if (!statusInitialized[TypeInitialize.ChatInformation].IsSuccess || !
// ... [Code preview truncated due to length. Full source in attached file] ...