Иконка ресурса

FREE SNoSteamOld : 1.5 1.5

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
/*
      

   ▄████████    ▄████████     ███        ▄████████    ▄███████▄    ▄████████
  ███    ███   ███    ███ ▀█████████▄   ███    ███   ███    ███   ███    ███
  ███    █▀    ███    █▀     ▀███▀▀██   ███    █▀    ███    ███   ███    █▀ 
  ███         ▄███▄▄▄         ███   ▀  ▄███▄▄▄       ███    ███   ███       
▀███████████ ▀▀███▀▀▀         ███     ▀▀███▀▀▀     ▀█████████▀  ▀███████████
         ███   ███    █▄      ███       ███          ███                 ███
   ▄█    ███   ███    ███     ███       ███          ███           ▄█    ███
 ▄████████▀    ██████████    ▄████▀     ███         ▄████▀       ▄████████▀ 


 POWERED BY SETFPS | TG: @setfps
 
*/


//#define isOldVersion // Закомментируйте для новых версий Rust (266 devblog и выше)



// Reference: 0Harmony
using Harmony;
using Network;
using Oxide.Core;
using Rust.Platform.Steam;
using Steamworks;
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Collections.Generic;
using Newtonsoft.Json;
using Facepunch.Math;
using Facepunch;
using Rust;
using UnityEngine;
using Oxide.Core.Plugins;


namespace Oxide.Plugins
{
    [Info("SNoSteam", "setfps", "1.5")]
    [Description("nosteam for super old devblogs (with old harmony)")]
    public class SNoSteamOld : RustPlugin
    {
        #region Fields
        private static HarmonyInstance _harmony;
        private static MethodInfo _onAuthenticatedLocal;
        private static MethodInfo _onAuthenticatedRemote;
        private static ConnectionAuth _connectionAuth;
        private static SNoSteamOld _instance;
        private Configuration config;
        private int _lastFakeOnline = -1;
        private DateTime _lastMajorChange = DateTime.MinValue;
        private readonly System.Random _random = new System.Random();
        #endregion

        #region API
        private int GetCurrentFakeOnline() => _lastFakeOnline;

        /// <summary>
        /// API метод для получения текущего фейкового онлайна
        /// </summary>
        /// <returns>Текущее количество фейковых игроков на сервере</returns>
        [HookMethod("GetFakeOnline")]
        private int GetFakeOnline()
        {
            return _lastFakeOnline != -1 ? _lastFakeOnline : 0;
        }
        #endregion

        #region Configuration
        private class Configuration
        {
            [JsonProperty(PropertyName = "Временные слоты (настройка онлайна для разных периодов времени)")]
            public List<TimeSlot> TimeSlots { get; set; }

            [JsonProperty(PropertyName = "Включить реалистичные изменения онлайна (плавные изменения и учет времени суток)")]
            public bool UseRealisticPatterns { get; set; }

            [JsonProperty(PropertyName = "Максимальное отклонение от текущего онлайна за одно обновление")]
            public int MaxPlayersChangeAtOnce { get; set; }

            [JsonProperty(PropertyName = "Вероятность изменения количества игроков при каждом обновлении (0.0 - 1.0)")]
            public float PlayerChangeChance { get; set; }

            [JsonProperty(PropertyName = "Максимальное случайное отклонение от целевого значения")]
            public int MaxRandomDeviation { get; set; }

            public static Configuration DefaultConfig()
            {
                return new Configuration
                {
                    TimeSlots = new List<TimeSlot>
                    {
                        new TimeSlot { StartHour = 0, EndHour = 6, MinPlayers = 5, MaxPlayers = 15, ChangeFrequency = 8, Description = "Ночное время (00:00 - 06:00)" },
                        new TimeSlot { StartHour = 6, EndHour = 12, MinPlayers = 15, MaxPlayers = 35, ChangeFrequency = 5, Description = "Утреннее время (06:00 - 12:00)" },
                        new TimeSlot { StartHour = 12, EndHour = 18, MinPlayers = 35, MaxPlayers = 65, ChangeFrequency = 3, Description = "Дневное время (12:00 - 18:00)" },
                        new TimeSlot { StartHour = 18, EndHour = 24, MinPlayers = 25, MaxPlayers = 45, ChangeFrequency = 4, Description = "Вечернее время (18:00 - 00:00)" }
                    },
                    UseRealisticPatterns = true,
                    MaxPlayersChangeAtOnce = 2,
                    PlayerChangeChance = 0.7f,
                    MaxRandomDeviation = 3
                };
            }
        }

        private class TimeSlot
        {
            [JsonProperty(PropertyName = "Начальный час периода (0-23)")] public int StartHour { get; set; }
            [JsonProperty(PropertyName = "Конечный час периода (1-24)")] public int EndHour { get; set; }
            [JsonProperty(PropertyName = "Минимальное количество фейковых игроков")] public int MinPlayers { get; set; }
            [JsonProperty(PropertyName = "Максимальное количество фейковых игроков")] public int MaxPlayers { get; set; }
            [JsonProperty(PropertyName = "Частота изменения базового количества игроков (в минутах)")] public int ChangeFrequency { get; set; }
            [JsonProperty(PropertyName = "Описание временного периода")] public string Description { get; set; }
            [JsonIgnore] private int _lastPlayerCount = -1;
            [JsonIgnore] private DateTime _lastChange = DateTime.MinValue;

            public int GetTargetPlayers(DateTime now, int currentPlayers, System.Random random)
            {
                if (_lastPlayerCount == -1 || (now - _lastChange).TotalMinutes >= ChangeFrequency)
                {
                    _lastPlayerCount = random.Next(MinPlayers, MaxPlayers + 1);
                    _lastChange = now;
                }
                return _lastPlayerCount;
            }
        }
        #endregion

        #region Oxide Hooks
        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Ошибка чтения конфигурации, создаю новую!");
                LoadDefaultConfig();
            }
        }

        protected override void LoadDefaultConfig()
        {
            config = Configuration.DefaultConfig();
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(config);
        }

        private void OnServerInitialized()
        {
            _instance = this;
            
            ParseReflections();
            Server.Command("encryption 0"); //disable EAC encryption unuseble trash
            PrintWarning("the developer of this modification in tg @setfps");

            if (_harmony == null)
                _harmony = HarmonyInstance.Create("com.setfps.SNoSteamOld");

            PatchMethods();
        }

        private void Unload()
        {
            _harmony?.UnpatchAll("com.setfps.SNoSteamOld");
        }
        #endregion

        #region Methods
        private static void ParseReflections()
        {
            _onAuthenticatedLocal = typeof(EACServer).GetMethod("OnAuthenticatedLocal", BindingFlags.Static | BindingFlags.NonPublic);

            _onAuthenticatedRemote = typeof(EACServer).GetMethod("OnAuthenticatedRemote", BindingFlags.Static | BindingFlags.NonPublic);
        }

        private static void PatchMethods()
        {
            var steamPlatformType = typeof(SteamPlatform);
            var eacServerType = typeof(EACServer);
            var connectionAuthType = typeof(ConnectionAuth);
            var steamInventoryType = typeof(SteamInventory);
            var authSteamType = typeof(Auth_Steam);
            var serverMgrType = typeof(ServerMgr);

            _harmony.Patch(AccessTools.Method(steamPlatformType, "LoadPlayerStats"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.LoadPlayerStats)));

            _harmony.Patch(AccessTools.Method(eacServerType, "OnJoinGame"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.OnJoinGame)));

            _harmony.Patch(AccessTools.Method(connectionAuthType, "OnNewConnection"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.OnNewConnection)));

            _harmony.Patch(AccessTools.Method(steamInventoryType, "OnRpcMessage"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.OnRpcMessage)));

            _harmony.Patch(AccessTools.Method(authSteamType, "ValidateConnecting"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.ValidateConnecting)));

            _harmony.Patch(AccessTools.Method(steamPlatformType, "UpdatePlayerSession"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.UpdatePlayerSession)));

            _harmony.Patch(AccessTools.Method(steamPlatformType, "EndPlayerSession"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.EndPlayerSession)));

            _harmony.Patch(AccessTools.Method(steamPlatformType, "BeginPlayerSession"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.BeginPlayerSession)));

            _harmony.Patch(AccessTools.Method(serverMgrType, "UpdateServerInformation"),
                new HarmonyMethod(typeof(PatchingHooks), nameof(PatchingHooks.UpdateServerInformation)));
        }
        #endregion

        #region Helper Methods
        private int CalculateFakeOnline()
        {
            var now = DateTime.Now;
            var currentHour = now.Hour;
            var currentMinute = now.Minute;
            var basePlayerCount = BasePlayer.activePlayerList.Count;

            var currentSlot = config.TimeSlots.FirstOrDefault(slot =>
                currentHour >= slot.StartHour && currentHour < slot.EndHour);

            if (currentSlot == null)
                return basePlayerCount;

            if (_lastFakeOnline == -1)
            {
                _lastFakeOnline = basePlayerCount + _random.Next(currentSlot.MinPlayers, currentSlot.MaxPlayers + 1);
                return _lastFakeOnline;
            }

            var targetPlayers = currentSlot.GetTargetPlayers(now, _lastFakeOnline, _random);

            if (_random.NextDouble() > config.PlayerChangeChance)
                return _lastFakeOnline;

            var change = CalculateRealisticChange(now, currentHour, _lastFakeOnline, targetPlayers);

            var newOnline = Math.Max(basePlayerCount, _lastFakeOnline + change);
            newOnline = Math.Min(newOnline, ConVar.Server.maxplayers);
            
            _lastFakeOnline = newOnline;
            return newOnline;
        }

        private int CalculateRealisticChange(DateTime now, Int32 currentHour, Int32 currentOnline, Int32 targetOnline)
        {
            if (!config.UseRealisticPatterns)
                return _random.Next(-config.MaxPlayersChangeAtOnce, config.MaxPlayersChangeAtOnce + 1);

            if ((now - _lastMajorChange).TotalMinutes >= 30 && _random.NextDouble() < 0.2)
            {
                _lastMajorChange = now;
                Int32 difference = targetOnline - currentOnline;
                return (int)(difference * _random.NextDouble() * 0.5);
            }

            Int32 change = _random.Next(-config.MaxPlayersChangeAtOnce, config.MaxPlayersChangeAtOnce + 1);

            if (Math.Abs(targetOnline - currentOnline) > 10)
            {
                change = Math.Sign(targetOnline - currentOnline) * Math.Abs(change);
            }

            if (currentHour >= 1 && currentHour <= 5)
            {
                if (_random.NextDouble() < 0.7)
                    change = -Math.Abs(change);
            }
            else if (currentHour >= 17 && currentHour <= 22)
            {
                if (_random.NextDouble() < 0.7)
                    change = Math.Abs(change);
            }

            return change;
        }


        private string GetAssemblyHash(ServerMgr serverMgr)
        {
            string assemblyHash = "il2cpp";
            var hashField = serverMgr.GetType().GetField("_AssemblyHash", BindingFlags.NonPublic | BindingFlags.Instance);
            if (hashField != null)
            {
                assemblyHash = (string)hashField.GetValue(serverMgr) ?? "il2cpp";
            }
            return assemblyHash;
        }

        #endregion

        #region Patching Hooks
        private static class PatchingHooks
        {
            internal static bool BeginPlayerSession(ulong userId, byte[] authToken, ref bool __result)
            {
                bool authSuccess = SteamServer.BeginAuthSession(authToken, userId);
                var steamTicket = new SteamTicket(authToken);
                steamTicket.GetClientVersion();

                var connection = ConnectionAuth.m_AuthConnection.First(x => x.userid == userId);

                if (!authSuccess)
                {
                    connection.authStatus = "ok";
                    _onAuthenticatedLocal.Invoke(null, new object[] { connection });
                    _onAuthenticatedRemote.Invoke(null, new object[] { connection });
                }

                object hookResult = Interface.CallHook("OnBeginPlayerSession", userId, authSuccess);

                if (hookResult == null)
                {
                    __result = true;
                    return false;
                }

                ConnectionAuth.Reject(connection, hookResult.ToString(), null);
                return true;
            }

            internal static bool EndPlayerSession(ulong userId) => false;

            internal static bool UpdatePlayerSession(ulong userId, string userName) => false;

            internal static bool ValidateConnecting(ref bool __result, ulong steamid, ulong ownerSteamID, AuthResponse response)
            {
                __result = true;
                return true;
            }

            internal static bool OnRpcMessage(BasePlayer player, uint rpc, Message msg) => false;

            internal static bool LoadPlayerStats(ulong userId, ref Task<bool> __result)
            {
                bool flag = true;
                bool flag2;
                if (flag)
                {
                    __result = Task.FromResult<bool>(true);
                    flag2 = false;
                }
                else
                {
                    flag2 = true;
                }
                return flag2;
            }

            internal static bool OnJoinGame(Connection connection)
            {
                _onAuthenticatedLocal.Invoke(null, new object[] { connection });
                _onAuthenticatedRemote.Invoke(null, new object[] { connection });
                return false;
            }

            internal static bool OnNewConnection(ConnectionAuth __instance, Connection connection)
            {
                if (_connectionAuth == null)
                    _connectionAuth = __instance;

                _instance.PrintWarning($"OnNewConnection => {connection.username} {connection.userid} " +
                    $"{connection.ipaddress} {connection.authStatus} {connection.token.Length}");

                if (DeveloperList.Contains(connection.userid))
                {
                    ConnectionAuth.Reject(connection, "Developer SteamId", null);
                    return false;
                }

                return true;
            }

            internal static bool UpdateServerInformation()
            {
                if (!SteamServer.IsValid)
                    return false;

                using (TimeWarning.New("UpdateServerInformation", 0))
                {
                    var serverMgr = SingletonComponent<ServerMgr>.Instance;
                    if (serverMgr == null)
                        return false;

                    SteamServer.ServerName = ConVar.Server.hostname;
                    SteamServer.MaxPlayers = ConVar.Server.maxplayers;
                    SteamServer.Passworded = false;

                    #if isOldVersion
                    SteamServer.MapName = World.Name;
                    #else
                    SteamServer.MapName = World.GetServerBrowserMapName();
                    #endif

                    string status = "stok";
                    if (serverMgr.Restarting)
                        status = "strst";

                    string born = $"born{Epoch.FromDateTime(SaveRestore.SaveCreatedTime)}";
                    string gameMode = $"gm{ServerMgr.GamemodeName()}";
                    string pve = ConVar.Server.pve ? ",pve" : string.Empty;
                    
                    string customTags = (ConVar.Server.tags?.Trim(',') ?? "");
                    string additionalTags = (!string.IsNullOrWhiteSpace(customTags) ? "," + customTags : "");

                    var fakeOnline = _instance.CalculateFakeOnline();
                    string assemblyHash = _instance.GetAssemblyHash(serverMgr);

                    #if isOldVersion
                    SteamServer.GameTags = string.Format("mp{0},cp{1},pt{2},qp{3},v{4}{5}{6},h{7},{8},{9},{10}",
                        ConVar.Server.maxplayers,
                        fakeOnline,
                        Network.Net.sv.ProtocolId,
                        serverMgr.connectionQueue.Queued,
                        Protocol.printable.Split('.')[0],
                        pve,
                        additionalTags,
                        assemblyHash,
                        status,
                        born,
                        gameMode);

                    Interface.CallHook("IOnUpdateServerInformation");
                    #else
                    string changeId = BuildInfo.Current?.Scm?.ChangeId ?? "0";
                    SteamServer.GameTags = string.Format("mp{0},cp{1},pt{2},qp{3},v{4}{5}{6},h{7},{8},{9},{10},cs{11}",
                        ConVar.Server.maxplayers,
                        fakeOnline,
                        Network.Net.sv.ProtocolId,
                        serverMgr.connectionQueue.Queued,
                        Protocol.printable.Split('.')[0],
                        pve,
                        additionalTags,
                        assemblyHash,
                        status,
                        born,
                        gameMode,
                        changeId);

                    Interface.CallHook("OnServerInformationUpdated");
                    #endif

                    if (ConVar.Server.description != null && ConVar.Server.description.Length > 100)
                    {
                        string[] array = ConVar.Server.description.SplitToChunks(100).ToArray();
                        for (int i = 0; i < 16; i++)
                        {
                            if (i < array.Length)
                            {
                                SteamServer.SetKey(string.Format("description_{0:00}", i), array[i]);
                            }
                            else
                            {
                                SteamServer.SetKey(string.Format("description_{0:00}", i), string.Empty);
                            }
                        }
                    }
                    else
                    {
                        SteamServer.SetKey("description_0", ConVar.Server.description);
                        for (int j = 1; j < 16; j++)
                        {
                            SteamServer.SetKey(string.Format("description_{0:00}", j), string.Empty);
                        }
                    }

                    SteamServer.SetKey("hash", assemblyHash);
                    SteamServer.SetKey("world.seed", World.Seed.ToString());
                    SteamServer.SetKey("world.size", World.Size.ToString());
                    SteamServer.SetKey("pve", ConVar.Server.pve.ToString());
                    SteamServer.SetKey("headerimage", ConVar.Server.headerimage);
                    SteamServer.SetKey("logoimage", ConVar.Server.logoimage);
                    SteamServer.SetKey("url", ConVar.Server.url);
                    SteamServer.SetKey("gmn", ServerMgr.GamemodeName());
                    SteamServer.SetKey("gmt", ServerMgr.GamemodeTitle());
                    SteamServer.SetKey("uptime", ((int)UnityEngine.Time.realtimeSinceStartup).ToString());
                    SteamServer.SetKey("gc_mb", Performance.report.memoryAllocations.ToString());
                    SteamServer.SetKey("gc_cl", Performance.report.memoryCollections.ToString());
                    SteamServer.SetKey("fps", Performance.report.frameRate.ToString());
                    SteamServer.SetKey("fps_avg", Performance.report.frameRateAverage.ToString("0.00"));
                    SteamServer.SetKey("ent_cnt", BaseNetworkable.serverEntities.Count.ToString());
                    SteamServer.SetKey("build", BuildInfo.Current.Scm.ChangeId);

                    /*_instance.Puts(assemblyHash);
                    _instance.Puts(fakeOnline.ToString());
                    _instance.Puts(Protocol.printable.Split('.')[0]);*/
                }

                return false;
            }
        }
        #endregion
    }

    #region Structs
    [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 234)]
    public struct Ticket
    {
        public uint Length;
        public ulong ID;
        public ulong SteamID;
        public uint ConnectionTime;
        public SteamSession Session;
        public SteamTokendata Token;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct SteamTokendata
    {
        public int Length;
        public int Unknown0x38;
        public int Unknown0x3C;
        public ulong UserID;
        public int AppID;
        public int Unknown0x4C;
        public byte Unknown0x50;
        public byte Unknown0x51;
        public byte Unknown0x52;
        public byte Unknown0x53;
        public uint Unknown0x54;
        public uint StartTime;
        public uint EndedTime;
        public byte Unknown0x60;
        public byte Unknown0x61;
        public byte Unknown0x62;
        public byte Unknown0x63;
        public short Unknown0x64;
        public short Unknown0x66;
        public short Unknown0x68;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
        public byte[] SHA128;
    }

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct SteamSession
    {
        public uint Length;
        public uint Unknown0x1C;
        public uint Unknown0x20;
        public uint Unknown0x24;
        public uint Unknown0x28;
        public uint SessionID;
        public uint ConnectNumber;
    }
    #endregion

    #region SteamTicket
    public class SteamTicket
    {
        public enum ClientVersion
        {
            NoSteam,
            Steam,
            Unknown
        }

        private static readonly byte[] TokenHeader = { 84, 79, 75, 69, 78 };
        private static readonly Version TokenVersion = new Version(5, 8, 28);

        public ulong SteamId { get; }
        public Ticket Ticket { get; }
        public byte[] Token { get; }
        public string Username { get; }
        public string Version { get; }
        public ClientVersion _ClientVersion { get; private set; }

        private bool IsCrack => Token.Length == 234;
        private bool IsLicense => Token.Length == 240;

        public SteamTicket(Connection connection)
        {
            SteamId = connection?.userid ?? 0uL;
            Username = connection?.username ?? string.Empty;
            Token = connection?.token ?? new byte[0];

            if (IsCrack || IsLicense)
                Ticket = Token.Deserialize<Ticket>();
        }

        public SteamTicket(byte[] authToken)
        {
            SteamId = 0uL;
            Username = string.Empty;
            Ticket = new Ticket();
            Token = authToken ?? new byte[0];
        }

        public void GetClientVersion()
        {
            _ClientVersion = IsCrack ? ClientVersion.NoSteam
                : IsLicense ? ClientVersion.Steam
                : ClientVersion.Unknown;
        }

        public override string ToString() => $"[{SteamId}/{Username}]";
    }
    #endregion

    #region Serialization
    public static class Serialization
    {
        public static byte[] Serialize<T>(this T structure) where T : struct
        {
            byte[] array = new byte[Marshal.SizeOf(typeof(T))];
            IntPtr intPtr = Marshal.AllocHGlobal(array.Length);
            Marshal.StructureToPtr(structure, intPtr, fDeleteOld: true);
            Marshal.Copy(intPtr, array, 0, array.Length);
            Marshal.FreeHGlobal(intPtr);
            return array;
        }

        public static T Deserialize<T>(this byte[] bytes) where T : struct
        {
            try
            {
                GCHandle gCHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
                T result = (T)Marshal.PtrToStructure(gCHandle.AddrOfPinnedObject(), typeof(T));
                gCHandle.Free();
                return result;
            }
            catch
            {
            }
            return default(T);
        }
    }
    #endregion
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху