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

FREE RewardPlay : 0.0.82 0.0.82

Нет прав для скачивания
C#:
using Oxide.Core;
using Oxide.Core.Plugins;
using UnityEngine;
using System.Collections.Generic;
using Oxide.Core.Libraries;
using Newtonsoft.Json.Linq;
using System;
using Newtonsoft.Json;
using System.Linq;
using System.Reflection;
using Oxide.Game.Rust.Cui;

//НИ В КОЕМ СЛУЧАЕ НЕ ТРОГАТЬ ПЛАГИН!!!

//НЕВЕРНЫЕ ИЗМЕНЕНИЯ МОГУТ ПОВЛЕЧЬ ЗА СОБОЙ БЛОКИРОВКУ АККАУНТА НА САЙТЕ, 
//   А ТАКЖЕ ОШИБОЧНОЕ СПИСАНИЕ СРЕДСТВ

namespace Oxide.Plugins
{
    [Info("RewardPlay", "sudo", "0.0.82")]
    public class RewardPlay : RustPlugin
    {   
        [PluginReference]
        private Plugin MultiFighting, NoSteam, TirifyGamePluginPirate;

        private Dictionary<ulong, Timer> playerAfkTimers = new Dictionary<ulong, Timer>();

        private Dictionary<ulong, PlayerSession> playerSessions = new Dictionary<ulong, PlayerSession>();
        private Dictionary<ulong, PlayerActive> playerActive = new Dictionary<ulong, PlayerActive>();

        private const string ApiCheck = "https://rewardplay.org/api/server/check";
        private const string ApiImport = "https://rewardplay.org/api/server/import";
        private const string ApiPluginInfo = "https://rewardplay.org/api/server/plugin";

        private string versionPlugin;
        private Timer ImportTimer;

        private static string ipAddress;
        private static int? portQuery;
        private static int? portGame;
        private static bool isPirate = false;

        private float price;
        private string status;
        private long LastImportTime = 0;
        private bool afkRecord;

        private void ApiPost(string api, Dictionary<string, object> postData, Action<int, JObject> callback) {
            string jsonData = JsonConvert.SerializeObject(postData, Formatting.None);
            webrequest.Enqueue(api, jsonData, (code, response) =>
            {
                if (code == 200 && response != null) callback(code, JObject.Parse(response));
                else PrintError($"Ошибка API: {code}");
            }, this, RequestMethod.POST, new Dictionary<string, string> {  { "Content-Type", "application/json" }, { "User-Agent", "RewardPlay PLUGIN" }, { "secretKey", config.secretKey } });
        }

        private void ApiGet(string api, Dictionary<string, object> getData, Action<int, JObject> callback)
        {
            if (getData.Count != 0){
                var queryString = string.Join("&", getData.Select(kv => $"{Uri.EscapeDataString(kv.Key)}={Uri.EscapeDataString(kv.Value.ToString())}"));
                api = $"{api}?{queryString}";
            }

            webrequest.Enqueue(api , null, (code, response) =>
            {
                if (code == 200 && response != null) callback(code, JObject.Parse(response));
                else PrintError($"Ошибка API: {code}");
            }, this, RequestMethod.GET, new Dictionary<string, string> { { "Content-Type", "application/json" } });
        }

        private void OnServerInitialized()
        {
            ipAddress = ConVar.Server.ip;
            portQuery = ConVar.Server.queryport;
            portGame = ConVar.Server.port;
            
            if(!portQuery.HasValue) {
                PrintError($"Query port сервера не указан");
                return;
            }
            if(!portGame.HasValue) {
                PrintError($"Game port сервера не указан");
                return;
            }

            if (MultiFighting != null || NoSteam != null || TirifyGamePluginPirate != null) isPirate = true;

            versionPlugin = GetType().GetCustomAttribute<InfoAttribute>().Version.ToString();
            var postData = new Dictionary<string, object> { { "portQuery", portQuery}, { "portGame", portGame }, { "ip", ipAddress }, { "isPirate", isPirate }, { "versionPlugin", versionPlugin} };
            ApiPost(ApiCheck, postData, (code, response) =>
            {
                if (response["success"]?.ToObject<bool>() == true) {
                    price = response["price"].ToObject<float>();
                    status = response["status"].ToString();
                    afkRecord = response["afkRecord"].ToObject<bool>();
                    Puts("Все проверки пройдены, запускаем отправку информацию о игроках...");
                    //ВРЕМЯ ОТПРАВКИ НЕ МЕНЯТЬ!!!
                    ImportTimer = timer.Every(300f, () =>
                    {
                        if (config.logging) Puts("Отправляем инфорацию о игроках");
                        ImportPlayers();
                    });

                    LoadData();

                    cmd.AddChatCommand("reward", this, "OpenUICommand");
                    cmd.AddChatCommand("rewardplay", this, "OpenUICommand");
                    cmd.AddChatCommand("rewardClose", this, "CloseUICommand");

                    foreach(var player in BasePlayer.activePlayerList)
                        OnPlayerConnected(player, true);

                    foreach (var target in playerSessions.Keys.ToList()) {
                        var session = playerSessions[target];

                        bool online = BasePlayer.activePlayerList.Any(p => p.userID == target);
                        
                        if (!online && session.Connect > session.Disconnect) {
                            playerSessions.Remove(target);
                        }
                    }

                    ApiGet(ApiPluginInfo, new Dictionary<string, object> {}, (code, response) =>
                    {
                        if(response["success"]?.ToObject<bool>() == true) {
                            var actualVersion = response["version"].ToString();
                            if (versionPlugin != actualVersion) PrintError($"Актуальная версия плагина (v {actualVersion}), скорее обновитесь!");
                        }
                    });
                }
                else {
                    PrintError($"{response["message"].ToString()}");
                    if (response["recheck"]?.ToObject<bool>() == true) {
                        timer.Once(5, OnServerInitialized);
                    }
                }
            });
        }   

        private void ImportPlayers()
        {
            var players = new Dictionary<ulong, Dictionary<string, long>>{};
            long importTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

            foreach(var entry in playerSessions)
            {
                ulong steamId = entry.Key;
                PlayerSession session = entry.Value;
               
                long connect = session.Connect;
                long disconnect = session.Disconnect;
        
                long earned = 0;
                bool online = disconnect > connect;

                bool giveEarned = false;

                players[steamId] = new Dictionary<string, long>  { { "connect", connect }, { "disconnect", disconnect } };
                
                if (playerActive.TryGetValue(entry.Key, out PlayerActive active) && afkRecord)
                {
                    long lastActive = active.LastActiveTime;
                    long activeAfterAFK = active.ActiveAfterAFK;

                    players[steamId].Add("lastActive", lastActive);
                    players[steamId].Add("activeAfterAFK", activeAfterAFK);

                    if (active.openedMenu && lastActive + 590 <= importTime && !online) {
                        BasePlayer player = BasePlayer.FindByID(steamId);
                        if (player != null && player.IsConnected) StartAfkPlayerTell(player);
                    }
                    else giveEarned = true;
                }
                if (giveEarned) {
                    if (status != "active") {
                        continue;
                    }
                    else if (online) {
                        session.Earned = 0f;
                    }
                    else if (session.Earned == 0f) {
                        earned = importTime - connect;
                    }
                    else if (session.Earned > 0f) {
                        earned = importTime - LastImportTime;
                    }

                    session.Earned += earned * (price / 3600);
                }
                
            }
            LastImportTime = importTime;

            var postData = new Dictionary<string, object> { { "players", players }, { "secretKey", config.secretKey }, { "sendTime", importTime } };

            ApiPost(ApiImport, postData, (code, response) =>
            {
                if (response["success"]?.ToObject<bool>() == true) 
                {
                    if (config.logging) Puts("Инфорация отправлена");
                    price = response["price"].ToObject<float>(); 
                    status = response["status"].ToString();
                    afkRecord = response["afkRecord"].ToObject<bool>();
                    if (!afkRecord && playerAfkTimers.Count > 0) StopAllAfkPlayerTell();
                    if (status == "inactive") {
                        foreach (var entry in playerActive)
                        {
                            BasePlayer player = BasePlayer.FindByID(entry.Key);
                            if (player != null && player.IsConnected && !entry.Value.alerted && entry.Value.openedMenu)
                            {
                                entry.Value.alerted = true;
                                OpenUI(player);
                            }
                        }
                    } else if (status == "active") playerActive.Values.ToList().ForEach(p => p.alerted = false);

                }
                else PrintError($"{response["message"].ToString()}");
            });
        }

        private void OnPlayerConnected(BasePlayer player, bool pluginLoaded = false)
        {
            ulong steamId = player.userID;
            long playerConnectLax = GetTimeStampConnected(player);
            long playerConnect = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            
            if (!playerSessions.TryGetValue(steamId, out PlayerSession playerSession))
            {
                playerSession = new PlayerSession 
                { 
                    Connect = pluginLoaded ? playerConnectLax : playerConnect,
                    Disconnect = 0
                };
                playerSessions.Add(steamId, playerSession);
            }
            else
            {
                if (pluginLoaded)
                {
                    if (playerConnectLax - 300 >= playerSession.Connect)
                        return;
                    if (playerSession.Connect < playerConnectLax)
                        playerSession.Connect = playerConnectLax;
                    if (playerSession.Disconnect > playerConnectLax)
                        playerSession.Disconnect = 0;
                }
                else
                {
                    playerSession.Connect = playerConnect;
                }
            }
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            ulong steamId = player.userID;
            long playerConnectLax = GetTimeStampConnected(player);
            long playerDisconnect = DateTimeOffset.UtcNow.ToUnixTimeSeconds();

            if (!playerSessions.TryGetValue(steamId, out PlayerSession playerSession))
            {
                playerSession = new PlayerSession
                {
                    Connect = playerConnectLax,
                    Disconnect = playerDisconnect,
                    Earned = 0.0f
                };
                playerSessions.Add(steamId, playerSession);
            }
            else
            {
                playerSession.Disconnect = playerDisconnect;
                playerSession.Earned = 0.0f;
            }

            StopAfkPlayerTell(player);
        }
        private void OnPlayerInput(BasePlayer player, InputState input)
        {
            if (!afkRecord) return;
            if (player == null && !player.IsConnected) return;
            
            Vector3 currentPosition = player.transform.position;
            if (!playerActive.TryGetValue(player.userID, out PlayerActive active))
            {
                active = new PlayerActive
                {
                    LastActiveTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                    LastPosition = currentPosition
                };
                playerActive.Add(player.userID, active);
            }
            else if (Vector3.Distance(currentPosition, active.LastPosition) > 3) 
            {
                var currentTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                //НЕ ТРОГАТЬ - ОТ ЭТОГО НЕ ЗАВИСИТ ВРЕМЯ ЧЕРЕЗ СКОЛЬКО БУДЕТ ИГРОК В АФК!!!
                if (currentTime - active.LastActiveTime > 600) {
                    active.ActiveAfterAFK = currentTime;
                    StopAfkPlayerTell(player);
                }

                active.LastActiveTime = currentTime;
                active.LastPosition = currentPosition;
            }
        }

        object OnPlayerRespawn(BasePlayer player, BasePlayer.SpawnPoint spawnPoint)
        {
            Vector3 currentPosition = spawnPoint.pos;
            if (!playerActive.TryGetValue(player.userID, out PlayerActive active)) {
                active = new PlayerActive
                {
                    LastActiveTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                    LastPosition = currentPosition
                };
                playerActive.Add(player.userID, active);
            }

            active.LastPosition = currentPosition;

            return null;
        }

        private void OpenUICommand(BasePlayer player)
        {
            OpenUI(player);
        }

        private void CloseUICommand(BasePlayer player)
        {
            CuiHelper.DestroyUi(player, UI_MAIN);
        }

        string UI_MAIN = "MAIN_PANEL";

        private void OpenUI(BasePlayer player/*, bool afk = false*/) 
        {
            CuiHelper.DestroyUi(player, UI_MAIN);
            var url = (status == "inactive"/* || afk*/) ? "https://rewardplay.org/assets/images/plugin/empty.png" : "https://rewardplay.org/assets/images/plugin/default.png";
            PlayerSession playerSession = playerSessions[player.userID];
            playerActive[player.userID].openedMenu = true;

            var element = new CuiElementContainer();

            element.Add(new CuiPanel
            {
                RectTransform = { AnchorMin = "0.343 0.115", 
                                  AnchorMax = "0.64 0.284" },
                Image = { Color = "1 1 1 0" },
                //CursorEnabled = true
            }, "Overlay", UI_MAIN);

            element.Add(new CuiElement
            {
                Parent = UI_MAIN,
                Components =
                {
                    new CuiRawImageComponent
                    {
                        Url = url,
                    },

                    new CuiRectTransformComponent
                    {
                        AnchorMin = "0 0", 
                        AnchorMax = "1 1",
                    }
                }
            });
            
            element.Add(new CuiButton
            {
                Button =
                {
                    Command = "chat.say /rewardClose",
                    Color = "1 1 1 0",
                },
                RectTransform =
                {
                    AnchorMin = "0.94 0.8",
                    AnchorMax = "0.988 0.97",
                }
            }, UI_MAIN);

            // if (afk) {
            //     textUI(element, "Вы были неактивны более 10 минут. Начисление на баланс возобновится, как только вы продолжите играть.");
            // }
            if (status == "inactive") {
                textUI(element, "У администратора сервера закончились средства. Попросите его пополнить баланс или выберите другой сервер на нашем сайте.");
            }
            else {
                ActiveUI(element, playerSession);
            }


            CuiHelper.AddUi(player, element);

        }

        private void textUI(CuiElementContainer element, string text) {
            element.Add(new CuiElement
                {
                    Parent = UI_MAIN,
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Text = text,
                            FontSize = 12,
                            Font = "robotocondensed-regular.ttf",
                            Color = "0.902 0.902 0.902 1",
                            Align = TextAnchor.UpperLeft,
                        },

                        new CuiRectTransformComponent
                        {
                            OffsetMin  = "105 -10",
                            OffsetMax = "-30 -50", 
                        },
                    }
                });

                element.Add(new CuiElement
                {
                    Parent = UI_MAIN,
                    Components =
                    {
                        new CuiTextComponent
                        {
                            Text = $"Оплата приостановлена!",
                            FontSize = 12,
                            Font = "robotocondensed-regular.ttf",
                            Color = "0.541 0.537 0.537 1",
                            Align = TextAnchor.MiddleLeft,
                        },

                        new CuiRectTransformComponent
                        {
                           OffsetMin  = "135 95",
                            OffsetMax = "-30 -10", 
                        },
                    }
                });
        }

        private void ActiveUI(CuiElementContainer element, PlayerSession playerSession) {
            element.Add(new CuiElement
            {
                Parent = UI_MAIN,
                Components =
                {
                    new CuiTextComponent
                    {
                        Text = $"Оплата за час: <color='white'><size='11'>{price}₽</size></color>",
                        FontSize = 12,
                        Font = "robotocondensed-regular.ttf",
                        Color = "0.439 0.439 0.439 1",
                        Align = TextAnchor.MiddleLeft,
                    },

                    new CuiRectTransformComponent
                    {
                        OffsetMin  = "130 60",
                        OffsetMax = "50 -40",
                    },
                }
            });

            element.Add(new CuiElement
            {
                Parent = UI_MAIN,
                Components =
                {
                    new CuiTextComponent
                    {
                        Text = $"Время игры: <color='white'><size='11'>{ConvertSecondsToTimeFormat((int)(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - playerSession.Connect))}</size></color>",
                        FontSize = 12,
                        Font = "robotocondensed-regular.ttf",
                        Color = "0.439 0.439 0.439 1",
                        Align = TextAnchor.MiddleLeft,
                    },

                    new CuiRectTransformComponent
                    {
                        OffsetMin  = "130 42",
                        OffsetMax = "50 -60",
                    },
                }
            });

            element.Add(new CuiElement
            {
                Parent = UI_MAIN,
                Components =
                {
                    new CuiTextComponent
                    {
                        Text = $"Заработано за сеанс: <color='white'><size='11'>~ {(float)Math.Round(playerSession.Earned, 2)}₽</size></color>",
                        FontSize = 12,
                        Font = "robotocondensed-regular.ttf",
                        Color = "0.439 0.439 0.439 1",
                        Align = TextAnchor.MiddleLeft,
                    },

                    new CuiRectTransformComponent
                    {
                        OffsetMin  = "130 23",
                        OffsetMax = "50 -83",
                    },
                }
            });
            
            element.Add(new CuiElement
            {
                Parent = UI_MAIN,
                Components =
                {
                    new CuiTextComponent
                    {
                        Text = $"*Информация обновляется каждые 5 минут",
                        FontSize = 8,
                        Font = "robotocondensed-regular.ttf",
                        Color = "0.357 0.357 0.357 1",
                        Align = TextAnchor.MiddleLeft,
                    },

                    new CuiRectTransformComponent
                    {
                        OffsetMin  = "90 3",
                        OffsetMax = "50 -105",
                    },
                }
            });
        }

        private ConfigData config;
        public class ConfigData
        {
            public string secretKey { get; set; } = "";
            public bool logging { get; set; } = true;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<ConfigData>();
                if (config == null)
                {
                    LoadDefaultConfig();
                }
            }
            catch
            {
                PrintError("Ошибка загрузки конфигурации! Создаём новую.");
                LoadDefaultConfig();
            }
        }

        protected override void LoadDefaultConfig()
        {
            config = new ConfigData();
            SaveConfig();
        }

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


        private void LoadData()
        {
            playerSessions = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, PlayerSession>>("RewardPlay/playerSessions") ?? new Dictionary<ulong, PlayerSession>();
            playerActive = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, PlayerActive>>("RewardPlay/playerActive") ?? new Dictionary<ulong, PlayerActive>();
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("RewardPlay/playerSessions", playerSessions);
            Interface.Oxide.DataFileSystem.WriteObject("RewardPlay/playerActive", playerActive);
        }

        private class PlayerSession
        {
            public long Connect { get; set; } = 0;
            public long Disconnect { get; set; } = 0;
            public float Earned { get; set; } = 0.0f;
        }

        private class PlayerActive
        {
            public long LastActiveTime;
            public long ActiveAfterAFK;
            public Vector3 LastPosition;
            public bool openedMenu;
            public bool alerted;
        }

        private void Unload()
        {
            foreach (var player in BasePlayer.activePlayerList) {
                CuiHelper.DestroyUi(player, UI_MAIN);
                OnPlayerDisconnected(player, "unloaded");
            }

            //ImportPlayers();
            SaveData();
        }

        private void OnNewSave(string filename)
        {
            if (config.logging) Puts("Новый save обнаружен!\nОтправляем инфорацию и чистим дату");
            ImportPlayers();

            playerSessions.Clear();
            playerActive.Clear();
            SaveData();
        }

        public string ConvertSecondsToTimeFormat(int seconds)
        {
            int hours = seconds / 3600;
            int minutes = (seconds % 3600) / 60;

            return $"{hours}ч {minutes}м";
        }

        public long GetTimeStampConnected(BasePlayer player)
        {
            long serverStartTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds() - (long)UnityEngine.Time.realtimeSinceStartup;
            long loginTimestamp = serverStartTime + (long)player.net.connection.connectionTime;
            
            return loginTimestamp;
        }

        public void StartAfkPlayerTell(BasePlayer player)
        {
            if (playerAfkTimers.ContainsKey(player.userID))
            {   
                playerAfkTimers[player.userID].Destroy();
                playerAfkTimers.Remove(player.userID);
            }

            string text = "<color=#fcd535>[RewardPlay]</color>\nВы были неактивны более 10 минут. Начисление на баланс возобновится, как только вы продолжите играть!";

            sendMessage(player, text);

            playerAfkTimers[player.userID] = timer.Every(120f, () => {
                sendMessage(player, text);
            });
        }

        public void StopAfkPlayerTell(BasePlayer player)
        {
            if (playerAfkTimers.ContainsKey(player.userID))
            {
                playerAfkTimers[player.userID].Destroy();
                playerAfkTimers.Remove(player.userID);
                sendMessage(player, "<color=#fcd535>[RewardPlay]</color>\nВы вышли из АФК!");
            }
        }

        public void StopAllAfkPlayerTell()
        {
            foreach (var timer in playerAfkTimers.Values) timer.Destroy();
            playerAfkTimers.Clear();
        }

        public void sendMessage(BasePlayer player, string message) {
            Player.Message(player, message, 76561199557013128);
        }
    }
}

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