C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Shop", "Mevent", "1.0.26")]
public class Shop : RustPlugin
{
#region Fields
[PluginReference]
private Plugin ImageLibrary, ItemCostCalculator, HumanNPC, Notify, UINotify, NoEscape, Duel, Duelist;
private static Shop _instance;
private readonly Dictionary<int, ShopItem> _shopItems = new Dictionary<int, ShopItem>();
private readonly Dictionary<BasePlayer, Coroutine> _coroutines = new Dictionary<BasePlayer, Coroutine>();
private readonly Dictionary<string, List<string>> _itemsCategories =
new Dictionary<string, List<string>>();
private readonly List<string> _images = new List<string>();
private const string Layer = "UI.Shop";
private const string ModalLayer = "UI.Shop.Modal";
private const string EditingLayer = "UI.Shop.Editing";
private const string PermAdmin = "Shop.admin";
private readonly Dictionary<ulong, DataCart> _carts = new Dictionary<ulong, DataCart>();
private class DataCart
{
public readonly Dictionary<ShopItem, int> Items = new Dictionary<ShopItem, int>();
public void AddItem(ShopItem item)
{
if (Items.ContainsKey(item))
Items[item]++;
else
Items.Add(item, 1);
}
public void RemoveItem(ShopItem item)
{
Items.Remove(item);
}
public void ChangeAmountItem(ShopItem item, int amount)
{
if (amount > 0)
Items[item] = amount;
else
Items.Remove(item);
}
public int GetAmount()
{
return Items.Sum(x => x.Key.Amount * x.Value);
}
public double GetPrice(BasePlayer player)
{
return Items.Sum(x => x.Key.GetPrice(player) * x.Value);
}
public int GetTotalAmount()
{
return (from check in Items
let shopItem = check.Key
where shopItem.Type == ItemType.Item && shopItem.Definition != null
select shopItem.GetStacks(shopItem.Definition, shopItem.Amount * check.Value).Count).Sum();
}
#region Data
public PlayerCart ToPlayerCart()
{
return new PlayerCart
{
Items = Items.ToDictionary(x => x.Key.ID, y => y.Value)
};
}
public DataCart()
{
}
public DataCart(PlayerCart cart)
{
Items = cart.Items.ToDictionary(x => _instance.FindItemById(x.Key), y => y.Value);
}
#endregion
}
private readonly Dictionary<BasePlayer, NPCShop> _openedShops = new Dictionary<BasePlayer, NPCShop>();
private NPCShop GetShopByPlayer(BasePlayer player)
{
NPCShop shop;
return _openedShops.TryGetValue(player, out shop) ? shop : null;
}
private readonly Dictionary<BasePlayer, Dictionary<string, object>> _itemEditing =
new Dictionary<BasePlayer, Dictionary<string, object>>();
#endregion
#region Colors
private string _firstColor;
private string _secondColor;
private string _thirdColor;
private string _fourthColor;
private string _fifthColor;
private string _sixthColor;
private string _seventhColor;
#endregion
#region Config
private Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public string[] Commands = { "shop", "shops" };
[JsonProperty(PropertyName = "Load images when logging into the server?")]
public bool LoginImages = true;
[JsonProperty(PropertyName = "Work with Notify?")]
public bool UseNotify = true;
[JsonProperty(PropertyName = "Can admins edit? (by flag)")]
public bool FlagAdmin = true;
[JsonProperty(PropertyName = "Block (NoEscape)")]
public bool BlockNoEscape;
[JsonProperty(PropertyName = "Blocking the opening in duels?")]
public bool UseDuels;
[JsonProperty(PropertyName = "Delay between loading images")]
public float ImagesDelay = 1f;
[JsonProperty(PropertyName = "Economy")]
public EconomyConf Economy = new EconomyConf
{
Type = EconomyType.Plugin,
AddHook = "Deposit",
BalanceHook = "Balance",
RemoveHook = "Withdraw",
Plug = "Economics",
ShortName = "scrap",
DisplayName = string.Empty,
Skin = 0
};
[JsonProperty(PropertyName = "Shop", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ShopCategory> Shop = new List<ShopCategory>();
[JsonProperty(PropertyName = "First Color")]
public string FirstColor = "#161617";
[JsonProperty(PropertyName = "Second Color")]
public string SecondColor = "#4B68FF";
[JsonProperty(PropertyName = "Third Color")]
public string ThirdColor = "#0E0E10";
[JsonProperty(PropertyName = "Fourth Color")]
public string FourthColor = "#A0A935";
[JsonProperty(PropertyName = "Fifth Color")]
public string FifthColor = "#FF4B4B";
[JsonProperty(PropertyName = "Sixth Color")]
public string SixthColor = "#324192";
[JsonProperty(PropertyName = "Seventh Color")]
public string SeventhColor = "#CD3838";
[JsonProperty(PropertyName = "NPC Shops (NPC ID - shop categories)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, NPCShop> NPCs = new Dictionary<string, NPCShop>
{
["1234567"] = new NPCShop
{
Shops = new List<string>
{
"Tool",
"Food"
}
},
["7654321"] = new NPCShop
{
Shops = new List<string>
{
"Weapon",
"Ammunition"
}
},
["4644687478"] = new NPCShop
{
Shops = new List<string>
{
"*"
}
}
};
[JsonProperty(PropertyName = "Interface")]
public UserInterface UI = new UserInterface
{
DisplayType = "Menu",
Width = 770,
Height = 500,
CategoriesOnString = 9,
CategoriesMargin = 7.5f,
CategoriesHeight = 40,
ItemsOnString = 4,
Strings = 2,
ItemWidth = 150,
ItemHeight = 165,
Margin = 35,
UseScrollCategories = true,
EnableSearch = true,
RoundDigits = 5
};
[JsonProperty(PropertyName = "Blocked skins for sell",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, List<ulong>> BlockedSkins = new Dictionary<string, List<ulong>>
{
["short name"] = new List<ulong>
{
52,
25
},
["short name 2"] = new List<ulong>
{
52,
25
}
};
public VersionNumber Version;
}
private class UserInterface
{
[JsonProperty(PropertyName = "Display type (Overlay/Hud)")]
public string DisplayType;
[JsonProperty(PropertyName = "Height")]
public float Height;
[JsonProperty(PropertyName = "Width")] public float Width;
[JsonProperty(PropertyName = "Categories On Page")]
public int CategoriesOnString;
[JsonProperty(PropertyName = "Categories Margin")]
public float CategoriesMargin;
[JsonProperty(PropertyName = "Categories Height")]
public float CategoriesHeight;
[JsonProperty(PropertyName = "Items On String")]
public int ItemsOnString;
[JsonProperty(PropertyName = "Strings")]
public int Strings;
[JsonProperty(PropertyName = "Item Height")]
public float ItemHeight;
[JsonProperty(PropertyName = "Item Width")]
public float ItemWidth;
[JsonProperty(PropertyName = "Margin")]
public float Margin;
[JsonProperty(PropertyName = "Use scroll in categories?")]
public bool UseScrollCategories;
[JsonProperty(PropertyName = "Enable search?")]
public bool EnableSearch;
[JsonProperty(PropertyName = "Number of digits after decimal point for rounding prices")]
public int RoundDigits;
}
private class NPCShop
{
[JsonProperty(PropertyName = "Categories (Titles) [* - all]",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> Shops;
}
private class ShopCategory
{
[JsonProperty(PropertyName = "Enabled")]
public bool Enabled;
[JsonProperty(PropertyName = "Title")] public string Title;
[JsonProperty(PropertyName = "Permission")]
public string Permission;
[JsonProperty(PropertyName = "Items", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<ShopItem> Items;
}
private enum ItemType
{
Item,
Command,
Plugin,
Kit
}
private class ShopItem
{
[JsonProperty(PropertyName = "Type")] [JsonConverter(typeof(StringEnumConverter))]
public ItemType Type;
[JsonProperty(PropertyName = "ID")] public int ID;
[JsonProperty(PropertyName = "Image")] public string Image;
[JsonProperty(PropertyName = "Title")] public string Title;
[JsonProperty(PropertyName = "Description")]
public string Description;
[JsonProperty(PropertyName = "Command (%steamid%)")]
public string Command;
[JsonProperty(PropertyName = "Kit")] public string Kit;
[JsonProperty(PropertyName = "Plugin")]
public PluginItem Plugin;
[JsonProperty(PropertyName = "DisplayName (empty - default)")]
public string DisplayName;
[JsonProperty(PropertyName = "ShortName")]
public string ShortName;
[JsonProperty(PropertyName = "Skin")] public ulong Skin;
[JsonProperty(PropertyName = "Amount")]
public int Amount;
[JsonProperty(PropertyName = "Price")] public double Price;
[JsonProperty(PropertyName = "Sell Price")]
public double SellPrice;
[JsonProperty(PropertyName = "Buy Cooldown (0 - disable)")]
public float BuyCooldown;
[JsonProperty(PropertyName = "Sell Cooldown (0 - disable)")]
public float SellCooldown;
[JsonProperty(PropertyName = "Discount (%)", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> Discount = new Dictionary<string, int>();
[JsonProperty(PropertyName = "Sell Limits (0 - no limit)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> SellLimits = new Dictionary<string, int>();
[JsonProperty(PropertyName = "Buy Limits (0 - no limit)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> BuyLimits = new Dictionary<string, int>();
[JsonProperty(PropertyName = "Max Buy Amount (0 - disable)")]
public int BuyMaxAmount;
[JsonProperty(PropertyName = "Max Sell Amount (0 - disable)")]
public int SellMaxAmount;
[JsonIgnore] private string _publicTitle;
[JsonIgnore]
public string PublicTitle
{
get
{
if (string.IsNullOrEmpty(_publicTitle))
_publicTitle = GetName();
return _publicTitle;
}
}
private string GetName()
{
if (!string.IsNullOrEmpty(Title))
return Title;
if (!string.IsNullOrEmpty(DisplayName))
return DisplayName;
var def = ItemManager.FindItemDefinition(ShortName);
if (!string.IsNullOrEmpty(ShortName) && def != null)
return def.displayName.translated;
return string.Empty;
}
[JsonIgnore] public ItemDefinition Definition;
public Dictionary<string, object> ToDictionary()
{
return new Dictionary<string, object>
{
["Generated"] = false,
["ID"] = ID,
["Type"] = Type,
["Image"] = Image,
["Title"] = Title,
["Command"] = Command,
["DisplayName"] = DisplayName,
["ShortName"] = ShortName,
["Skin"] = Skin,
["Amount"] = Amount,
["Price"] = Price,
["SellPrice"] = SellPrice,
["Plugin_Hook"] = Plugin.Hook,
["Plugin_Name"] = Plugin.Plugin,
["Plugin_Amount"] = Plugin.Amount
};
}
public ShopItem()
{
}
public ShopItem(Dictionary<string, object> dictionary)
{
ID = (int)dictionary["ID"];
Type = (ItemType)dictionary["Type"];
Image = (string)dictionary["Image"];
Title = (string)dictionary["Title"];
Command = (string)dictionary["Command"];
DisplayName = (string)dictionary["DisplayName"];
ShortName = (string)dictionary["ShortName"];
Skin = (ulong)dictionary["Skin"];
Amount = (int)dictionary["Amount"];
Price = (double)dictionary["Price"];
SellPrice = (double)dictionary["SellPrice"];
Plugin = new PluginItem
{
Hook = (string)dictionary["Plugin_Hook"],
Plugin = (string)dictionary["Plugin_Name"],
Amount = (int)dictionary["Plugin_Amount"]
};
Discount = new Dictionary<string, int>();
}
public double GetPrice(BasePlayer player)
{
var discount = GetDiscount(player);
var price = Price;
return Math.Round(discount != 0 ? price * (1f - discount / 100f) : price,
_instance._config.UI.RoundDigits);
}
public int GetDiscount(BasePlayer player)
{
return (from check in Discount
where _instance.permission.UserHasPermission(player.UserIDString, check.Key)
select check.Value).Prepend(0).Max();
}
public int GetLimit(BasePlayer player, bool buy = true)
{
var dict = buy ? BuyLimits : SellLimits;
if (dict.Count == 0)
return 0;
return (from check in dict
where _instance.permission.UserHasPermission(player.UserIDString, check.Key)
select check.Value).Prepend(0).Max();
}
public void Get(BasePlayer player, int count = 1)
{
switch (Type)
{
case ItemType.Item:
ToItem(player, count);
break;
case ItemType.Command:
ToCommand(player, count);
break;
case ItemType.Plugin:
Plugin.Get(player, count);
break;
case ItemType.Kit:
ToKit(player, count);
break;
}
}
private void ToKit(BasePlayer player, int count)
{
if (string.IsNullOrEmpty(Kit)) return;
for (var i = 0; i < count; i++)
Interface.Oxide.CallHook("GiveKit", player, Kit);
}
private void ToItem(BasePlayer player, int count)
{
var def = ItemManager.FindItemDefinition(ShortName);
if (def == null)
{
Debug.LogError($"Error creating item with ShortName '{ShortName}'");
return;
}
GetStacks(def, Amount * count)?.ForEach(stack =>
{
var newItem = ItemManager.Create(def, stack, Skin);
if (newItem == null)
{
_instance?.PrintError($"Error creating item with ShortName '{ShortName}'");
return;
}
if (!string.IsNullOrEmpty(DisplayName)) newItem.name = DisplayName;
player.GiveItem(newItem, BaseEntity.GiveItemReason.PickedUp);
});
}
private void ToCommand(BasePlayer player, int count)
{
for (var i = 0; i < count; i++)
{
var command = Command.Replace("\n", "|").Replace("%steamid%", player.UserIDString, StringComparison.OrdinalIgnoreCase).Replace(
"%username%",
player.displayName, StringComparison.OrdinalIgnoreCase);
foreach (var check in command.Split('|')) _instance?.Server.Command(check);
}
}
public List<int> GetStacks(ItemDefinition item, int amount)
{
var list = new List<int>();
var maxStack = item.stackable;
if (maxStack == 0) maxStack = 1;
while (amount > maxStack)
{
amount -= maxStack;
list.Add(maxStack);
}
list.Add(amount);
return list;
}
}
private class PluginItem
{
[JsonProperty(PropertyName = "Hook")] public string Hook;
[JsonProperty(PropertyName = "Plugin Name")]
public string Plugin;
[JsonProperty(PropertyName = "Amount")]
public int Amount;
public void Get(BasePlayer player, int count = 1)
{
var plug = _instance?.plugins.Find(Plugin);
if (plug == null)
{
_instance?.PrintError($"Plugin '{Plugin}' not found !!! ");
return;
}
switch (Plugin)
{
case "Economics":
{
plug.Call(Hook, player.userID, (double)Amount * count);
break;
}
default:
{
plug.Call(Hook, player.userID, Amount * count);
break;
}
}
}
}
private enum EconomyType
{
Plugin,
Item
}
private class EconomyConf
{
[JsonProperty(PropertyName = "Type (Plugin/Item)")] [JsonConverter(typeof(StringEnumConverter))]
public EconomyType Type;
[JsonProperty(PropertyName = "Plugin name")]
public string Plug;
[JsonProperty(PropertyName = "Balance add hook")]
public string AddHook;
[JsonProperty(PropertyName = "Balance remove hook")]
public string RemoveHook;
[JsonProperty(PropertyName = "Balance show hook")]
public string BalanceHook;
[JsonProperty(PropertyName = "ShortName")]
public string ShortName;
[JsonProperty(PropertyName = "Display Name (empty - default)")]
public string DisplayName;
[JsonProperty(PropertyName = "Skin")] public ulong Skin;
public double ShowBalance(BasePlayer player)
{
switch (Type)
{
case EconomyType.Plugin:
{
var plugin = _instance?.plugins?.Find(Plug);
if (plugin == null) return 0;
return Math.Round(Convert.ToDouble(plugin.Call(BalanceHook, player.userID)));
}
case EconomyType.Item:
{
return ItemCount(player.inventory.AllItems(), ShortName, Skin);
}
default:
return 0;
}
}
public void AddBalance(BasePlayer player, double amount)
{
switch (Type)
{
case EconomyType.Plugin:
{
var plugin = _instance?.plugins?.Find(Plug);
if (plugin == null) return;
switch (Plug)
{
case "BankSystem":
case "ServerRewards":
plugin.Call(AddHook, player.userID, (int)amount);
break;
default:
plugin.Call(AddHook, player.userID, amount);
break;
}
break;
}
case EconomyType.Item:
{
var am = (int)amount;
var item = ToItem(am);
if (item == null) return;
player.GiveItem(item);
break;
}
}
}
public bool RemoveBalance(BasePlayer player, double amount)
{
switch (Type)
{
case EconomyType.Plugin:
{
if (ShowBalance(player) < amount) return false;
var plugin = _instance?.plugins.Find(Plug);
if (plugin == null) return false;
switch (Plug)
{
case "BankSystem":
case "ServerRewards":
plugin.Call(RemoveHook, player.userID, (int)amount);
break;
default:
plugin.Call(RemoveHook, player.userID, amount);
break;
}
return true;
}
case EconomyType.Item:
{
var playerItems = player.inventory.AllItems();
var am = (int)amount;
if (ItemCount(playerItems, ShortName, Skin) < am) return false;
Take(playerItems, ShortName, Skin, am);
return true;
}
default:
return false;
}
}
private Item ToItem(int amount)
{
var item = ItemManager.CreateByName(ShortName, amount, Skin);
if (item == null)
{
Debug.LogError($"Error creating item with ShortName: '{ShortName}'");
return null;
}
if (!string.IsNullOrEmpty(DisplayName)) item.name = DisplayName;
return item;
}
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<Configuration>();
if (_config == null) throw new Exception();
if (_config.Version < Version)
UpdateConfigValues();
SaveConfig();
}
catch
{
PrintError("Your configuration file contains an error.Using default configuration values.");
LoadDefaultConfig();
}
}
protected override void SaveConfig()
{
Config.WriteObject(_config);
}
protected override void LoadDefaultConfig()
{
_config = new Configuration();
}
private void UpdateConfigValues()
{
PrintWarning("Config update detected! Updating config values...");
var baseConfig = new Configuration();
if (_config.Version == default(VersionNumber) && _config.Version < new VersionNumber(1, 0, 21))
{
_data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>(Name);
if (_data != null)
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/Players", _data);
}
if (_config.Version < new VersionNumber(1, 0, 21))
_config.Shop.ForEach(shop =>
{
shop.Items.ForEach(item =>
{
item.SellLimits = new Dictionary<string, int>
{
["shop.default"] = 0,
["shop.vip"] = 0
};
item.BuyLimits = new Dictionary<string, int>
{
["shop.default"] = 0,
["shop.vip"] = 0
};
});
});
if (_config.Version < new VersionNumber(1, 0, 24)) _config.UI.DisplayType = baseConfig.UI.DisplayType;
_config.Version = Version;
PrintWarning("Config update completed!");
}
#endregion
#region Data
private PluginData _data;
private void SaveData()
{
SavePlayers();
SaveCooldown();
SaveLimits();
}
private void SavePlayers()
{
_data.PlayerCarts.Clear();
foreach (var check in _carts)
_data.PlayerCarts.Add(check.Key, check.Value.ToPlayerCart());
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/Players", _data);
}
private void SaveCooldown()
{
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/Cooldown", _cooldown);
}
private void SaveLimits()
{
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/Limits", _limits);
}
private void LoadData()
{
try
{
_data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>($"{Name}/Players");
_cooldown = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, Cooldown>>($"{Name}/Cooldown");
_limits = Interface.Oxide.DataFileSystem.ReadObject<PlayerLimits>($"{Name}/Limits");
}
catch (Exception e)
{
PrintError(e.ToString());
}
if (_data == null) _data = new PluginData();
if (_cooldown == null) _cooldown = new Dictionary<ulong, Cooldown>();
if (_limits == null) _limits = new PlayerLimits();
}
private class PluginData
{
[JsonProperty(PropertyName = "Players", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<ulong, PlayerCart> PlayerCarts = new Dictionary<ulong, PlayerCart>();
}
private class PlayerCart
{
[JsonProperty(PropertyName = "Items", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<int, int> Items = new Dictionary<int, int>();
}
#endregion
#region Hooks
private void Init()
{
_instance = this;
LoadData();
if (!_config.LoginImages)
Unsubscribe(nameof(OnPlayerConnected));
_firstColor = HexToCuiColor(_config.FirstColor);
_secondColor = HexToCuiColor(_config.SecondColor);
_thirdColor = HexToCuiColor(_config.ThirdColor);
_fourthColor = HexToCuiColor(_config.FourthColor);
_fifthColor = HexToCuiColor(_config.FifthColor);
_sixthColor = HexToCuiColor(_config.SixthColor);
_seventhColor = HexToCuiColor(_config.SeventhColor);
}
private void OnServerInitialized()
{
if (_config.Shop.Count == 0)
FillCategories();
LoadImages();
_config.Shop.ForEach(category =>
{
if (!string.IsNullOrEmpty(category.Permission) && !permission.PermissionExists(category.Permission))
permission.RegisterPermission(category.Permission, this);
});
if (!permission.PermissionExists(PermAdmin))
permission.RegisterPermission(PermAdmin, this);
CheckOnDuplicates();
ItemsToDict();
foreach (var image in _shopItems.Values.Select(shopItem => !string.IsNullOrEmpty(shopItem.Image) ? shopItem.Image : shopItem.ShortName).Where(image => !_images.Contains(image))) _images.Add(image);
foreach (var check in _data.PlayerCarts)
_carts.Add(check.Key, new DataCart(check.Value));
if (_config.LoginImages)
foreach (var player in BasePlayer.activePlayerList)
OnPlayerConnected(player);
AddCovalenceCommand(_config.Commands, nameof(CmdShopOpen));
if (_shopItems.Any(x => x.Value.BuyCooldown > 0 || x.Value.SellCooldown > 0))
timer.Every(1, ItemsUpdateController);
}
private void Unload()
{
foreach (var player in BasePlayer.activePlayerList)
{
CuiHelper.DestroyUi(player, Layer);
CuiHelper.DestroyUi(player, ModalLayer);
CuiHelper.DestroyUi(player, EditingLayer);
OnPlayerDisconnected(player);
}
SaveData();
_instance = null;
}
private void OnPlayerConnected(BasePlayer player)
{
if (player == null) return;
var coroutine = ServerMgr.Instance.StartCoroutine(LoadImages(player));
if (_coroutines.ContainsKey(player))
_coroutines[player] = coroutine;
else
_coroutines.Add(player, coroutine);
}
private void OnPlayerDisconnected(BasePlayer player)
{
if (player == null) return;
_itemsToUpdate.Remove(player);
if (_itemEditing.ContainsKey(player)) _itemEditing.Remove(player);
if (_coroutines.ContainsKey(player))
{
var coroutine = _coroutines[player];
if (coroutine != null)
ServerMgr.Instance.StopCoroutine(coroutine);
}
}
private void OnUseNPC(BasePlayer npc, BasePlayer player)
{
if (npc == null || player == null) return;
NPCShop npcShop;
if (!_config.NPCs.TryGetValue(npc.UserIDString, out npcShop) || npcShop == null) return;
_openedShops[player] = npcShop;
MainUi(player, npcShop: npcShop, first: true);
}
#endregion
#region Commands
private void CmdShopOpen(IPlayer cov, string command, string[] args)
{
var player = cov?.Object as BasePlayer;
if (player == null) return;
if (_config.UseDuels && InDuel(player))
{
SendNotify(player, NoUseDuel, 1);
return;
}
MainUi(player, first: true);
}
[ConsoleCommand("UI_Shop")]
private void CmdConsoleShop(ConsoleSystem.Arg arg)
{
var player = arg?.Player();
if (player == null || !arg.HasArgs()) return;
switch (arg.Args[0])
{
case "closeui":
{
_itemsToUpdate.Remove(player);
_openedShops.Remove(player);
break;
}
case "main_page":
{
int catPage, page;
if (!arg.HasArgs(3) || !int.TryParse(arg.Args[1], out catPage) ||
!int.TryParse(arg.Args[2], out page)) return;
var search = string.Empty;
if (arg.HasArgs(4)) search = string.Join(" ", arg.Args.Skip(3));
if (string.IsNullOrEmpty(search) && catPage == -1)
catPage = 0;
MainUi(player, catPage, page, GetShopByPlayer(player), search);
break;
}
case "buyitem":
{
int id;
if (!arg.HasArgs(2) ||
!int.TryParse(arg.Args[1], out id)) return;
var shopItem = FindItemById(id);
if (shopItem == null) return;
var playerCart = GetPlayerCart(player);
if (playerCart == null) return;
playerCart.AddItem(shopItem);
var cooldownTime = GetCooldownTime(player.userID, shopItem, true);
if (cooldownTime > 0)
{
SendNotify(player, BuyCooldownMessage, 1, shopItem.PublicTitle,
FormatShortTime(player, TimeSpan.FromSeconds(cooldownTime)));
return;
}
var container = new CuiElementContainer();
RefreshCart(ref container, player, playerCart);
CuiHelper.AddUi(player, container);
break;
}
case "changeicat":
{
int catPage, iCategory;
if (!arg.HasArgs(3) || !int.TryParse(arg.Args[1], out catPage) ||
!int.TryParse(arg.Args[2], out iCategory)) return;
var container = new CuiElementContainer();
RefreshCategories(ref container, player, GetCategories(player, GetShopByPlayer(player)), catPage,
iCategory);
CuiHelper.AddUi(player, container);
break;
}
case "gocat":
{
int catPage, iCategory;
if (!arg.HasArgs(3) || !int.TryParse(arg.Args[1], out catPage) ||
!int.TryParse(arg.Args[2], out iCategory)) return;
MainUi(player, catPage, npcShop: GetShopByPlayer(player));
var container = new CuiElementContainer();
RefreshCategories(ref container, player, GetCategories(player, GetShopByPlayer(player)), catPage,
iCategory);
CuiHelper.AddUi(player, container);
break;
}
case "cart_page":
{
int page;
if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out page)) return;
var playerCart = GetPlayerCart(player);
if (playerCart == null) return;
var container = new CuiElementContainer();
RefreshCart(ref container, player, playerCart, page);
CuiHelper.AddUi(player, container);
break;
}
case "cart_item_remove":
{
int id;
if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out id)) return;
var shopItem = FindItemById(id);
if (shopItem == null) return;
var playerCart = GetPlayerCart(player);
if (playerCart == null) return;
playerCart.RemoveItem(shopItem);
var container = new CuiElementContainer();
RefreshCart(ref container, player, playerCart);
CuiHelper.AddUi(player, container);
break;
}
case "cart_item_change":
{
int id, amount;
if (!arg.HasArgs(3) ||
!int.TryParse(arg.Args[1], out id) ||
!int.TryParse(arg.Args[2], out amount)) return;
var shopItem = FindItemById(id);
if (shopItem == null) return;
var playerCart = GetPlayerCart(player);
if (playerCart == null) return;
if (shopItem.BuyMaxAmount > 0 && amount > shopItem.BuyMaxAmount)
amount = shopItem.BuyMaxAmount;
playerCart.ChangeAmountItem(shopItem, amount);
var container = new CuiElementContainer();
RefreshCart(ref container, player, playerCart);
CuiHelper.AddUi(player, container);
break;
}
case "cart_try_buyitems":
{
AcceptBuy(player);
break;
}
case "cart_buyitems":
{
var playerCart = GetPlayerCart(player);
if (playerCart == null) return;
var price = playerCart.GetPrice(player);
if (price <= 0) return;
if (_config.BlockNoEscape && NoEscape != null)
{
var success = NoEscape?.Call("IsBlocked", player);
if (success is bool && (bool)success)
{
ErrorUi(player, Msg(player, BuyRaidBlocked));
return;
}
}
var totalcount = playerCart.GetTotalAmount();
var slots = player.inventory.containerBelt.capacity -
player.inventory.containerBelt.itemList.Count +
(player.inventory.containerMain.capacity -
player.inventory.containerMain.itemList.Count);
if (slots < totalcount)
{
ErrorUi(player, Msg(player, NotEnoughtSpace));
return;
}
if (!_config.Economy.RemoveBalance(player, price))
{
ErrorUi(player, Msg(player, NotMoney));
return;
}
if (playerCart.Items.Any(x =>
{
var limit = GetLimit(player, x.Key, true);
if (limit > 0) return false;
ErrorUi(player, Msg(player, BuyLimitReached, x.Key.PublicTitle));
return true;
}))
return;
foreach (var cartItem in playerCart.Items)
{
cartItem.Key?.Get(player, cartItem.Value);
SetCooldown(player, cartItem.Key, true);
UseLimit(player, cartItem.Key, true);
}
CuiHelper.DestroyUi(player, Layer);
_carts.Remove(player.userID);
_itemsToUpdate.Remove(player);
SendNotify(player, ReceivedItems, 0);
break;
}
case "trysellitem":
{
int itemId;
if (!arg.HasArgs(2) || !int.TryParse(arg.Args[1], out itemId)) return;
var item = FindItemById(itemId);
if (item == null) return;
var amount = 1;
if (arg.HasArgs(3) && !int.TryParse(arg.Args[2], out amount) || amount < 1) return;
if (item.SellMaxAmount > 0 && amount > item.SellMaxAmount) amount = item.SellMaxAmount;
SellUi(player, item, amount);
break;
}
case "sellitem":
{
int itemId, amount;
if (!arg.HasArgs(3) ||
!int.TryParse(arg.Args[1], out itemId) ||
!int.TryParse(arg.Args[2], out amount)) return;
var item = FindItemById(itemId);
if (item == null) return;
var cooldownTime = GetCooldownTime(player.userID, item, false);
if (cooldownTime > 0)
{
ErrorUi(player, Msg(player, SellCooldownMessage));
return;
}
if (_config.BlockNoEscape && NoEscape != null)
{
var success = NoEscape?.Call("IsBlocked", player);
if (success is bool && (bool)success)
{
ErrorUi(player, Msg(player, SellRaidBlocked));
return;
}
}
var limit = GetLimit(player, item, false);
if (limit <= 0)
{
ErrorUi(player, Msg(player, SellLimitReached, item.PublicTitle));
return;
}
List<ulong> blockedSkins;
if (_config.BlockedSkins.TryGetValue(item.ShortName, out blockedSkins))
if (blockedSkins.Contains(item.Skin))
{
ErrorUi(player, Msg(player, SkinBlocked));
return;
}
var totalAmount = item.Amount * amount;
var playerItems = player.inventory.AllItems();
if (ItemCount(playerItems, item.ShortName, item.Skin) < totalAmount)
{
ErrorUi(player, Msg(player, NotEnough));
return;
}
Take(playerItems, item.ShortName, item.Skin, totalAmount);
_config.Economy.AddBalance(player, item.SellPrice * amount);
SetCooldown(player, item, false, true);
UseLimit(player, item, false);
if (_itemsToUpdate.ContainsKey(player))
{
if (!_itemsToUpdate[player].Contains(item))
_itemsToUpdate[player].Add(item);
}
else
{
_itemsToUpdate.Add(player, new List<ShopItem> { item });
}
var container = new CuiElementContainer();
SellButtonUi(player, ref container, item);
BalanceUi(ref container, player);
CuiHelper.AddUi(player, container);
SendNotify(player, SellNotify, 0, totalAmount, item.PublicTitle);
break;
}
case "startedititem":
{
int id, category, page;
if (!IsAdmin(player) || !arg.HasArgs(4) ||
!int.TryParse(arg.Args[1], out category) ||
!int.TryParse(arg.Args[2], out page) ||
!int.TryParse(arg.Args[3], out id)) return;
_itemEditing.Remove(player);
EditUi(player, category, page, id, true);
break;
}
case "edititem":
{
int category, page;
if (!IsAdmin(player) || !arg.HasArgs(5) || !int.TryParse(arg.Args[1], out category) ||
!int.TryParse(arg.Args[2], out page)) return;
// ... [Code preview truncated due to length. Full source in attached file] ...