C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using WebSocketSharp;
namespace Oxide.Plugins {
[Info("GameStoresRUST", "TopPlugin.ru", "3.0.0")]
public class GameStoresRUST : RustPlugin {
#region References
[PluginReference]
private Plugin ImageLibrary;
#endregion
#region Classes
private static class Delays {
[JsonProperty("Игроки с активными запросами к АПИ")]
public static List<ulong> ItemList = new List<ulong>();
[JsonProperty("Количество запросов за последнюю секунду")]
public static int RequestPerSecond = 0;
[JsonProperty("Ограничение запросов в секунду")]
public static int RequestPerSecondLimit = 20;
public static bool CanRequest(BasePlayer player) {
if (RequestPerSecond > RequestPerSecondLimit) {
return false;
}
if (ItemList.Contains(player.userID)) {
player.ChatMessage($"Пожалуйста, дождитесь <<окончания>> предыдущего действия!");
return false;
}
return true;
}
public static void FinishRequest(BasePlayer player) {
if (ItemList.Contains(player.userID)) ItemList.Remove(player.userID);
}
public static IEnumerator MakeRequest(BasePlayer player) {
RequestPerSecond++;
if (ItemList.Contains(player.userID)) yield return null;
ItemList.Add(player.userID);
yield return new WaitForSeconds(3f);
if (ItemList.Contains(player.userID)) ItemList.Remove(player.userID);
}
}
private class Stats {
}
private class Configuration {
public class API {
[JsonProperty("ИД магазина в сервисе")]
public string ShopID = "UNDEFINED";
[JsonProperty("ИД сервера в сервисе")]
public string ServerID = "UNDEFINED";
[JsonProperty("Секретный ключ (не распространяйте его)")]
public string SecretKey = "UNDEFINED";
}
public class Interface {
[JsonProperty("Количество предметов на строке")]
public int ItemOnString = 7;
[JsonProperty("Количество строк в интерфейсе")]
public int StringAmount = 5;
[JsonProperty("Сторона одного предмета")]
public int ItemSide = 100;
[JsonProperty("Отступ между предметами")]
public int ItemMargin = 5;
}
public class TOP {
[JsonProperty("Отправлять данные топа игроков")]
public bool UseTop = true;
}
[JsonProperty("Настройки API плагина")]
public API APISettings = new API();
[JsonProperty("Настройки интерфейса плагина")]
public Interface InterfaceSettings = new Interface();
[JsonProperty("Настройки статистики сервера")]
public TOP TOPSettings = new TOP();
}
private class WItem {
public string ID;
public string Name;
public int ItemID;
public int Amount;
public string ShortName;
public string Command;
public string ImageUrl;
public bool Blocked;
public double Block_Date = 0;
public bool IsBlueprint;
public bool IsCommand;
public bool IsItem;
public WItem(Dictionary<string, object> data, bool show = true) {
try {
if (data.ContainsKey("id")) ID = data["id"].ToString();
if (data.ContainsKey("name")) Name = data["name"].ToString();
if (data.ContainsKey("item_id")) ItemID = System.Convert.ToInt32(data["item_id"]);
if (data.ContainsKey("amount")) Amount = System.Convert.ToInt32(data["amount"]);
if (data.ContainsKey("command")) Command = data["command"].ToString();
if (data.ContainsKey("img")) ImageUrl = data["img"].ToString();
if (data.ContainsKey("blocked")) Blocked = bool.Parse(data["blocked"].ToString());
if (data.ContainsKey("block_date") && data["block_date"] is int) {
double.TryParse(data["block_date"].ToString(), out Block_Date);
}
if (data.ContainsKey("type")) {
IsBlueprint = data["type"].ToString() == "bp";
IsCommand = data["type"].ToString() == "command";
IsItem = data["type"].ToString() == "item";
}
if (ItemID != 0) {
var itemInfo = ItemManager.FindItemDefinition(ItemID);
if (itemInfo != null) ShortName = itemInfo.shortname;
else if (IDToShortName.ContainsKey(ItemID)) {
itemInfo = ItemManager.FindItemDefinition(IDToShortName[ItemID]);
if (itemInfo == null) return;
ShortName = itemInfo.shortname;
}
}
var imageLibrary = instance.plugins.Find("ImageLibrary");
if (imageLibrary != null) {
if (ItemID == 0) {
if ((bool)imageLibrary.Call("HasImage", $"IconGS.{ID}")) {
string probablyId = (string)imageLibrary.Call("GetImage", $"IconGS.{ID}");
if (!probablyId.IsNullOrEmpty() && probablyId != instance.NoImageID && probablyId != instance.LoadingImageID) ImageUrl = probablyId;
return;
}
if (!ImageUrl.IsNullOrEmpty()) {
imageLibrary.Call("AddImage", ImageUrl.Replace("https", "http"), $"IconGS.{ID}");
}
}
else {
string probablyId = (string)imageLibrary.Call("GetImage", ShortName);
if (!probablyId.IsNullOrEmpty() && probablyId != instance.NoImageID && probablyId != instance.LoadingImageID) ImageUrl = probablyId;
}
}
}
catch (NullReferenceException e) {
Interface.Oxide.LogError(JsonConvert.SerializeObject(data));
}
}
}
#endregion
#region Variables
private static bool initialization = false;
private static bool Initialized = false;
private static GameStoresRUST instance;
private static Configuration Settings = new Configuration();
private string ShopURL = "UNDEFINED";
private int StartBalance = 0;
public string NoImageID = "";
public string LoadingImageID = "";
private Dictionary<int, Dictionary<ulong, int>> ListTimeOutCommand = new Dictionary<int, Dictionary<ulong, int>>();
private Dictionary<ulong, List<int>> playersBasketCache = new Dictionary<ulong, List<int>>();
private HashSet<ulong> ListBannedCommandUserID = new HashSet<ulong>();
private Timer TimerCheckInstant;
private string MainApiLink = $"https://gamestores.ru/api/";
private string ReserveApiLink = $"https://gs.gamestores.ru/api/";
//private string BaseRequest => $"https://gamestores.ru/api/?shop_id={Settings.APISettings.ShopID}&secret={Settings.APISettings.SecretKey}{(!Settings.APISettings.ServerID.IsNullOrEmpty() && Settings.APISettings.ServerID != "0" && Settings.APISettings.ServerID != "1" && Settings.APISettings.ServerID != "UNDEFINED" ? $"&server={Settings.APISettings.ServerID}" : "")}";
private string BaseRequestParams => $"?shop_id={Settings.APISettings.ShopID}&secret={Settings.APISettings.SecretKey}{(!Settings.APISettings.ServerID.IsNullOrEmpty() && Settings.APISettings.ServerID != "0" && Settings.APISettings.ServerID != "1" && Settings.APISettings.ServerID != "UNDEFINED" ? $"&server= {
Settings.APISettings.ServerID
}
" : "")}";
private string BaseRequest = "";
#endregion
#region Interface
private int TryImageCounter = 0;
private void OnServerInitialized() {
PrintWarning("\n-----------------------------\n" + " Author - https://topplugin.ru/\n" + " VK - https://vk.com/rustnastroika\n" + " Discord - https://discord.com/invite/5DPTsRmd3G\n" + "-----------------------------");
BaseRequest = MainApiLink + BaseRequestParams;
if (Settings.APISettings.ServerID != "0" && Settings.APISettings.ServerID != "UNDEFINED") {
TimerCheckInstant = timer.Repeat(20, 0, CheckInstant);
}
else {
LogAction(null, $"Некорректный ServerID, автоматическая выдача команд невозможна");
PrintError($"Incorrect ServerID, reciving auto commands (Products) disabled");
}
if (!ImageLibrary) {
if (TryImageCounter < 3) {
LogAction(null, $"ImageLibrary is not initialized, try again in 1 sec.", true);
TryImageCounter++;
timer.Once(1, OnServerInitialized);
return;
}
else LogAction(null, $"Starting without ImageLibrary", true);
}
if (ImageLibrary) {
NoImageID = (string)ImageLibrary.Call("GetImage", "NONE");
LoadingImageID = (string)ImageLibrary.Call("GetImage", "LOADING");
}
instance = this;
if (!Settings.TOPSettings.UseTop) Unsubscribe(nameof(OnEntityDeath));
if (!Settings.TOPSettings.UseTop) Unsubscribe(nameof(OnPlayerDisconnected));
if (Settings.APISettings.ShopID == "UNDEFINED" || Settings.APISettings.SecretKey == "UNDEFINED") {
LogAction(null, $"Verify that plugin is installed correct! Some of API settings are 'UNDEFINED'", true, true);
return;
}
timer.Once(2, FetchShopUrl);
timer.Every(1, () => Delays.RequestPerSecond = 0);
ListTimeOutCommand[0] = new Dictionary<ulong, int>();
ListTimeOutCommand[1] = new Dictionary<ulong, int>();
ListTimeOutCommand[2] = new Dictionary<ulong, int>();
int totalTick = 0;
int tick = 0;
timer.Repeat(2, 0, () => {
if (totalTick == 30) {
totalTick = 0;
ListBannedCommandUserID.Clear();
}
ListTimeOutCommand[0].Clear();
if (tick == 3 || tick == 6) {
ListTimeOutCommand[1].Clear();
}
if (tick == 6) {
tick = 0;
ListTimeOutCommand[2].Clear();
}
tick++;
totalTick++;
}
);
}
protected override void LoadConfig() {
base.LoadConfig();
try {
Settings = Config.ReadObject<Configuration>();
if (Settings?.APISettings == null) LoadDefaultConfig();
}
catch {
LogAction(null, $"Error reading config, creating one new config!", true, true);
LoadDefaultConfig();
}
NextTick(SaveConfig);
}
protected override void LoadDefaultConfig() {
Settings = new Configuration();
}
protected override void SaveConfig() => Config.WriteObject(Settings);
private void Unload() {
foreach (var pl in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(pl, StoreLayer);
}
}
#endregion
#region Hooks
private void OnPlayerDisconnected(BasePlayer player, string reason) {
StatHandler.AddStat(new StatHandler.TimeStat(player));
}
#endregion
#region Stats
private static class StatHandler {
internal class Stat {
[JsonProperty("dataType")]
public string DataType;
}
internal class KillStat : Stat {
[JsonProperty("player_id")]
public string PlayerUserId;
[JsonProperty("victim_id")]
public string VictimUserID;
[JsonProperty("type")]
public string Type;
[JsonProperty("time")]
public string Time;
}
internal class TimeStat : Stat {
[JsonProperty("player_id")]
public string PlayerID;
[JsonProperty("username")]
public string PlayerName;
[JsonProperty("played")]
public string Played;
[JsonProperty("time")]
public string Time;
public TimeStat(BasePlayer player) {
PlayerID = player.UserIDString;
PlayerName = player.displayName;
DataType = "leave";
Played = player.secondsConnected.ToString();
Time = CurrentTime().ToString();
}
}
private static List<Stat> Stats = new List<Stat>();
public static void AddStat(Stat stat) {
Stats.Add(stat);
if (Stats.Count > 10) {
SendStats();
Stats.Clear();
}
}
public static void SendStats() {
try {
if (!Initialized) {
instance.LogAction(null, $"Sending stats error! Plugin not initialized", true, true);
return;
}
if (Stats.Count == 0) {
instance.LogAction(null, $"Nothing to send", true);
return;
}
var obj = JsonConvert.SerializeObject(Stats);
RequestPost($"&method=topData&data={obj}", (i, s) => {
if (i != 200) return;
Dictionary<string, object> response = JsonConvert.DeserializeObject<Dictionary<string, object>>(s, new KeyValuesConverter());
if (response.ContainsKey("result") && response["result"].ToString() == "success") {
instance.LogAction(null, $"GameStores sent stats successful!", true);
Stats.Clear();
}
else {
instance.LogAction(null, $"Sending stats error!", true, true);
}
}
);
}
catch {
// ignored
}
}
}
[ConsoleCommand("sendtop")]
private void CmdSendTop(ConsoleSystem.Arg args) {
if (args.Player() != null && !args.Player().IsAdmin) return;
StatHandler.SendStats();
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (entity == null || info == null || info.Initiator == null) return;
if (Settings.TOPSettings.UseTop) {
BaseEntity initiator = info.Initiator;
if (entity as BasePlayer == null && initiator as BasePlayer == null) return;
StatHandler.KillStat stat = new StatHandler.KillStat();
if (initiator as BasePlayer != null) stat.PlayerUserId = initiator.ToPlayer().UserIDString;
else if (initiator.PrefabName.Contains("agents")) stat.PlayerUserId = "1";
else return;
if (entity as BasePlayer != null) {
stat.VictimUserID = entity.ToPlayer().UserIDString;
stat.Type = entity.ToPlayer().IsSleeping() ? "sleeper" : "kill";
}
else if (entity.PrefabName.Contains("agents")) {
stat.VictimUserID = "1";
stat.Type = "kill";
}
else {
return;
}
stat.DataType = "death";
stat.Time = CurrentTime().ToString();
StatHandler.AddStat(stat);
}
}
#endregion
#region Commands
[ConsoleCommand("UI_GameStoresRUST")]
private void CmdConsoleCommand(ConsoleSystem.Arg args) {
BasePlayer player = args.Player();
if (player == null) return;
if (ListBannedCommandUserID.Contains(player.userID)) {
player.ChatMessage("Вы сделали слишком много запросов.Отдохните немного, скоро возможность выполнять действие к вам вернется.");
return;
}
if (ListTimeOutCommand[0].ContainsKey(player.userID) == false) ListTimeOutCommand[0][player.userID] = 1;
else ListTimeOutCommand[0][player.userID] = ListTimeOutCommand[0][player.userID] + 1;
if (ListTimeOutCommand[1].ContainsKey(player.userID) == false) ListTimeOutCommand[1][player.userID] = 1;
else ListTimeOutCommand[1][player.userID] = ListTimeOutCommand[1][player.userID] + 1;
if (ListTimeOutCommand[2].ContainsKey(player.userID) == false) ListTimeOutCommand[2][player.userID] = 1;
else ListTimeOutCommand[2][player.userID] = ListTimeOutCommand[2][player.userID] + 1;
if (ListTimeOutCommand[0][player.userID] >= 10 || ListTimeOutCommand[1][player.userID] >= 20 || ListTimeOutCommand[2][player.userID] >= 30) {
this.ListBannedCommandUserID.Add(player.userID);
}
switch (args.Args[0].ToLower()) {
case "page" : {
int page = 0;
if (!args.HasArgs(2) || !int.TryParse(args.Args[1], out page)) return;
InitializeStore(player, page, false);
break;
}
case "take" : {
if (!args.HasArgs(3)) return;
int index = 0, id = 0;
if (!int.TryParse(args.Args[1], out index) || !int.TryParse(args.Args[2], out id)) return;
if (!playersBasketCache.ContainsKey(player.userID)) {
player.ChatMessage("Предмет не найден, попробуйте перезапустить корзину");
return;
}
else if (!playersBasketCache[player.userID].Contains(id)) {
player.ChatMessage("Предмет не найден, попробуйте перезапустить корзину");
return;
}
if (args.HasArgs(5) && args.Args[3].ToLower() == "blocked") {
double left = 0;
if (!double.TryParse(args.Args[4], out left)) return;
TimeSpan span = TimeSpan.FromSeconds(left);
string text = "";
if (span.Days >= 1) text += $"{span.Days} дн.";
if (span.Hours >= 1) text += $"{span.Hours} ч.";
if (span.Minutes >= 1) text += $"{span.Minutes} мин.";
if (span.Seconds >= 1) text += $"{span.Seconds} сек.";
ShowNotify(player, "Вы не можете забрать этот предмет из корзины!\n" + $"До его разблокировки осталось: {text}");
return;
}
ShowNotify(player, "Подождите, ваш запрос обрабатывается!");
CuiElementContainer container = new CuiElementContainer();
if (!Delays.CanRequest(player)) {
ShowNotify(player, "Подождите, ваш предыдущий запрос ещё обрабатывается!");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "1 1 1 0.2", Close = StoreLayer + ".BlockPanel." + index + ".Open", Command = $"UI_GameStoresRUST take {index} {id}"
}
, Text = {
Text = "ПОДОЖДИТЕ", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", Color = "1 1 1 0.4", FontSize = 14
}
}
, StoreLayer + ".BlockPanel." + index, StoreLayer + ".BlockPanel." + index + ".Open");
CuiHelper.AddUi(player, container);
return;
}
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
FadeIn = 1f, Color = "1 1 1 0.2", Close = StoreLayer + ".BlockPanel." + index + ".Open", Command = $"UI_GameStoresRUST take {index} {id}", Material = ""
}
, Text = {
Text = "ПОДОЖДИТЕ", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", Color = "1 1 1 0.4", FontSize = 14
}
}
, StoreLayer + ".BlockPanel." + index, StoreLayer + ".BlockPanel." + index + ".Open");
CuiHelper.AddUi(player, container);
LogAction(null, $"---------------------------------");
LogAction(player, $"Запрос на получение предмета: {id}");
Request($"&item=true&steam_id={player.UserIDString}&id={id}", (i, s) => {
switch (i) {
case 0 : LogAction(player, $"API не ответило на запрос: {id}");
PrintError("Api does not responded to a request");
if (player != null) {
player.ChatMessage($"Непредвиденная ошибка со стороны сервера, просим прощения!");
CuiHelper.DestroyUi(player, StoreLayer);
}
break;
case 200 : Dictionary<string, object> response = JsonConvert.DeserializeObject<Dictionary<string, object>>(s, new KeyValuesConverter());
if (!response.ContainsKey("data")) {
LogAction(player, $"Ошибка получения товара, отсутствует Data [{id}]");
container.Clear();
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel." + index + ".Open");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
FadeIn = 1f, Color = "1 0.5 0.5 0.2", Close = StoreLayer + ".BlockPanel." + index + ".Open", Command = $"UI_GameStoresRUST take {index} {id}", Material = ""
}
, Text = {
Text = "ОШИБКА\nПОЛУЧЕНИЯ", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", Color = "1 0.7 0.7 1", FontSize = 24
}
}
, StoreLayer + ".BlockPanel." + index, StoreLayer + ".BlockPanel." + index + ".Open");
ShowNotify(player, "Произошла непредвиденная ошибка, попробуйте позже!\n" + "Ваш предмет в безопасности, не переживайте!");
CuiHelper.AddUi(player, container);
return;
}
LogAction(player, $"Товар отмечен полученным [{id}]");
Request($"&gived=true&id={id}", (code, newResponse) => {
if (code != 200 || JsonConvert.DeserializeObject<JObject>(newResponse)["result"].ToString() != "success") {
container.Clear();
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel." + index + ".Open");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
FadeIn = 1f, Color = "1 0.5 0.5 0.2", Close = StoreLayer + ".BlockPanel." + index + ".Open", Command = $"UI_GameStoresRUST take {index} {id}", Material = ""
}
, Text = {
Text = "ОШИБКА\nПОЛУЧЕНИЯ", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", Color = "1 0.7 0.7 1", FontSize = 24
}
}
, StoreLayer + ".BlockPanel." + index, StoreLayer + ".BlockPanel." + index + ".Open");
ShowNotify(player, "Произошла непредвиденная ошибка, попробуйте позже!\n" + "Ваш предмет в безопасности, не переживайте!");
CuiHelper.AddUi(player, container);
return;
}
ProcessTake(player, response["data"] as Dictionary<string, object>);
}
, player);
container.Clear();
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel." + index + ".Open");
container.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
FadeIn = 1f, Color = "0.5 1 0.5 0.2", Material = ""
}
, Text = {
Text = "УСПЕШНО\nПОЛУЧЕНО", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-bold.ttf", Color = "0.7 1 0.7 1", FontSize = 14
}
}
, StoreLayer + ".BlockPanel." + index, StoreLayer + ".BlockPanel." + index + ".Open");
if (playersBasketCache.ContainsKey(player.userID) && playersBasketCache[player.userID].Contains(id)) playersBasketCache[player.userID].RemoveAt(playersBasketCache[player.userID].IndexOf(id));
CuiHelper.AddUi(player, container);
break;
case 404 : LogAction(player, $"Сайт не ответил на запрос: {id}");
player.ChatMessage($"Непредвиденная ошибка со стороны сервера, просим прощения!");
CuiHelper.DestroyUi(player, StoreLayer);
LogAction(null, "Response code: 404, please check your configurations", true);
break;
}
}
, player);
break;
}
}
}
#endregion
#region Interface
private static string StoreLayer = "UI_GameStoresRUST_Store";
private void InitializeStore(BasePlayer player, int page, bool first = true) {
CuiElementContainer container = new CuiElementContainer();
if (first) {
CuiHelper.DestroyUi(player, StoreLayer);
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0.289 0", AnchorMax = "0.945 1", OffsetMax = "0 0"
}
, Image = {
Color = "0.117 0.121 0.109 0.95"
}
}
, "Menu_UI", StoreLayer);
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0.04 0.84", AnchorMax = "0.96 0.97", OffsetMax = "0 0"
}
, Text = {
Text = $"<size=25><b>Корзина сервера</b></size>\nЭто ваша корзина с покупками, вы можете забрать их в любой момент.", Color = "1 1 1 0.5", Align = TextAnchor.MiddleCenter, FontSize = 12, Font = "robotocondensed-regular.ttf"
}
}
, StoreLayer);
}
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel");
container.Add(new CuiPanel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 0.9", OffsetMax = "0 0"
}
, Image = {
Color = "0 0 0 0"
}
}
, StoreLayer, StoreLayer + ".BlockPanel");
container.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1.1", OffsetMax = "0 0"
}
, Text = {
Text = "Подождите, мы обрабатываем ваш запрос...", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 20
}
}
, StoreLayer + ".BlockPanel", StoreLayer + ".BlockPanel.Text");
CuiHelper.AddUi(player, container);
Request($"&method=basket&steam_id={player.UserIDString}", (code, response) => {
switch (code) {
default : {
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel.Text");
CuiElementContainer secondContainer = new CuiElementContainer();
secondContainer.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Text = {
Text = "Корзина временно недоступна, попробуйте позже", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 38
}
}
, StoreLayer + ".BlockPanel", StoreLayer + ".BlockPanel.Text");
CuiHelper.AddUi(player, secondContainer);
break;
}
case 200 : {
var firstInfo = JsonConvert.DeserializeObject<Dictionary<string, object>>(response, new KeyValuesConverter());
if (firstInfo.ContainsKey("result")) {
if (firstInfo["result"].ToString() == "fail") {
if (firstInfo["code"].ToString() == "104") {
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel.Text");
CuiElementContainer secondContainer = new CuiElementContainer();
secondContainer.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Text = {
Text = "Ваша корзина пуста", Color = "1 1 1 0.5", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 34
}
}
, StoreLayer + ".BlockPanel", StoreLayer + ".BlockPanel.Text");
CuiHelper.AddUi(player, secondContainer);
}
if (firstInfo["code"].ToString() == "105") {
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel.Text");
CuiElementContainer secondContainer = new CuiElementContainer();
secondContainer.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0.1", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Text = {
Text = "Вы не авторизованы в магазине!\n" + "Ссылку на авторизацию вы можете найти в разделе 'помощь'", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 34
}
}
, StoreLayer + ".BlockPanel", StoreLayer + ".BlockPanel.Text");
CuiHelper.AddUi(player, secondContainer);
}
}
else {
CuiElementContainer secondContainer = new CuiElementContainer();
if (!(firstInfo["data"] is List<object>)) {
PrintError("Unkown error #1");
CuiHelper.DestroyUi(player, StoreLayer);
return;
}
List<object> data = firstInfo["data"] as List<object>;
List<WItem> wItems = new List<WItem>();
foreach (var check in data.Skip(page * Settings.InterfaceSettings.ItemOnString * Settings.InterfaceSettings.StringAmount).Take(Settings.InterfaceSettings.ItemOnString * Settings.InterfaceSettings.StringAmount)) {
wItems.Add(new WItem(check as Dictionary<string, object>));
}
if (playersBasketCache.ContainsKey(player.userID)) playersBasketCache[player.userID].Clear();
foreach (Dictionary<string, object> product in data) {
if (product.ContainsKey("id")) {
if (!playersBasketCache.ContainsKey(player.userID)) playersBasketCache.Add(player.userID, new List<int>());
playersBasketCache[player.userID].Add(Convert.ToInt32(product["id"]));
}
}
secondContainer.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0.02", AnchorMax = "1 0.13", OffsetMax = "0 0"
}
, Text = {
Text = (page + 1).ToString(), Align = TextAnchor.MiddleCenter, FontSize = 34
}
}
, StoreLayer + ".BlockPanel");
secondContainer.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.37 0.02", AnchorMax = "0.47 0.13", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Material = "", Command = page > 0 ? $"UI_GameStoresRUST page {page - 1}" : ""
}
, Text = {
Text = "<", Color = page > 0 ? "1 1 1 1" : "1 1 1 0.2", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 35
}
}
, StoreLayer + ".BlockPanel");
secondContainer.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.53 0.02", AnchorMax = "0.63 0.13", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Material = "", Command = (page + 1) * Settings.InterfaceSettings.ItemOnString * Settings.InterfaceSettings.StringAmount < data.Count ? $"UI_GameStoresRUST page {page + 1}" : ""
}
, Text = {
Text = ">", Color = (page + 1) * Settings.InterfaceSettings.ItemOnString * Settings.InterfaceSettings.StringAmount < data.Count ? "1 1 1 1" : "1 1 1 0.2", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 35
}
}
, StoreLayer + ".BlockPanel");
double xSwitch = 0;
double ySwitch = 0;
for (int i = 0; i < Settings.InterfaceSettings.ItemOnString * Settings.InterfaceSettings.StringAmount; i++) {
UI_RecountPosition(ref xSwitch, ref ySwitch, i, Settings.InterfaceSettings.ItemOnString * Settings.InterfaceSettings.StringAmount);
secondContainer.Add(new CuiButton {
RectTransform = {
AnchorMin = "0.495 0.55", AnchorMax = "0.495 0.55", OffsetMin = $"{xSwitch} {ySwitch - Settings.InterfaceSettings.ItemSide}", OffsetMax = $"{xSwitch + Settings.InterfaceSettings.ItemSide} {ySwitch}"
}
, Button = {
Color = "1 1 1 0.1", Command = $""
}
, Text = {
Text = ""
}
}
, StoreLayer + ".BlockPanel", StoreLayer + $".BlockPanel.{i}");
}
foreach (var check in wItems.Select((i, t) => new {
A = i, B = t
}
)) {
if (check.A.IsBlueprint) {
if (plugins.Find("ImageLibrary") != null) {
secondContainer.Add(new CuiElement {
Parent = StoreLayer + ".BlockPanel." + check.B, Components = {
new CuiRawImageComponent {
Png = (string) plugins.Find("ImageLibrary").Call("GetImage", "blueprintbase")
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 5", OffsetMax = "-5 -5"
}
,
}
}
);
}
else {
secondContainer.Add(new CuiElement {
Parent = StoreLayer + ".BlockPanel." + check.B, Components = {
new CuiRawImageComponent {
Url = "https://gamestores.ru/img/games/rust/blueprintbase.png"
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 5", OffsetMax = "-5 -5"
}
,
}
}
);
}
}
if (!check.A.ImageUrl.Contains("http")) {
secondContainer.Add(new CuiElement {
Parent = StoreLayer + ".BlockPanel." + check.B, Components = {
new CuiRawImageComponent {
Png = check.A.ImageUrl
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 5", OffsetMax = "-5 -5"
}
,
}
}
);
}
else {
secondContainer.Add(new CuiElement {
Parent = StoreLayer + ".BlockPanel." + check.B, Components = {
new CuiRawImageComponent {
Url = check.A.ImageUrl
}
, new CuiRectTransformComponent {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "5 5", OffsetMax = "-5 -5"
}
,
}
}
);
}
if (check.A.Amount > 1) {
secondContainer.Add(new CuiLabel {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "0 5", OffsetMax = "-5 0"
}
, Text = {
Text = "x" + check.A.Amount, Color = "1 1 1 0.5", Align = TextAnchor.LowerRight, Font = "robotocondensed-regular.ttf", FontSize = 12
}
}
, StoreLayer + ".BlockPanel." + check.B);
}
if (check.A.Blocked) {
double left = check.A.Block_Date - CurrentTime();
secondContainer.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "1 0.5 0.5 0.2", Command = $"UI_GameStoresRUST take {check.B} {check.A.ID} blocked {left}"
}
, Text = {
Text = "", Align = TextAnchor.MiddleCenter, Font = "robotocondensed-regular.ttf", FontSize = 38
}
}
, StoreLayer + ".BlockPanel." + check.B, StoreLayer + ".BlockPanel." + check.B + ".Open");
}
else {
secondContainer.Add(new CuiButton {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0"
}
, Button = {
Color = "0 0 0 0", Close = StoreLayer + ".BlockPanel." + check.B + ".Open", Command = $"UI_GameStoresRUST take {check.B} {check.A.ID}"
}
, Text = {
Text = ""
}
}
, StoreLayer + ".BlockPanel." + check.B, StoreLayer + ".BlockPanel." + check.B + ".Open");
}
}
CuiHelper.AddUi(player, secondContainer);
CuiHelper.DestroyUi(player, StoreLayer + ".BlockPanel.Text");
}
}
break;
}
}
}
, player);
}
#endregion
#region Utils
private void ShowNotify(BasePlayer player, string text) {
CuiHelper.DestroyUi(player, StoreLay
// ... [Code preview truncated due to length. Full source in attached file] ...