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

FREE MineralEconomy : 1.0.0 1.0.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Game.Rust.Cui;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Mineral Economy", "YourName", "1.0.0")]
    [Description("Динамическая экономика для минералов с автоматическим изменением цен")]
    public class MineralEconomy : RustPlugin
    {
        #region Fields
        private const string PermissionUse = "mineraleconomy.use";
        private const string PermissionAdmin = "mineraleconomy.admin";
        private const string PermissionCommand = "mineraleconomy.command";
        private const string PermissionButton = "mineraleconomy.button";
        private Configuration config = null!;
        private StoredData storedData = null!;
        private const string UiMain = "MineralEconomy.UI";
        private const string MineralShortname = "coal";
        private const ulong MineralSkinId = 3165461999;
        private readonly Dictionary<ulong, Recycler> playerRecyclers = new();
        private Timer? distanceCheckTimer;
        private const float MaxDistanceFromRecycler = 3f;
        #endregion Fields

        #region Configuration
        private sealed class Configuration
        {
            [JsonProperty("Стоимость продажи минерала в зависимости от наличия")]
            public required List<PriceRange> SellPrices { get; set; }

            [JsonProperty("Стоимость покупки минерала в зависимости от наличия")]
            public required List<PriceRange> BuyPrices { get; set; }

            [JsonProperty("Настройки меню")]
            public required MenuSettings MenuSettings { get; set; }

            public static Configuration DefaultConfig()
            {
                return new Configuration
                {
                    SellPrices = new List<PriceRange>
                    {
                        new()
                        {
                            MinAmount = 0,
                            MaxAmount = 10,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 50,
                            },
                        },
                        new()
                        {
                            MinAmount = 11,
                            MaxAmount = 20,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 40,
                            },
                        },
                        new()
                        {
                            MinAmount = 21,
                            MaxAmount = 30,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 30,
                            },
                        },
                        new()
                        {
                            MinAmount = 31,
                            MaxAmount = 50,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 20,
                            },
                        },
                        new()
                        {
                            MinAmount = 51,
                            MaxAmount = 10000,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 10,
                            },
                        },
                    },
                    BuyPrices = new List<PriceRange>
                    {
                        new()
                        {
                            MinAmount = 0,
                            MaxAmount = 10,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 100,
                            },
                        },
                        new()
                        {
                            MinAmount = 11,
                            MaxAmount = 20,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 80,
                            },
                        },
                        new()
                        {
                            MinAmount = 21,
                            MaxAmount = 30,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 60,
                            },
                        },
                        new()
                        {
                            MinAmount = 31,
                            MaxAmount = 50,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 40,
                            },
                        },
                        new()
                        {
                            MinAmount = 51,
                            MaxAmount = 10000,
                            Price = new()
                            {
                                ShortName = "scrap",
                                SkinId = 0,
                                Amount = 20,
                            },
                        },
                    },
                    MenuSettings = new MenuSettings
                    {
                        AnchorSettings = new AnchorSettings
                        {
                            RecyclerButton = new ButtonSettings
                            {
                                AnchorMin = "0.5 0.2",
                                AnchorMax = "0.6 0.25",
                                OffsetMin = "0 0",
                                OffsetMax = "0 0",
                            },
                        },
                    },
                };
            }
        }

        internal sealed class PriceRange
        {
            [JsonProperty("Минимальное количество")]
            public int MinAmount { get; set; }

            [JsonProperty("Максимальное количество")]
            public int MaxAmount { get; set; }

            [JsonProperty("Цена")]
            public required ItemAmount Price { get; set; }
        }

        internal sealed class ItemAmount
        {
            [JsonProperty(nameof(ShortName))]
            public required string ShortName { get; set; }

            [JsonProperty(nameof(SkinId))]
            public ulong SkinId { get; set; }

            [JsonProperty(nameof(Amount))]
            public int Amount { get; set; }
        }

        internal sealed class MenuSettings
        {
            [JsonProperty("Настройки привязки")]
            public required AnchorSettings AnchorSettings { get; set; }
        }

        internal sealed class AnchorSettings
        {
            [JsonProperty("Кнопка переработчика")]
            public required ButtonSettings RecyclerButton { get; set; }
        }

        internal sealed class ButtonSettings
        {
            [JsonProperty(nameof(AnchorMin))]
            public required string AnchorMin { get; set; }

            [JsonProperty(nameof(AnchorMax))]
            public required string AnchorMax { get; set; }

            [JsonProperty(nameof(OffsetMin))]
            public required string OffsetMin { get; set; }

            [JsonProperty(nameof(OffsetMax))]
            public required string OffsetMax { get; set; }
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                config = Config.ReadObject<Configuration>();
                if (config == null)
                {
                    LoadDefaultConfig();
                }
            }
            catch (Exception ex) when (ex is JsonException or InvalidCastException)
            {
                LoadDefaultConfig();
            }
            SaveConfig();
        }

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

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

        #region Data
        private sealed class StoredData
        {
            [JsonProperty("Всего продано минералов")]
            public int TotalMineralsSold { get; set; }

            [JsonProperty("Всего куплено минералов")]
            public int TotalMineralsBought { get; set; }

            [JsonProperty("Текущий баланс минералов")]
            public int CurrentMineralAmount => TotalMineralsSold - TotalMineralsBought;

            public StoredData()
            {
                TotalMineralsSold = 0;
                TotalMineralsBought = 0;
            }
        }

        private void LoadData()
        {
            storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("MineralEconomy");
            if (storedData == null)
            {
                storedData = new StoredData();
                SaveData();
            }
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject("MineralEconomy", storedData);
        }
        #endregion Data

        #region Oxide Hooks
        private void Init()
        {
            permission.RegisterPermission(PermissionUse, this);
            permission.RegisterPermission(PermissionAdmin, this);
            permission.RegisterPermission(PermissionCommand, this);
            permission.RegisterPermission(PermissionButton, this);
            LoadData();

            distanceCheckTimer = timer.Every(1f, CheckPlayersDistance);
        }

        private void OnServerInitialized(bool initial)
        {
            // Register commands
            cmd.AddChatCommand("mineral", this, CmdMineral);
            cmd.AddChatCommand("minerals", this, CmdMineral);
            cmd.AddChatCommand("givemineral", this, CmdGiveMineral);
        }

        private void Unload()
        {
            distanceCheckTimer?.Destroy();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                if (player == null)
                {
                    continue;
                }

                _ = CuiHelper.DestroyUi(player, UiMain);
                _ = CuiHelper.DestroyUi(player, "MarketRecyclerButton");
            }
        }

        private void CheckPlayersDistance()
        {
            foreach (KeyValuePair<ulong, Recycler> kvp in playerRecyclers.ToList())
            {
                BasePlayer player = BasePlayer.FindByID(kvp.Key);
                Recycler recycler = kvp.Value;

                if (player == null || recycler == null)
                {
                    _ = playerRecyclers.Remove(kvp.Key);
                    continue;
                }

                float distance = Vector3.Distance(
                    player.transform.position,
                    recycler.transform.position
                );
                if (distance > MaxDistanceFromRecycler)
                {
                    DestroyUI(player);
                    SendReply(
                        player,
                        GetLocalizedMessage("TooFarFromRecycler", player.UserIDString)
                    );
                    _ = playerRecyclers.Remove(kvp.Key);
                }
            }
        }
        #endregion Oxide Hooks

        #region Commands
        private void CmdMineral(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermissionCommand))
            {
                SendReply(player, GetLocalizedMessage("NoPermissionCommand", player.UserIDString));
                return;
            }

            ShowUI(player);
        }

        private void CmdGiveMineral(BasePlayer player, string command, string[] args)
        {
            if (!permission.UserHasPermission(player.UserIDString, PermissionAdmin))
            {
                SendReply(player, "У вас нет разрешения на использование этой команды!");
                return;
            }

            if (args.Length < 2)
            {
                SendReply(player, "Использование: /givemineral <игрок> <количество>");
                return;
            }

            BasePlayer target = BasePlayer.Find(args[0]);
            if (target == null)
            {
                SendReply(player, "Игрок не найден!");
                return;
            }

            if (!int.TryParse(args[1], out int amount) || amount <= 0)
            {
                SendReply(player, "Укажите корректное количество минералов!");
                return;
            }

            GiveItem(target, MineralShortname, MineralSkinId, amount);
            storedData.TotalMineralsSold += amount;
            SaveData();

            SendReply(player, $"Вы выдали {amount} минералов игроку {target.displayName}");
            SendReply(target, $"Вы получили {amount} минералов от администратора");
        }

        [ConsoleCommand("mineraleconomy.sell")]
        private void CmdSell(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (player == null)
            {
                return;
            }

            int amount = arg.GetInt(0, 1);
            if (amount is not (1 or 10))
            {
                SendReply(player, "Неверное количество минералов!");
                return;
            }

            int currentPrice = GetCurrentSellPrice();

            if (!HasItem(player, MineralShortname, MineralSkinId, amount))
            {
                SendReply(player, "У вас недостаточно минералов!");
                return;
            }

            TakeItem(player, MineralShortname, MineralSkinId, amount);
            GiveItem(player, "scrap", 0, currentPrice * amount);
            storedData.TotalMineralsSold += amount;
            SaveData();

            SendReply(player, $"Вы продали {amount} минералов за {currentPrice * amount} скрапа!");
            ShowUI(player);
        }

        [ConsoleCommand("mineraleconomy.buy")]
        private void CmdBuy(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (player == null)
            {
                return;
            }

            int amount = arg.GetInt(0, 1);
            if (amount is not (1 or 10))
            {
                SendReply(player, "Неверное количество минералов!");
                return;
            }

            int currentPrice = GetCurrentBuyPrice();

            if (!HasItem(player, "scrap", 0, currentPrice * amount))
            {
                SendReply(player, "У вас недостаточно скрапа!");
                return;
            }

            if (storedData.CurrentMineralAmount < amount)
            {
                SendReply(player, "На сервере недостаточно минералов!");
                return;
            }

            TakeItem(player, "scrap", 0, currentPrice * amount);
            GiveItem(player, MineralShortname, MineralSkinId, amount);
            storedData.TotalMineralsBought += amount;
            SaveData();

            SendReply(player, $"Вы купили {amount} минералов за {currentPrice * amount} скрапа!");
            ShowUI(player);
        }
        #endregion Commands

        #region UI
        private void ShowUI(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            try
            {
                DestroyUI(player);

                Recycler? nearestRecycler = null;
                float minDistance = float.MaxValue;

                foreach (Recycler recycler in UnityEngine.Object.FindObjectsOfType<Recycler>())
                {
                    float distance = Vector3.Distance(
                        player.transform.position,
                        recycler.transform.position
                    );
                    if (distance < minDistance)
                    {
                        minDistance = distance;
                        nearestRecycler = recycler;
                    }
                }

                if (nearestRecycler == null || minDistance > MaxDistanceFromRecycler)
                {
                    SendReply(
                        player,
                        GetLocalizedMessage("TooFarFromRecycler", player.UserIDString)
                    );
                    return;
                }

                playerRecyclers[player.userID] = nearestRecycler;

                int currentSellPrice = GetCurrentSellPrice();
                int currentBuyPrice = GetCurrentBuyPrice();

                CuiElementContainer container = new()
                {
                    // Основная панель
                    {
                        new CuiPanel
                        {
                            Image =
                            {
                                Color = HexToRustFormat("#3c3a34"),
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            RectTransform = { AnchorMin = "0.25 0.15", AnchorMax = "0.75 0.85" },
                            CursorEnabled = true,
                        },
                        "Overlay",
                        UiMain
                    },
                    // Верхняя панель заголовка
                    {
                        new CuiPanel
                        {
                            Image =
                            {
                                Color = HexToRustFormat("#524e49"),
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            RectTransform = { AnchorMin = "0 0.9", AnchorMax = "1 1" },
                        },
                        UiMain
                    },
                    // Заголовок
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = GetLocalizedMessage("MarketTitle", player.UserIDString),
                                FontSize = 20,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0 0.9", AnchorMax = "1 1" },
                        },
                        UiMain
                    },
                    // Добавляем подзаголовок с описанием
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = "Цены зависят от количества минералов на рынке",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0 0.86", AnchorMax = "1 0.89" },
                        },
                        UiMain
                    },
                    // Кнопка закрытия
                    {
                        new CuiButton
                        {
                            Button =
                            {
                                Color = "0.7 0.3 0.2 0.98",
                                Command = "mineraleconomy.close",
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            Text =
                            {
                                Text = "✕",
                                FontSize = 20,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.92 0.91", AnchorMax = "0.98 0.99" },
                        },
                        UiMain
                    },
                    // Информационная панель
                    {
                        new CuiPanel
                        {
                            Image =
                            {
                                Color = HexToRustFormat("#524e49"),
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            RectTransform = { AnchorMin = "0.05 0.75", AnchorMax = "0.95 0.85" },
                        },
                        UiMain
                    },
                    // Баланс минералов с дополнительной информацией
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text =
                                    $"Текущий баланс рынка: {storedData.CurrentMineralAmount} минералов",
                                FontSize = 16,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.1 0.79", AnchorMax = "0.9 0.85" },
                        },
                        UiMain
                    },
                    // Актуальный курс продажи с пояснением
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = $"Текущая цена продажи: {currentSellPrice} ⚙ за минерал",
                                FontSize = 14,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleRight,
                                Color = HexToRustFormat("#7FD47F"),
                            },
                            RectTransform = { AnchorMin = "0.1 0.75", AnchorMax = "0.48 0.79" },
                        },
                        UiMain
                    },
                    // Актуальный курс покупки с пояснением
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = $"Текущая цена покупки: {currentBuyPrice} ⚙ за минерал",
                                FontSize = 14,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleLeft,
                                Color = HexToRustFormat("#FF6B6B"),
                            },
                            RectTransform = { AnchorMin = "0.52 0.75", AnchorMax = "0.9 0.79" },
                        },
                        UiMain
                    },
                    // Панель продажи
                    {
                        new CuiPanel
                        {
                            Image =
                            {
                                Color = HexToRustFormat("#524e49"),
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            RectTransform = { AnchorMin = "0.05 0.45", AnchorMax = "0.475 0.7" },
                        },
                        UiMain
                    },
                    // Заголовок продажи
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = GetLocalizedMessage("SellToServer", player.UserIDString),
                                FontSize = 16,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.05 0.65", AnchorMax = "0.475 0.7" },
                        },
                        UiMain
                    },
                    // Кнопки продажи
                    {
                        new CuiButton
                        {
                            Button =
                            {
                                Color = HexToRustFormat("#637640"),
                                Command = "mineraleconomy.sell 1",
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            Text =
                            {
                                Text = $"ПРОДАТЬ 1 МИНЕРАЛ\nВы получите {currentSellPrice} ⚙",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.07 0.55", AnchorMax = "0.455 0.62" },
                        },
                        UiMain
                    },
                    {
                        new CuiButton
                        {
                            Button =
                            {
                                Color = HexToRustFormat("#637640"),
                                Command = "mineraleconomy.sell 10",
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            Text =
                            {
                                Text =
                                    $"ПРОДАТЬ 10 МИНЕРАЛОВ\nВы получите {currentSellPrice * 10} ⚙",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.07 0.46", AnchorMax = "0.455 0.53" },
                        },
                        UiMain
                    },
                    // Панель покупки
                    {
                        new CuiPanel
                        {
                            Image =
                            {
                                Color = HexToRustFormat("#524e49"),
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            RectTransform = { AnchorMin = "0.525 0.45", AnchorMax = "0.95 0.7" },
                        },
                        UiMain
                    },
                    // Заголовок покупки
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = GetLocalizedMessage("BuyFromServer", player.UserIDString),
                                FontSize = 16,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.525 0.65", AnchorMax = "0.95 0.7" },
                        },
                        UiMain
                    },
                    // Кнопки покупки
                    {
                        new CuiButton
                        {
                            Button =
                            {
                                Color = HexToRustFormat("#783838"),
                                Command = "mineraleconomy.buy 1",
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            Text =
                            {
                                Text = $"КУПИТЬ 1 МИНЕРАЛ\nСтоимость: {currentBuyPrice} ⚙",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.545 0.55", AnchorMax = "0.93 0.62" },
                        },
                        UiMain
                    },
                    {
                        new CuiButton
                        {
                            Button =
                            {
                                Color = HexToRustFormat("#783838"),
                                Command = "mineraleconomy.buy 10",
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            Text =
                            {
                                Text = $"КУПИТЬ 10 МИНЕРАЛОВ\nСтоимость: {currentBuyPrice * 10} ⚙",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.545 0.46", AnchorMax = "0.93 0.53" },
                        },
                        UiMain
                    },
                    // Таблица цен
                    {
                        new CuiPanel
                        {
                            Image =
                            {
                                Color = HexToRustFormat("#524e49"),
                                Material = "assets/content/ui/uibackgroundblur-ingame.mat",
                            },
                            RectTransform = { AnchorMin = "0.05 0.05", AnchorMax = "0.95 0.4" },
                        },
                        UiMain
                    },
                    // Заголовок таблицы с подробным описанием
                    {
                        new CuiLabel
                        {
                            Text =
                            {
                                Text =
                                    "СИСТЕМА ДИНАМИЧЕСКОГО ЦЕНООБРАЗОВАНИЯ\n"
                                    + "Цены автоматически меняются в зависимости от количества минералов на рынке:\n"
                                    + "• Чем меньше минералов, тем выше цена покупки\n"
                                    + "• Чем больше минералов, тем ниже цена продажи",
                                FontSize = 12,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform = { AnchorMin = "0.05 0.35", AnchorMax = "0.95 0.4" },
                        },
                        UiMain
                    },
                };

                // Заголовки колонок с пояснениями
                string[] headers = { "Баланс рынка", "Цена продажи (⚙)", "Цена покупки (⚙)" };

                const float columnWidth = 0.28f;
                const float startX = 0.055f;

                for (int i = 0; i < headers.Length; i++)
                {
                    _ = container.Add(
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = headers[i],
                                FontSize = 12,
                                Font = "robotocondensed-bold.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform =
                            {
                                AnchorMin = $"{startX + (i * (columnWidth + 0.02))} 0.3",
                                AnchorMax = $"{startX + ((i + 1) * columnWidth) + (i * 0.02)} 0.35",
                            },
                        },
                        UiMain
                    );
                }

                // Данные таблицы с пояснениями
                for (int i = 0; i < config.SellPrices.Count; i++)
                {
                    float yMin = 0.25f - (i * 0.04f);
                    float yMax = yMin + 0.035f;

                    _ = container.Add(
                        new CuiLabel
                        {
                            Text =
                            {
                                Text =
                                    $"{config.SellPrices[i].MinAmount}-{config.SellPrices[i].MaxAmount} шт.",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#dcd3cc"),
                            },
                            RectTransform =
                            {
                                AnchorMin = $"{startX} {yMin}",
                                AnchorMax = $"{startX + columnWidth} {yMax}",
                            },
                        },
                        UiMain
                    );

                    _ = container.Add(
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = $"{config.SellPrices[i].Price.Amount} ⚙ за шт.",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#7FD47F"),
                            },
                            RectTransform =
                            {
                                AnchorMin = $"{startX + columnWidth + 0.02} {yMin}",
                                AnchorMax = $"{startX + (2 * columnWidth) + 0.02} {yMax}",
                            },
                        },
                        UiMain
                    );

                    _ = container.Add(
                        new CuiLabel
                        {
                            Text =
                            {
                                Text = $"{config.BuyPrices[i].Price.Amount} ⚙ за шт.",
                                FontSize = 12,
                                Font = "robotocondensed-regular.ttf",
                                Align = TextAnchor.MiddleCenter,
                                Color = HexToRustFormat("#FF6B6B"),
                            },
                            RectTransform =
                            {
                                AnchorMin = $"{startX + (2 * columnWidth) + 0.04} {yMin}",
                                AnchorMax = $"{startX + (3 * columnWidth) + 0.04} {yMax}",
                            },
                        },
                        UiMain
                    );
                }

                _ = CuiHelper.AddUi(player, container);
            }
            catch (Exception ex)
            {
                PrintError($"Error showing UI for {player.displayName}: {ex}");
            }
        }

        private void DestroyUI(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            try
            {
                _ = CuiHelper.DestroyUi(player, UiMain);
            }
            catch (ArgumentException ex)
            {
                PrintError(
                    $"Invalid UI arguments while destroying for {player.displayName}: {ex.Message}"
                );
            }
            catch (InvalidOperationException ex)
            {
                PrintError(
                    $"Invalid UI operation while destroying for {player.displayName}: {ex.Message}"
                );
            }
        }
        #endregion UI

        #region Helpers
        private string HexToRustFormat(string hex)
        {
            if (hex.StartsWith('#'))
            {
                hex = hex.Substring(1);
            }

            if (hex.Length is 6 or 8)
            {
                int r = Convert.ToInt32(hex.Substring(0, 2), 16);
                int g = Convert.ToInt32(hex.Substring(2, 2), 16);
                int b = Convert.ToInt32(hex.Substring(4, 2), 16);
                float a = hex.Length == 8 ? Convert.ToInt32(hex.Substring(6, 2), 16) / 255f : 1f;

                return $"{r / 255f} {g / 255f} {b / 255f} {a}";
            }

            return "1 1 1 1";
        }

        private int GetCurrentSellPrice()
        {
            PriceRange range = config.SellPrices.FirstOrDefault(r =>
                storedData.CurrentMineralAmount >= r.MinAmount
                && storedData.CurrentMineralAmount <= r.MaxAmount
            );

            return range?.Price.Amount ?? 0;
        }

        private int GetCurrentBuyPrice()
        {
            PriceRange range = config.BuyPrices.FirstOrDefault(r =>
                storedData.CurrentMineralAmount >= r.MinAmount
                && storedData.CurrentMineralAmount <= r.MaxAmount
            );

            return range?.Price.Amount ?? 0;
        }

        [ConsoleCommand("mineraleconomy.close")]
        private void CmdCloseUI(ConsoleSystem.Arg arg)
        {
            BasePlayer player = arg.Player();
            if (player == null)
            {
                return;
            }

            DestroyUI(player);
        }

        private bool HasItem(BasePlayer player, string shortname, ulong skinId, int amount)
        {
            ItemDefinition definition = ItemManager.FindItemDefinition(shortname);
            if (definition == null)
            {
                return false;
            }

            int totalAmount = 0;
            ItemContainer mainContainer = player.inventory.containerMain;
            foreach (Item item in mainContainer.itemList)
            {
                if (item.info.itemid == definition.itemid && item.skin == skinId)
                {
                    totalAmount += item.amount;
                }
            }
            return totalAmount >= amount;
        }

        private void TakeItem(BasePlayer player, string shortname, ulong skinId, int amount)
        {
            ItemDefinition definition = ItemManager.FindItemDefinition(shortname);
            if (definition == null)
            {
                return;
            }

            int remainingAmount = amount;
            ItemContainer mainContainer = player.inventory.containerMain;
            List<Item> itemsToRemove = new();

            foreach (Item item in mainContainer.itemList)
            {
                if (remainingAmount <= 0)
                {
                    break;
                }
                if (item.info.itemid == definition.itemid && item.skin == skinId)
                {
                    int amountToTake = Math.Min(remainingAmount, item.amount);
                    if (amountToTake >= item.amount)
                    {
                        remainingAmount -= item.amount;
                        itemsToRemove.Add(item);
                    }
                    else
                    {
                        item.amount -= amountToTake;
                        remainingAmount -= amountToTake;
                        item.MarkDirty();
                    }
                }
            }

            foreach (Item item in itemsToRemove)
            {
                item.Remove();
            }
        }

        private void GiveItem(BasePlayer player, string shortname, ulong skinId, int amount)
        {
            Item item = ItemManager.CreateByName(shortname, amount, skinId);
            if (item != null)
            {
                player.GiveItem(item);
            }
        }
        #endregion Helpers

        #region Localization
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["MarketTitle"] = "MINERAL MARKET",
                    ["MarketTitleRu"] = "ТОРГОВАЯ ПЛОЩАДКА МИНЕРАЛОВ",
                    ["MarketButton"] = "Mineral market",
                    ["MarketButtonRu"] = "РЫНОК МИНЕРАЛОВ",
                    ["AvailableAmount"] = "AVAILABLE ON MARKET",
                    ["AvailableAmountRu"] = "ДОСТУПНО НА РЫНКЕ",
                    ["CurrentRate"] = "CURRENT RATE",
                    ["CurrentRateRu"] = "АКТУАЛЬНЫЙ КУРС",
                    ["SellToServer"] = "SELL TO SERVER",
                    ["SellToServerRu"] = "ПРОДАЖА СЕРВЕРУ",
                    ["BuyFromServer"] = "BUY FROM SERVER",
                    ["BuyFromServerRu"] = "ПОКУПКА У СЕРВЕРА",
                    ["SellDescription"] = "Sell your minerals to the server at a profitable price",
                    ["SellDescriptionRu"] = "Продайте ваши минералы серверу по выгодной цене",
                    ["BuyDescription"] = "Buy minerals from the server at current rate",
                    ["BuyDescriptionRu"] = "Приобретайте минералы у сервера по текущему курсу",
                    ["PricingSystem"] = "DYNAMIC PRICING SYSTEM",
                    ["PricingSystemRu"] = "СИСТЕМА ДИНАМИЧЕСКОГО ЦЕНООБРАЗОВАНИЯ",
                    ["MarketAmount"] = "MARKET AMOUNT",
                    ["MarketAmountRu"] = "КОЛИЧЕСТВО НА РЫНКЕ",
                    ["SellPrice"] = "SELL PRICE",
                    ["SellPriceRu"] = "ЦЕНА ПРОДАЖИ",
                    ["BuyPrice"] = "BUY PRICE",
                    ["BuyPriceRu"] = "ЦЕНА ПОКУПКИ",
                    ["TooFarFromRecycler"] = "Вы слишком далеко от переработчика!",
                },
                this
            );
        }

        private string GetLocalizedMessage(string key, string? userId = null)
        {
            return lang.GetMessage(key, this, userId);
        }
        #endregion Localization

        #region UI Hooks
        private void OnLootEntity(BasePlayer player, StorageContainer container)
        {
            if (player == null || container == null)
            {
                return;
            }

            Recycler? recycler = container as Recycler;
            if (recycler != null)
            {
                if (!permission.UserHasPermission(player.UserIDString, PermissionButton))
                {
                    SendReply(
                        player,
                        GetLocalizedMessage("NoPermissionButton", player.UserIDString)
                    );
                    return;
                }

                CuiElementContainer elements = new()
                {
                    {
                        new CuiPanel
                        {
                            CursorEnabled = false,
                            RectTransform =
                            {
                                AnchorMin = "0.5 0",
                                AnchorMax = "0.5 0",
                                OffsetMin = "470 400",
                                OffsetMax = "572 420",
                            },
                            Image = { Color = "0 0 0 0" },
                        },
                        "Overlay",
                        "MarketRecyclerPanel"
                    },
                    {
                        new CuiButton
                        {
                            Button =
                            {
                                Color = "0.4313726 0.5372549 0.2705882 1",
                                Command = "chat.say /mineral",
                                Material = "assets/icons/greyout.mat",
                            },
                            Text =
                            {
                                Text = GetLocalizedMessage("MarketButton", player.UserIDString),
                                Font = "robotocondensed-bold.ttf",
                                FontSize = 12,
                                Align = TextAnchor.MiddleCenter,
                                Color = "0.9686275 0.9215687 0.8705883 1",
                            },
                            RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
                        },
                        "MarketRecyclerPanel",
                        "MarketRecyclerButton"
                    },
                };

                _ = CuiHelper.DestroyUi(player, "MarketRecyclerPanel");
                _ = CuiHelper.AddUi(player, elements);
            }
        }

        private void OnLootEntityEnd(BasePlayer player, StorageContainer container)
        {
            if (player == null)
            {
                return;
            }

            Recycler? recycler = container as Recycler;
            if (recycler != null)
            {
                _ = CuiHelper.DestroyUi(player, "MarketRecyclerPanel");
            }
        }

        private void OnEntityDismounted(BaseMountable entity, BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            _ = CuiHelper.DestroyUi(player, "MarketRecyclerPanel");
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player == null)
            {
                return;
            }

            _ = CuiHelper.DestroyUi(player, "MarketRecyclerPanel");
        }

        private void OnPlayerSleepEnded(BasePlayer player)
        {
            if (player == null)
            {
                return;
            }

            _ = CuiHelper.DestroyUi(player, "MarketRecyclerPanel");
        }
        #endregion UI Hooks
    }
}

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