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

FREE IQEconomic : 2.10.13 2.10.13

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using ConVar;
using Pool = Facepunch.Pool;
using Object = System.Object;
using System;
using System.Collections;
using UnityEngine.Networking;
using Oxide.Game.Rust.Cui;
using Newtonsoft.Json;
using Oxide.Core.Database;
using System.Linq;
using Oxide.Core;
using System.Text;
using Oxide.Core.Plugins;
using System.Collections.Generic;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("IQEconomic", "Mercury", "2.10.13")]
    [Description("Экономика на ваш сервер")]
    public class IQEconomic : RustPlugin {
        private Boolean isUsedSQL = false;
        private const String arrowLogRemoved = "=======>";
        private void OnPlayerSleep(BasePlayer player) {
            if (_interface == null) return;
            InterfaceBuilder.DestroyPlayerUI(player);
        }
        private void DisconnectedPlayer(BasePlayer player) {
            if (isUsedSQL) {
                PlayerInfo pInfo = PlayerInfo.Get(player.UserIDString);
                if (pInfo == null) return;
                ImportPlayerSQL(player.UserIDString, pInfo.Balance, pInfo.LimitBalance, pInfo.Time, pInfo.DateTime, pInfo.IsHide);
                return;
            }
            PlayerInfo.Save(player.UserIDString);
            PlayerInfo.Remove(player.UserIDString);
        }
        private void OnPlayerRespawned(BasePlayer player) {
            if (!saveAfterDeath.TryGetValue(player, out Int32 balance)) return;
            if (balance == 0) return;
            AddBalance(player, balance, TypeLog.ReturnedSaveAfterDeath);
        }
        private List<Item> GetPhysicsItems(BasePlayer player) {
            Configuration.GeneralSetting.PhysicsItem physicConfig = config.generalSetting.physicsItem;
            List<Item> acceptedItems = Pool.Get<List<Item>>();
            List<Item> playerInventory = GetAllItems(player);
            foreach (Item item in playerInventory) {
                if (physicConfig.IsPhysicMoney(item)) acceptedItems.Add(item);
            }
            Pool.FreeUnmanaged(ref playerInventory);
            return acceptedItems;
        }
        public String FormatTime(TimeSpan time, string userId) {
            if (time.Days > 0) return Format(time.Days, GetLang("EXCHANGER_COURSE_TITLE_FORMAT_TIME_DAYS", userId));
            if (time.Hours > 0) return Format(time.Hours, GetLang("EXCHANGER_COURSE_TITLE_FORMAT_TIME_HOURSE", userId));
            if (time.Minutes > 0) return Format(time.Minutes, GetLang("EXCHANGER_COURSE_TITLE_FORMAT_TIME_MINUTES", userId));
            return time.Seconds > 0 ? Format(time.Seconds, GetLang("EXCHANGER_COURSE_TITLE_FORMAT_TIME_SECONDS", userId)) : String.Empty;
        }
        private (BasePlayer, String) FindPlayerNameOrID(BasePlayer finder, String nameOrID) {
            List<BasePlayer> players = Pool.Get<List<BasePlayer>>();
            players.AddRange(BasePlayer.activePlayerList);
            if (nameOrID.IsSteamId() && ulong.TryParse(nameOrID, out UInt64 userID)) {
                BasePlayer player = BasePlayer.FindByID(userID);
                Pool.FreeUnmanaged(ref players);
                return (player, null);
            }
            List<BasePlayer> matchingPlayers = Pool.Get<List<BasePlayer>>();
            try {
                matchingPlayers.AddRange(players.Where(player => player.displayName != null && player.displayName.IndexOf(nameOrID, StringComparison.OrdinalIgnoreCase) >= 0));
                switch (matchingPlayers.Count) {
                    case 1 : {
                        BasePlayer foundPlayer = matchingPlayers[0];
                        return (foundPlayer, null);
                    }
                    case > 1 : {
                        String nicknameList = String.Join(", ", matchingPlayers.Take(3).Select(p => p.displayName));
                        return (null, GetLang("CHAT_ALERT_TRANSFER_MATCHES_PLAYERS", finder.UserIDString, nameOrID, nicknameList));
                    }
                    default : return (null, null);
                }
            }
            finally {
                Pool.FreeUnmanaged(ref players);
                Pool.FreeUnmanaged(ref matchingPlayers);
            }
        }
        private void OnPlayerDeath(BasePlayer target, HitInfo hitInfo) {
            if(!target) return;
            Boolean isRealPlayerTarget = IsRealPlayer(target);
            Configuration.EarningCoins.PresetEarning earningPlayer = config.earningCoins.killedPlayer;
            Configuration.EarningCoins.PresetEarning earningNpc = config.earningCoins.killedNpcs;
            if (isRealPlayerTarget) {
                if (isUsedUI) InterfaceBuilder.DestroyPlayerUI(target);
                if (config.generalSetting.physicsItem.useSaveDeath && config.generalSetting.typeCoins == TypeCoins.Physics) {
                    Int32 balance = GetBalancePlayer(target);
                    RemoveBalance(target, balance, TypeLog.SaveAfterDeath);
                    saveAfterDeath[target] = balance;
                }
            }
            if (!earningPlayer.useEarning && !earningNpc.useEarning) return;
            if (hitInfo == null) return;
            BasePlayer attacker = hitInfo.InitiatorPlayer;
            if (!attacker) return;
            if (!IsRealPlayer(attacker)) return;
            if (attacker == target) return;
            if (isRealPlayerTarget) {
                if (IsBlockedEarningKillPlayer(attacker, target)) return;
                if (!IsOnlyTakeEarning(attacker, earningPlayer)) return;
                AddBalance(attacker, earningPlayer.countMoney, TypeLog.Action, earningPlayer.useChatAlert ? "CHAT_ALERT_EARNING_KILLED_PLAYER" : default);
                return;
            }
            if (!IsOnlyTakeEarning(attacker, earningNpc)) return;
            AddBalance(attacker, earningNpc.countMoney, TypeLog.Action, earningNpc.useChatAlert ? "CHAT_ALERT_EARNING_KILLED_NPC" : default);
        }
        private void ImportPlayerSQL(String userID, Int32 balance, Int32 limitBalance, Int32 time, Double dateTime, Boolean isHide, Boolean isMigrate = false) {
            if (sqlConnection == null) return;
            Configuration.GeneralSetting.MySQLConnection sqlInfo = config.generalSetting.mySQLConnectionSettings;
            String hideString = isHide.ToString();
            String sqlQuery = $"UPDATE {sqlInfo.dbTableName} SET `steamid` = @0, `balance` = @1,`limit_balance` = @2,`time` = @3,`last_connection` = @4, `is_hide` = @5 WHERE `steamid` = @0";
            Sql updateCommand = Sql.Builder.Append(sqlQuery, userID, balance, limitBalance, time, dateTime, hideString);
            sqlLibrary.Update(updateCommand, sqlConnection, rowsAffected => {
                if (rowsAffected > 0) return;
                String Query = String.Format(SQL_Query_InsertUser(), userID, balance, limitBalance, time, dateTime, hideString);
                Sql sql = Sql.Builder.Append(Query);
                sqlLibrary.Insert(sql, sqlConnection, rowsAffecteds => {
                    if (!isMigrate) Puts(LanguageEn? $"" : $"Данные игрока {userID} были внесены в базу-данных");
                }
                );
            }
            );
        }
        private String SQL_Query_CreatedDatabase() {
            String CreatedDB = $"CREATE TABLE IF NOT EXISTS `{config.generalSetting.mySQLConnectionSettings.dbTableName}`(" + "`id` INT(11) NOT NULL AUTO_INCREMENT," + "`steamid` VARCHAR(255) NOT NULL," + "`balance` VARCHAR(255) NOT NULL," + "`limit_balance` VARCHAR(255) NOT NULL," + "`time` VARCHAR(255) NOT NULL," + "`last_connection` VARCHAR(255) NOT NULL," + "`is_hide` VARCHAR(6) NOT NULL," + " PRIMARY KEY(`id`))";
            return CreatedDB;
        }
        private void TransferToPlayer(BasePlayer player, BasePlayer targetPlayer, Int32 amount) {
            if (!IsValidTransfer(player, targetPlayer, amount)) return;
            ExecuteTransfer(player, targetPlayer, amount);
        }
        private List<String> GetOrSetCacheUI(String keyCache, String interfaceJson = null) {
            if (cachedUI.TryGetValue(keyCache, out List<String> ui)) return ui;
            if (interfaceJson == null) return null;
            List<String> newUI = new() {
                interfaceJson
            }
            ;
            cachedUI[keyCache] = newUI;
            return newUI;
        }
        private void ConsoleCommandBalance(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            ChatCommandBalance(player);
        }
        private void OnEntityDeath(LootContainer entity, HitInfo info) {
            if (!entity.PrefabName.Contains("barrel") || entity.PrefabName.Contains("hobobarrel")) return;
            Configuration.EarningCoins.PresetEarning earning = config.earningCoins.killedBarrels;
            if (!earning.useEarning) return;
            if (!entity || info == null) return;
            BasePlayer player = info.InitiatorPlayer;
            if(!IsTakeEarning(player, earning)) return;
            AddBalance(player, earning.countMoney, TypeLog.Action, earning.useChatAlert ? "CHAT_ALERT_EARNING_DESTROY_BARREL" : default);
        }
        private void RemoveBalance(String userID, Int32 amount, TypeLog typeLog) {
            if (config.generalSetting.typeCoins == TypeCoins.Physics) {
                PrintWarning(LanguageEn ? "" : $"Нельзя забрать валюту у игрока {userID} пока он оффлайн");
                return;
            }
            if (isUsedSQL) GetAndFunctionalBalancePlayerSQL(userID, false, amount);
            else {
                PlayerInfo pInfo = PlayerInfo.GetOffline(userID);
                if (pInfo == null) return;
                if (!DoesHaveEnoughBalance(pInfo.Balance)) {
                    pInfo.Balance = 0;
                    LogAction(userID, pInfo.Balance, typeLog, false);
                }
                else {
                    pInfo.Balance -= amount;
                    LogAction(userID, amount, typeLog, false);
                }
                PlayerInfo.SaveOffline(userID, pInfo);
                Interface.Oxide.CallHook("OnRemovedBalance", UInt64.Parse(userID), amount, null, pInfo.Balance);
            }
        }
        private static Boolean IsUnblockExchangerCourse(Int32 timeExchange) => ((SaveRestore.SaveCreatedTime.ToUniversalTime().Subtract(epoch).TotalSeconds + timeExchange) - CurrentTime) <= 0;
        void API_TRANSFERS(BasePlayer player, BasePlayer transferUserID, Int32 balance) => TransferToPlayer(player, transferUserID, balance);
        private String Format(Int32 units, String form) {
            Int32 lastDigit = units % 10;
            Int32 lastTwoDigits = units % 100;
            if (lastTwoDigits is >= 11 and <= 19) return $"{units}{form}";
            return lastDigit switch {
                1 => $"{units}{form}", 2 or 3 or 4 => $"{units}{form}", _ => $"{units}{form}"
            }
            ;
        }
        private Int32 GetLimiteExchanged(PlayerInfo pInfo) {
            Int32 limitExchange = config.exchangerSetting.limitStoreMoney;
            if (limitExchange <= 0) return -1;
            Int32 leftLimite = limitExchange - pInfo.LimitBalance;
            return leftLimite <= 0 ? 0 : leftLimite;
        }
        private void AddBalance(BasePlayer player, PlayerInfo pInfo, Int32 amount, TypeLog typeLog, String alertMessage = default) {
            if (!player || amount <= 0) return;
            if (config.generalSetting.typeCoins == TypeCoins.Physics) {
                Item physicMoney = config.generalSetting.physicsItem.CreatePhysicMoney(amount);
                if (physicMoney == null) return;
                if (!TryMoveItem(player, physicMoney)) {
                    physicMoney.Remove();
                    return;
                }
                if (!String.IsNullOrWhiteSpace(alertMessage)) SendChat(GetLang("CHAT_ALERT_EARNING_TITLE", player.UserIDString, amount, GetLang(alertMessage, player.UserIDString)), player);
                Int32 balancePlayer = GetBalancePlayer(player);
                UpdateExchangedUI(player, balancePlayer, GetLimiteExchanged(pInfo));
                LogAction(player, amount, typeLog, true);
                Interface.Oxide.CallHook("OnAddedBalance", player.userID.Get(), amount, player, balancePlayer);
                return;
            }
            pInfo.Balance += amount;
            if (!String.IsNullOrWhiteSpace(alertMessage)) SendChat(GetLang("CHAT_ALERT_EARNING_TITLE", player.UserIDString, amount, GetLang(alertMessage, player.UserIDString)), player);
            LogAction(player, amount, typeLog, true);
            DrawUI_UpdateTitleBalance(player, pInfo);
            UpdateExchangedUI(player, pInfo.Balance, GetLimiteExchanged(pInfo));
            Interface.Oxide.CallHook("OnAddedBalance", player.userID.Get(), amount, player, pInfo.Balance);
        }
        private void MoscovOVHBalanceSet(BasePlayer player, (Int32 exchangeCoins, Int32 storeMoney) exchangeDetail, UInt64 userID = 0) {
            if (!config.exchangerSetting.storeSetting.useMoscovOvh) return;
            if (!RustStore) {
                PrintWarning(LanguageEn ? "" : "У вас не установлен магазин MoscovOVH");
                return;
            }
            if (exchangeDetail.storeMoney <= 0) return;
            Boolean isSetOffline = !player || exchangeDetail.exchangeCoins <= 0;
            userID = !isSetOffline ? player.userID : userID;
            RustStore.CallHook("APIChangeUserBalance", userID, exchangeDetail.storeMoney, new Action<String>((result) => {
                PlayerInfo pInfo = PlayerInfo.Get(userID.ToString());
                if (result == "SUCCESS") {
                    if (isSetOffline) return;
                    RemoveBalance(player, exchangeDetail.exchangeCoins, TypeLog.Exchanger);
                    SendChat(GetLang("CHAT_ALERT_EXCHANGED_SUCCES", player.UserIDString), player);
                    if (config.exchangerSetting.limitStoreMoney <= 0) return;
                    if (pInfo != null) pInfo.LimitBalance += exchangeDetail.storeMoney;
                    return;
                }
                if (isSetOffline) return;
                SendChat(GetLang("CHAT_ALERT_EXCHANGED_FAIL", player.UserIDString), player);
            }
            ));
        }
        private List<Item> GetAllItems(BasePlayer player) {
            List<Item> itemList = Pool.Get<List<Item>>();
            player.inventory.GetAllItems(itemList);
            player.inventory.AddBackpackContentsToList(itemList);
            return itemList;
        }
        private enum TypeCoins {
            Virtual, Physics
        }
        void API_REMOVE_BALANCE(BasePlayer player, Int32 balance) => RemoveBalance(player, balance, TypeLog.API);
        private void DrawUI_UpdateTitleBalance(BasePlayer player, PlayerInfo pInfo) {
            if (!isUsedUI) return;
            if (player.IsSleeping()) return;
            if (_interface == null) return;
            if (pInfo == null) return;
            if (pInfo.IsHide) return;
            String Interface = InterfaceBuilder.GetInterface("UI_Balance_Title_Update");
            if (Interface == null) return;
            Int32 balance = GetBalancePlayer(pInfo);
            String balanceLang = balance >= 99999999 ? GetLang("BALANCE_TITLE_SHORT", player.UserIDString, balance) : GetLang("BALANCE_TITLE", player.UserIDString, balance);
            Interface = Interface.Replace("%BALANCE_TITLE%", balanceLang);
            AddUI(player, Interface);
        }
        private void OnPlayerConnected(BasePlayer player) => ConnectedPlayer(player);
        private Timer timerTrackerTimes;
        private Boolean isUsedStores = false;
        private void GetPlayerSQL(String userID, BasePlayer player = null) {
            if (sqlConnection == null) return;
            Sql sql = Sql.Builder.Append(SQL_Query_SelectedDatabase(userID));
            sqlLibrary.Query(sql, sqlConnection, list => {
                if (list == null) return;
                if (list.Count <= 0) {
                    PlayerInfo.Import(userID, new PlayerInfo {
                        Balance = 0, LimitBalance = 0, Time = 0, DateTime = CurrentTime, IsHide = false,
                    }
                    );
                    if (player) DrawUI_HudPanel(player);
                    return;
                }
                foreach (Dictionary<String, Object> entry in list) {
                    String steamID = (String)entry["steamid"];
                    if (!steamID.IsSteamId()) return;
                    if (!Int32.TryParse((String)entry["balance"], out Int32 balance)) return;
                    if (!Int32.TryParse((String)entry["limit_balance"], out Int32 limitBalance)) return;
                    if (!Int32.TryParse((String)entry["time"], out Int32 time)) return;
                    if (!Double.TryParse((String)entry["last_connection"], out Double dateTime)) return;
                    if (!Boolean.TryParse((String)entry["is_hide"], out Boolean isHideStatus)) return;
                    PlayerInfo.Import(userID, new PlayerInfo {
                        Balance = balance, LimitBalance = limitBalance, Time = time, DateTime = CurrentTime, IsHide = isHideStatus,
                    }
                    );
                    if (player) DrawUI_HudPanel(player);
                }
            }
            );
        }
        private Int32 GetBalancePlayer(PlayerInfo pInfo) => pInfo?.Balance ?? 0;
        void API_TRANSFERS(UInt64 userID, String transferUserID, Int32 balance) {
            BasePlayer player = BasePlayer.FindByID(userID);
            if (!player) return;
            TransferToPlayer(player, transferUserID, balance);
        }
        private void RemovePhysicMoney(BasePlayer player, Int32 amount) {
            List<Item> physicMoney = GetPhysicsItems(player);
            foreach (Item pItem in physicMoney) {
                if (amount <= 0) break;
                if (pItem.amount >= amount) {
                    pItem.amount -= amount;
                    if (pItem.amount == 0) {
                        pItem.RemoveFromContainer();
                        pItem.Remove();
                    }
                    amount = 0;
                }
                else {
                    amount -= pItem.amount;
                    pItem.RemoveFromContainer();
                    pItem.Remove();
                }
                pItem.MarkDirty();
            }
            Pool.FreeUnmanaged(ref physicMoney);
        }
        private void GetAndFunctionalBalancePlayerSQL(String userID, Boolean addOrRemove, Int32 amount = 0) {
            if (sqlConnection == null) return;
            Sql sql = Sql.Builder.Append(SQL_Query_SelectedDatabase(userID));
            sqlLibrary.Query(sql, sqlConnection, list => {
                if (list == null) return;
                if (list.Count <= 0) {
                    PlayerInfo.Import(userID, new PlayerInfo {
                        Balance = addOrRemove ? amount : 0, LimitBalance = 0, Time = 0, DateTime = CurrentTime, IsHide = false,
                    }
                    );
                    return;
                }
                foreach (Dictionary<String, Object> entry in list) {
                    String steamID = (String)entry["steamid"];
                    if (!steamID.IsSteamId()) return;
                    if (!Int32.TryParse((String)entry["balance"], out Int32 balance)) return;
                    if (!Int32.TryParse((String)entry["limit_balance"], out Int32 limitBalance)) return;
                    if (!Int32.TryParse((String)entry["time"], out Int32 time)) return;
                    if (!Double.TryParse((String)entry["last_connection"], out Double dateTime)) return;
                    if (!Boolean.TryParse((String)entry["is_hide"], out Boolean isHideStatus)) return;
                    PlayerInfo.Import(userID, new PlayerInfo {
                        Balance = addOrRemove ? balance + amount : Math.Max(balance - amount, 0), LimitBalance = limitBalance, Time = time, DateTime = dateTime, IsHide = isHideStatus,
                    }
                    );
                }
                PlayerInfo pInfo = PlayerInfo.Get(userID);
                ImportPlayerSQL(userID, pInfo.Balance, pInfo.LimitBalance, pInfo.Time, pInfo.DateTime, pInfo.IsHide);
                Interface.Oxide.CallHook(addOrRemove ? "OnAddedBalance" : "OnRemovedBalance", UInt64.Parse(userID), amount, null, pInfo.Balance);
            }
            );
        }
        /// <summary>
        /// Plans :
        /// - Исправлена возможная ошибка при Unload с закрытием SQL соединения
        /// - Добавлена возможность полной очистки дата-файла при вайпе сервера, включается отдельно в конфигурации
        /// - Убрана лишняя обработка игроков при загрузке плагина, если используется MySQL
        /// - Добавлены дополнительные проверки в OnPlayerDeath на случай ошибки в конфигурации или в случае возможных конфликтов
        /// - Добавлена возможность запретить использовать команду для обмена валюты пока игрок не находится в безопасной зоне
        /// - Добавлено сообщение о некорректном синтаксисе если включен обмен между игроками, но не включен обмен на магазин
        /// </summary>
        [PluginReference]
        Plugin IQChat, Friends, Clans, Battles, Duel, RustStore, GameStoresRUST, Duelist, ArenaTournament, XFarmRoom;
        private Configuration.ExchangerSetting.CourseController GetActualyCourse() {
            foreach (Configuration.ExchangerSetting.CourseController course in orderedListExchanged) {
                if (IsUnblockExchangerCourse(course.secondsAfterWipe)) return course;
            }
            return null;
        }
        private void UpdateMultiplier(BasePlayer player, Int32 balancePlayer, Int32 limitExchanged, Int32 multiplier) {
            exchangerDataPlayer[player] += multiplier;
            DrawUI_UpdateExchangeOne_Menu(player, balancePlayer, limitExchanged, exchangerDataPlayer[player]);
        }
        private void UpdateExchangerCourse() {
            Configuration.ExchangerSetting.CourseController courseUpdated = GetActualyCourse();
            if (actualyCourse != null && courseUpdated == actualyCourse) return;
            actualyCourse = courseUpdated;
            if (courseData.keyCourse == courseUpdated.secondsAfterWipe) return;
            courseData.keyCourse = actualyCourse.secondsAfterWipe;
            courseData.lastUpdateCourseTime = CurrentTime;
            if (!config.exchangerSetting.useMessageUpdateCourse) return;
            foreach (BasePlayer basePlayer in BasePlayer.activePlayerList) SendChat(GetLang("CHAT_ALERT_COURSE_UPDATE", basePlayer.UserIDString, config.commandExchanger), basePlayer);
        }
        void API_TRANSFERS(UInt64 userID, UInt64 transferUserID, Int32 balance) {
            BasePlayer player = BasePlayer.FindByID(userID);
            if (!player) return;
            TransferToPlayer(player, transferUserID.ToString(), balance);
        }
        void API_TRANSFERS(BasePlayer player, UInt64 transferUserID, Int32 balance) {
            if (!player) return;
            BasePlayer targetPlayer = BasePlayer.FindByID(transferUserID);
            if (!targetPlayer) return;
            TransferToPlayer(player, targetPlayer, balance);
        }
        private Dictionary<String, List<String>> cachedUI = new();
        void API_REMOVE_BALANCE(UInt64 userID, Int32 balance) {
            String idString = userID.ToString();
            API_REMOVE_BALANCE(idString, balance);
        }
        private String SQL_Query_CheckColumn() {
            String checkColumnQuery = $@"SELECT COUNT(*) 
                                        FROM INFORMATION_SCHEMA.COLUMNS 
                                        WHERE table_schema = DATABASE()
                                        AND table_name = '{config.generalSetting.mySQLConnectionSettings.dbTableName}' 
                                        AND column_name = 'is_hide';";
            return checkColumnQuery;
        }
        Int32 API_GET_BALANCE(BasePlayer player) => GetBalancePlayer(player);
        private String SQL_Query_InsertUser() {
            String InserUser = $"INSERT INTO `{config.generalSetting.mySQLConnectionSettings.dbTableName}`" + "(`steamid`, `balance`, `limit_balance`, `time`, `last_connection`, `is_hide`) VALUES ('{0}','{1}','{2}','{3}','{4}','{5}')";
            return InserUser;
        }
        private Dictionary<BasePlayer, Int32> saveAfterDeath = new();
        private static void AddUI(BasePlayer player, String json) {
            if (!player || player.net?.connection == null) return;
            CommunityEntity.ServerInstance.ClientRPC<String>(RpcTarget.Player("AddUI", player.net.connection), json);
        }
        private void ReadData() => courseData = Oxide.Core.Interface.Oxide.DataFileSystem.ReadObject<CourseInfo>("IQSystem/IQEconomic/Exchanger/UpdateCourseTime");
        private static IQEconomic _;
        private void GameStoreBalanceSet(BasePlayer player, (Int32 exchangeCoins, Int32 storeMoney) exchangeDetail, UInt64 userID = 0) {
            if (!config.exchangerSetting.storeSetting.useGameStores) return;
            if (!GameStoresRUST) {
                PrintWarning(LanguageEn ? "" : "У вас не установлен магазин GameStores");
                return;
            }
            if (exchangeDetail.storeMoney <= 0) return;
            Boolean isSetOffline = !player || exchangeDetail.exchangeCoins <= 0;
            userID = !isSetOffline ? player.userID : userID;
            PlayerInfo pInfo = PlayerInfo.Get(userID.ToString());
            if (!isSetOffline) {
                RemoveBalance(player, exchangeDetail.exchangeCoins, TypeLog.Exchanger);
                SendChat(GetLang("CHAT_ALERT_EXCHANGED_SUCCES", player.UserIDString), player);
                if (config.exchangerSetting.limitStoreMoney > 0) {
                    if (pInfo != null) pInfo.LimitBalance += exchangeDetail.storeMoney;
                }
            }
            GameStoresRUST.CallHook("API_ChangePlayerBalance", userID, exchangeDetail.storeMoney, "plus", null, new Action<Boolean, String>((code, result) => {
                LogToFile("DebugGS", $"GameStores DebugFile : isSetOffline : {isSetOffline}, exchangeCoins : {exchangeDetail.exchangeCoins}, code : {code}, result : {result}", this);
                //Cloud temp...// PlayerInfo pInfo = PlayerInfo.Get(userID.ToString());
                //
                if (code) {
                    //     if (isSetOffline) return;
                    //     RemoveBalance(player, exchangeDetail.exchangeCoins, TypeLog.Exchanger);
                    //     SendChat(GetLang("CHAT_ALERT_EXCHANGED_SUCCES", player.UserIDString), player);
                    //
                    //     if (config.exchangerSetting.limitStoreMoney <= 0) return;
                    //     if (pInfo != null)
                    //         pInfo.LimitBalance += exchangeDetail.storeMoney;
                    //
                    return;
                }
                if (isSetOffline) return;
                SendChat(GetLang("CHAT_ALERT_EXCHANGED_FAIL", player.UserIDString), player);
            }
            ));
        }
        private Int32 GetLimiteExchanged(BasePlayer player) {
            Int32 limitExchange = config.exchangerSetting.limitStoreMoney;
            if (limitExchange <= 0) return -1;
            PlayerInfo pInfo = PlayerInfo.Get(player.UserIDString);
            if (pInfo == null) return -1;
            Int32 leftLimite = limitExchange - pInfo.LimitBalance;
            return leftLimite <= 0 ? 0 : leftLimite;
        }
        Boolean API_IS_REMOVED_BALANCE(UInt64 userID, Int32 amount) {
            BasePlayer player = BasePlayer.FindByID(userID);
            return player && DoesHaveEnoughBalance(player, amount);
        }
        private Boolean IsLimiteBalance(PlayerInfo pInfo) {
            Int32 limitExchange = config.exchangerSetting.limitStoreMoney;
            if (limitExchange <= 0) return false;
            if (pInfo == null) return false;
            return pInfo.LimitBalance >= limitExchange;
        }
        private Configuration.ExchangerSetting.CourseController actualyCourse = null;
        private static Double CurrentTime => DateTime.UtcNow.Subtract(epoch).TotalSeconds;
        private const String transferPrivilage = "iqeconomic.transferuse";
        private static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
        Boolean API_MONEY_TYPE() => config.generalSetting.typeCoins == TypeCoins.Virtual;
        private const Boolean LanguageEn = false;
        private Boolean IsBlockedEarningKillPlayer(BasePlayer player, BasePlayer targetPlayer) => IsFriends(player, targetPlayer.userID) || IsDuel(player.userID);
        private String SQL_Query_AddNewColumn() {
            String addColumnQuery = $@"
            ALTER TABLE `{config.generalSetting.mySQLConnectionSettings.dbTableName}`
            ADD COLUMN `is_hide` VARCHAR(6) NOT NULL DEFAULT 'false';";
            return addColumnQuery;
        }
        void API_SET_BALANCE(UInt64 userID, Int32 balance, ItemContainer itemContainer = null) {
            String idString = userID.ToString();
            API_SET_BALANCE(idString, balance, itemContainer);
        }
        private void DrawUI_StaticIconBalance(BasePlayer player) {
            if (_interface == null) return;
            DestroyUI(player, InterfaceBuilder.UI_PANEL_STATIC_BALANCE);
            List<String> cashedStaticPanel = GetOrSetCacheUI("UI_Balance_Panel_Icon_Static");
            if (cashedStaticPanel != null) {
                foreach (String uiCached in cashedStaticPanel) AddUI(player, uiCached);
            }
            else {
                String Interface = InterfaceBuilder.GetInterface("UI_Balance_Panel_Icon_Static");
                if (Interface == null) return;
                List<String> newUI = GetOrSetCacheUI("UI_Balance_Panel_Icon_Static", Interface);
                cashedStaticPanel = newUI;
                foreach (String uiCached in cashedStaticPanel) AddUI(player, uiCached);
            }
        }
        private Boolean DoesHaveEnoughBalance(Int32 balancePlayer, Int32 amount = 0) {
            if (balancePlayer == 0) return false;
            return balancePlayer >= amount;
        }
        void API_SET_BALANCE(String userID, Int32 balance, ItemContainer itemContainer = null) {
            if (!UInt64.TryParse(userID, out UInt64 id)) return;
            BasePlayer player = BasePlayer.FindByID(id);
            if(!player) AddBalance(userID, balance, TypeLog.API);
            else AddBalance(player, balance, TypeLog.API);
        }
        private Object CanUserLogin(String name, String id) {
            if (sqlConnection == null) {
                PrintError(LanguageEn ? "" : "Невозможно сохранить или получить данные игрока! SQL соединение недоступно....");
                return null;
            }
            GetPlayerSQL(id);
            return null;
        }
        private IEnumerator MigrateProcess() {
            foreach (BasePlayer player in BasePlayer.activePlayerList) DisconnectedPlayer(player);
            InterfaceBuilder.DestroyAll();
            String[] playersData = PlayerInfo.GetFiles();
            Int32 countFiles = playersData.Length;
            PrintWarning(LanguageEn ? $"[MIGRATION] The process of transferring data from the local storage to MySQL -> {countFiles} records has started, it may take some time, do not turn off the server and do not restart the plugin, after closing you will see a message.Approximate waiting time : {Math.Round((countFiles * 0.5) / 60)} minutes" : $"[MIGRATION] Запущен процесс переноса данных с локального хранилища в MySQL -> {countFiles} записей, это может занять какое-то время, не выключайте сервер и не перезагружайте плагин, после заверешения вы увидите сообщение.Примерное время ожидания : {Math.Round((countFiles * 0.5) / 60)} минут(ы)");
            yield return CoroutineEx.waitForSeconds(0.25f);
            PrintWarning(LanguageEn ? "[MIGRATION] Trying to connect to MySQL" : "[MIGRATION] Попытка подключения к MySQL");
            SQL_OpenConnection(true);
            yield return CoroutineEx.waitForSeconds(10f);
            if (sqlConnection != null) PrintWarning(LanguageEn ? "[MIGRATION] Successfully connected to MySQL" : "[MIGRATION] Успешно подключились к MySQL");
            else {
                PrintWarning(LanguageEn ? "[MIGRATION] Failed to connect to MySQL" : "[MIGRATION] Не удалось подключиться к MySQL");
                if (coroutineMigrate != null) {
                    ServerMgr.Instance.StopCoroutine(coroutineMigrate);
                    coroutineMigrate = null;
                }
            }
            yield return CoroutineEx.waitForSeconds(1f);
            PrintWarning(LanguageEn ? "[MIGRATION] The process of transferring player data to MySQL has been started" : "[MIGRATION] Запущен процесс переноса данных игроков в MySQL");
            Int32 iterationCount = 0;
            foreach (String playerIDs in playersData) {
                PlayerInfo pInfo = PlayerInfo.GetOffline(playerIDs);
                if(pInfo == null) continue;
                ImportPlayerSQL(playerIDs, pInfo.Balance, pInfo.LimitBalance, pInfo.Time, pInfo.DateTime, pInfo.IsHide, true);
                iterationCount++;
                if (iterationCount % 100 == 0 || iterationCount == countFiles) {
                    Int32 remaining = countFiles - iterationCount;
                    PrintWarning(LanguageEn ? $"[MIGRATION] The transfer is in progress...There are {remaining} players left" : $"[MIGRATION] Перенос в процессе...Осталось {remaining} игроков");
                }
                yield return CoroutineEx.waitForSeconds(0.25f);
            }
            yield return CoroutineEx.waitForSeconds(10f);
            PrintWarning(LanguageEn ? "[MIGRATION] The transfer is complete! The plugin has been unloaded, now you can delete all the data files" : "[MIGRATION] Перенос завершен! Плагин выгружен, теперь вы можете удалить все дата-файлы");
            config.generalSetting.mySQLConnectionSettings.useMySQL = true;
            SaveConfig();
            NextTick(() => Interface.Oxide.UnloadPlugin(Name));
        }
        private class PlayerInfo : DataManager<PlayerInfo> {
            public static void Import(String id, PlayerInfo data) => ImportPlayer(id, data);
            public static void Save(String id) => SavePlayer(id);
            public static void SaveOffline(String id, PlayerInfo data) => SaveOfflinePlayer(id, data);
            public static void Remove(String id) => RemovePlayer(id);
            public static void Delete(String id) => DeletePlayer(id);
            public static PlayerInfo Load(String id) => LoadPlayer(id);
            public static PlayerInfo Get(String id) => GetPlayer(id);
            public static PlayerInfo GetOffline(String id) => GetOfflinePlayer(id);
            public static String[] GetFiles() => GetFilesPlayers();
            [JsonProperty(LanguageEn ? "Player Balance" : "Баланс игрока")]
            public Int32 Balance;
            [JsonProperty(LanguageEn ? "Player's balance withdrawal limit" : "Лимит вывода баланса игрока")]
            public Int32 LimitBalance;
            [JsonProperty(LanguageEn ? "Time counter" : "Счетчик времени")]
            public Int32 Time;
            [JsonProperty(LanguageEn ? "The player's last login to the server" : "Последний вход игрока на сервер")]
            public Double DateTime;
            [JsonProperty(LanguageEn ? "Is the player's balance menu hidden" : "Скрыта ли меню баланса у игрока")]
            public Boolean IsHide;
        }
        private void OnLootSpawn(LootContainer container) {
            if (!container) return;
            String shortPrefabName = container.ShortPrefabName;
            Item droppedItem = config.generalSetting.physicsItem.GetDroppedItem(shortPrefabName);
            if (droppedItem == null) return;
            container.Invoke(() => {
                if (container.inventory == null) return;
                if(!droppedItem.MoveToContainer(container.inventory)) droppedItem.Remove();
            }
            , 0.25f);
        }
        private void ExecuteTransfer(BasePlayer player, BasePlayer targetPlayer, Int32 amount) {
            RemoveBalance(player, amount, TypeLog.Transfer);
            SendChat(GetLang("CHAT_ALERT_TRANSFERED_SUCCES", player.UserIDString, amount, targetPlayer.displayName), player);
            AddBalance(targetPlayer, amount, TypeLog.Transfer);
            SendChat(GetLang("CHAT_ALERT_TRANSFERED_SUCCES", targetPlayer.UserIDString, amount, player.displayName), targetPlayer);
        }
        private void OnEntityDeath(BradleyAPC entity, HitInfo info) {
            Configuration.EarningCoins.PresetEarning earning = config.earningCoins.killedBradley;
            if (!earning.useEarning) return;
            if (!entity || info == null) return;
            BasePlayer player = info.InitiatorPlayer;
            if(!IsTakeEarning(player, earning)) return;
            AddBalance(player, earning.countMoney, TypeLog.Action, earning.useChatAlert ? "CHAT_ALERT_EARNING_DESTROY_BRADLEY" : default);
        }
        private const String arrowLogReceived = "=====>";
        private void DrawUI_HudPanel(BasePlayer player) {
            if (!isUsedUI) return;
            if (player.IsSleeping()) return;
            PlayerInfo pInfo = PlayerInfo.Get(player.UserIDString);
            if (pInfo == null) return;
            Configuration.GeneralSetting.InterfaceSetting.PresetUI presetUI = config.generalSetting.interfaceSetting.presetUI;
            if (pInfo.IsHide) DrawUI_StaticIconBalance(player);
            else DrawUI_StaticPanelBalance(player);
            if (presetUI.useTransferButton && config.exchangerSetting.useExchanger) DrawUI_StaticExchangerPanel(player);
            if (presetUI.useHideUI) DrawUI_StaticHider(player, pInfo.IsHide);
        }
        private const String actionLogRemoved = (LanguageEn ? "written off" : "списано");
        Boolean API_IS_USER(UInt64 userID) => API_IS_USER(userID.ToString());
        private String SQL_Query_SelectedDatabase(String steamId) {
            String SelectUser = $"SELECT * FROM `{config.generalSetting.mySQLConnectionSettings.dbTableName}` WHERE steamid = '{steamId}'";
            return SelectUser;
        }
        private const String actionLogReceived = (LanguageEn ? "received" : "получил");
        private void AddBalance(BasePlayer player, Int32 amount, TypeLog typeLog, String alertMessage = default) {
            if (!player) return;
            PlayerInfo pInfo = PlayerInfo.Get(player.UserIDString);
            if (pInfo == null) return;
            AddBalance(player, pInfo, amount, typeLog, alertMessage);
        }
        void API_SET_BALANCE(BasePlayer player, Int32 balance, ItemContainer itemContainer = null) => AddBalance(player, balance, TypeLog.API);
        private void HookController() {
            Configuration.EarningCoins earningCoins = config.earningCoins;
            if (!isUsedUI) {
                Unsubscribe(nameof(OnPlayerSleepEnded));
                Unsubscribe(nameof(OnPlayerSleep));
            }
            if (!isUsedSQL) Unsubscribe(nameof(CanUserLogin));
            else {
                Unsubscribe(nameof(OnNewSave));
                Unsubscribe(nameof(OnPlayerConnected));
            }
            if (config.generalSetting.typeCoins == TypeCoins.Virtual) {
                Unsubscribe(nameof(OnLootSpawn));
                Unsubscribe(nameof(OnItemSplit));
            }
            else {
                if (!config.generalSetting.physicsItem.droppedItem.isUseDropped) Unsubscribe(nameof(OnLootSpawn));
                if (config.generalSetting.physicsItem.skinID == 0 || plugins.Find("Stacks") || plugins.Find("Loottable") || plugins.Find("CustomSkinsStacksFix") || plugins.Find("SkinBox") || plugins.Find("StackModifier")) {
                    Unsubscribe(nameof(OnPluginLoaded));
                    Unsubscribe(nameof(OnItemSplit));
                }
            }
            Boolean anyGather = earningCoins.resourceGatherEarning.Count == 0 || earningCoins.resourceGatherEarning.Any(x => x.Value.useEarning);
            if(!anyGather) Unsubscribe(nameof(OnDispenserBonusReceived));
            Boolean anyCollectable = earningCoins.resourceCollectable.Count == 0 || earningCoins.resourceCollectable.Any(x => x.Value.useEarning);
            if(!anyCollectable) Unsubscribe(nameof(OnCollectiblePickedup));
            if (!isUsedUI && !earningCoins.killedPlayer.useEarning && !earningCoins.killedNpcs.useEarning && !config.generalSetting.physicsItem.useSaveDeath) Unsubscribe(nameof(OnPlayerDeath));
            if(!config.generalSetting.physicsItem.useSaveDeath || config.generalSetting.typeCoins == TypeCoins.Virtual) Unsubscribe(nameof(OnPlayerRespawned));
            if (!earningCoins.killedBradley.useEarning && !earningCoins.killedAnimal.useEarning && !earningCoins.killedBarrels.useEarning) Unsubscribe(nameof(OnEntityDeath));
            if (!earningCoins.killedHelicopter.useEarning) {
                Unsubscribe(nameof(OnPatrolHelicopterKill));
                Unsubscribe(nameof(OnEntityKill));
            }
        }
        private void ChatCommandBalance(BasePlayer player) {
            if (!player) return;
            Int32 balancePlayer = GetBalancePlayer(player);
            SendChat(GetLang("CHAT_ALERT_BALANCE", player.UserIDString, balancePlayer), player);
        }
        private class ImageUI {
            private const String _path = "IQSystem/IQEconomic/Images/";
            private const String _printPath = "data/" + _path;
            private readonly Dictionary<String, ImageData> _images = new() {
                {
                    "PANEL_BALANCE", new ImageData()
                }
                , {
                    "PANEL_EXCAHNGER", new ImageData()
                }
                , {
                    "ICON_BALANCE", new ImageData()
                }
                , {
                    "ICON_EXCHANGER", new ImageData()
                }
                , {
                    "ICON_UNHIDE", new ImageData()
                }
                , {
                    "ICON_HIDE", new ImageData()
                }
                ,
            }
            ;
            private enum ImageStatus {
                NotLoaded, Loaded, Failed
            }
            private class ImageData {
                public ImageStatus Status = ImageStatus.NotLoaded;
                public String Id {
                    get;
                    set;
                }
            }
            public String GetImage(String name) {
                if (_images.TryGetValue(name, out ImageData image) && image.Status == ImageStatus.Loaded) return image.Id;
                return null;
            }
            public void DownloadImage() {
                if (_ == null) return;
                KeyValuePair<String, ImageData>? image = null;
                foreach (KeyValuePair<String, ImageData> img in _images) {
                    if (img.Value.Status == ImageStatus.NotLoaded) {
                        image = img;
                        break;
                    }
                }
                if (image != null) {
                    ServerMgr.Instance.StartCoroutine(ProcessDownloadImage(image.Value));
                }
                else {
                    List<String> failedImages = new List<String>();
                    foreach (KeyValuePair<String, ImageData> img in _images) {
                        if (img.Value.Status == ImageStatus.Failed) {
                            failedImages.Add(img.Key);
                        }
                    }
                    if (failedImages.Count > 0) {
                        String images = string.Join(", ", failedImages);
                        _.PrintError(LanguageEn ? $"Failed to load the following images: {images}.Perhaps you did not upload them to the '{_printPath}' folder." : $"Не удалось загрузить следующие изображения: {images}.Возможно, вы не загрузили их в папку '{_printPath}'.");
                        Interface.Oxide.UnloadPlugin(_.Name);
                    }
                    else {
                        _.Puts(LanguageEn ? $"{_images.Count} images downloaded successfully!" : $"{_images.Count} изображений успешно загружено!");
                        _interface = new InterfaceBuilder();
                        if(!_.isUsedSQL) foreach (BasePlayer player in BasePlayer.activePlayerList) {
                            _.OnPlayerConnected(player);
                            _.DrawUI_HudPanel(player);
                        }
                    }
                }
            }
            public void UnloadImages() {
                foreach (KeyValuePair<string, ImageData> item in _images) if(item.Value.Status == ImageStatus.Loaded) if (item.Value?.Id != null) FileStorage.server.Remove(uint.Parse(item.Value.Id), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID);
                _images?.Clear();
            }
            private IEnumerator ProcessDownloadImage(KeyValuePair<String, ImageData> image) {
                String url = $"file://{Interface.Oxide.DataDirectory}/{_path}{image.Key}.png";
                using UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
                yield return www.SendWebRequest();
                if (www.result is UnityWebRequest.Result.ConnectionError or UnityWebRequest.Result.ProtocolError) image.Value.Status = ImageStatus.Failed;
                else {
                    Texture2D tex = DownloadHandlerTexture.GetContent(www);
                    image.Value.Id = FileStorage.server.Store(tex.EncodeToPNG(), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID).ToString();
                    image.Value.Status = ImageStatus.Loaded;
                    UnityEngine.Object.DestroyImmediate(tex);
                }
                DownloadImage();
            }
        }
        private void DrawUI_UpdateExchangeFull_Menu(BasePlayer player, Int32 balance, Int32 limiteExchanged) {
            if (_interface == null) return;
            String Interface = InterfaceBuilder.GetInterface("UI_Exchanger_Update_FullExchange_Button");
            if (Interface == null) return;
            Interface = Interface.Replace("%FULL_COURSE_TITLE%", actualyCourse.GetFullBalanceCourseString(player, balance, limiteExchanged));
            AddUI(player, Interface);
        }
        private void OnDispenserBonusReceived(ResourceDispenser dispenser, BasePlayer player, Item item) {
            if (dispenser == null || !player || item == null) return;
            Dictionary<String, Configuration.EarningCoins.PresetEarning> resourceGather = config.earningCoins.resourceGatherEarning;
            String shortname = item.info.shortname;
            if(!resourceGather.TryGetValue(shortname, out Configuration.EarningCoins.PresetEarning resourcePreset)) return;
            if(!resourcePreset.useEarning) return;
            if(!resourcePreset.IsEa
// ... [Code preview truncated due to length. Full source in attached file] ...

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