C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.RegularExpressions;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.ShopExtensionMethods;
using UnityEngine;
using Debug = UnityEngine.Debug;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Shop", "Mevent", "1.1.2")]
public class Shop : RustPlugin
{
#region Fields
[PluginReference] private Plugin
ImageLibrary = null,
ItemCostCalculator = null,
Notify = null,
UINotify = null,
NoEscape = null,
Duel = null,
Duelist = null;
private static Shop _instance;
private bool _enabledImageLibrary;
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<KeyValuePair<int, string>>> _itemsCategories =
new Dictionary<string, List<KeyValuePair<int, string>>>();
private readonly List<string> _images = new List<string>();
private List<ulong> _openedUI = new List<ulong>();
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 const string PermFreeBypass = "Shop.free";
private const string PermSetVM = "Shop.setvm";
private const int _itemsPerTick = 10;
private readonly Dictionary<ulong, DataCart> _carts = new Dictionary<ulong, DataCart>();
private readonly Dictionary<BasePlayer, NPCShop> _openedShops = new Dictionary<BasePlayer, NPCShop>();
private readonly Dictionary<BasePlayer, Dictionary<string, object>> _itemEditing =
new Dictionary<BasePlayer, Dictionary<string, object>>();
private Timer _updateController;
#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 static Configuration _config;
private class Configuration
{
[JsonProperty(PropertyName = "Commands", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public readonly string[] Commands = {"shop", "shops"};
[JsonProperty(PropertyName = "Enable money transfers between players??")]
public readonly bool Transfer = true;
[JsonProperty(PropertyName = "Enable logging to the console?")]
public readonly bool LogToConsole = true;
[JsonProperty(PropertyName = "Enable logging to the file?")]
public readonly bool LogToFile = true;
[JsonProperty(PropertyName = "Load images when logging into the server?")]
public readonly bool LoginImages = true;
[JsonProperty(PropertyName = "Work with Notify?")]
public readonly bool UseNotify = true;
[JsonProperty(PropertyName = "Can admins edit? (by flag)")]
public readonly bool FlagAdmin = true;
[JsonProperty(PropertyName = "Block (NoEscape)")]
public bool BlockNoEscape = false;
[JsonProperty(PropertyName = "Wipe Block")]
public bool WipeCooldown = false;
[JsonProperty(PropertyName = "Wipe Cooldown")]
public float WipeCooldownTimer = 3600;
[JsonProperty(PropertyName = "Respawn Block")]
public bool RespawnCooldown = true;
[JsonProperty(PropertyName = "Respawn Cooldown")]
public float RespawnCooldownTimer = 60;
[JsonProperty(PropertyName = "Blocking the opening in duels?")]
public bool UseDuels = false;
[JsonProperty(PropertyName = "Delay between loading images")]
public readonly float ImagesDelay = 1f;
[JsonProperty(PropertyName = "Economy")]
public readonly EconomyConf Economy = new EconomyConf
{
Type = EconomyType.Plugin,
AddHook = "Deposit",
BalanceHook = "Balance",
RemoveHook = "Withdraw",
Plug = "Economics",
ShortName = "scrap",
DisplayName = string.Empty,
Skin = 0,
TitleLangKey = "LangTitle",
BalanceLangKey = "BalanceTitle"
};
[JsonProperty(PropertyName = "Additional Economics",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<AdditionalEconomy> AdditionalEconomics = new List<AdditionalEconomy>
{
new AdditionalEconomy
{
ID = 1,
Enabled = true,
Type = EconomyType.Plugin,
AddHook = "AddPoints",
BalanceHook = "CheckPoints",
RemoveHook = "TakePoints",
Plug = "ServerRewards",
ShortName = "scrap",
DisplayName = string.Empty,
Skin = 0,
TitleLangKey = "sr_title",
BalanceLangKey = "sr_balance"
}
};
[JsonProperty(PropertyName = "Shop", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public readonly List<ShopCategory> Shop = new List<ShopCategory>();
[JsonProperty(PropertyName = "First Color")]
public readonly string FirstColor = "#161617";
[JsonProperty(PropertyName = "Second Color")]
public readonly string SecondColor = "#4B68FF";
[JsonProperty(PropertyName = "Third Color")]
public readonly string ThirdColor = "#0E0E10";
[JsonProperty(PropertyName = "Fourth Color")]
public readonly string FourthColor = "#A0A935";
[JsonProperty(PropertyName = "Fifth Color")]
public readonly string FifthColor = "#FF4B4B";
[JsonProperty(PropertyName = "Sixth Color")]
public readonly string SixthColor = "#324192";
[JsonProperty(PropertyName = "Seventh Color")]
public readonly string SeventhColor = "#CD3838";
[JsonProperty(PropertyName = "NPC Shops (NPC ID - shop categories)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public readonly 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 readonly UserInterface UI = new UserInterface
{
DisplayType = "Overlay",
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,
SelectCurrency = new SelectCurrencyUI
{
Title = new LabelSettings
{
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-bold.ttf",
FontSize = 14,
Color = new IColor("#FFFFFF")
},
TitlePosition = new InterfacePosition
{
AnchorMin = "0 1", AnchorMax = "1 1",
OffsetMin = "0 -30", OffsetMax = "0 0"
},
EconomyTitle = new LabelSettings
{
Align = TextAnchor.MiddleCenter,
Font = "robotocondensed-regular.ttf",
FontSize = 12,
Color = new IColor("#FFFFFF")
},
SelectedEconomyColor = new IColor("#4B68FF"),
UnselectedEconomyColor = new IColor("#4B68FF", 33),
EconomyWidth = 105f,
EconomyHeight = 25f,
EconomyMargin = 5f,
EconomyIndent = 5f,
FrameWidth = 10,
FrameIndent = 15,
FrameHeader = 35,
CloseAfterChange = true
}
};
[JsonProperty(PropertyName = "Blocked skins for sell",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public readonly 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
}
};
[JsonProperty(PropertyName = "Auto-Wipe Settings")]
public WipeSettings Wipe = new WipeSettings
{
Cooldown = true,
Players = true,
Limits = true
};
[JsonProperty(PropertyName = "Custom Vending Machines (Entity ID - settings)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public readonly Dictionary<uint, CustomVendingConf> CustomVending =
new Dictionary<uint, CustomVendingConf>
{
[123343941] = new CustomVendingConf
{
Categories = new List<string>
{
"Cars", "Misc"
}
}
};
public VersionNumber Version;
}
private class SelectCurrencyUI
{
[JsonProperty(PropertyName = "Title")] public LabelSettings Title;
[JsonProperty(PropertyName = "Title Position")]
public InterfacePosition TitlePosition;
[JsonProperty(PropertyName = "Economy Title")]
public LabelSettings EconomyTitle;
[JsonProperty(PropertyName = "Selected Economy Color")]
public IColor SelectedEconomyColor;
[JsonProperty(PropertyName = "Unselected Economy Color")]
public IColor UnselectedEconomyColor;
[JsonProperty(PropertyName = "Economy Width")]
public float EconomyWidth;
[JsonProperty(PropertyName = "Economy Height")]
public float EconomyHeight;
[JsonProperty(PropertyName = "Economy Margin")]
public float EconomyMargin;
[JsonProperty(PropertyName = "Economy Indent")]
public float EconomyIndent;
[JsonProperty(PropertyName = "Frame Width")]
public float FrameWidth;
[JsonProperty(PropertyName = "Frame Indent")]
public float FrameIndent;
[JsonProperty(PropertyName = "Frame Header")]
public float FrameHeader;
[JsonProperty(PropertyName = "Close the menu after a currency change?")]
public bool CloseAfterChange;
}
private class InterfacePosition
{
public string AnchorMin;
public string AnchorMax;
public string OffsetMin;
public string OffsetMax;
}
private class LabelSettings
{
[JsonProperty(PropertyName = "FontSize")]
public int FontSize;
[JsonProperty(PropertyName = "Align")] [JsonConverter(typeof(StringEnumConverter))]
public TextAnchor Align;
[JsonProperty(PropertyName = "Color")] public IColor Color;
[JsonProperty(PropertyName = "Font")] public string Font;
}
private class IColor
{
[JsonProperty(PropertyName = "HEX")] public string Hex;
[JsonProperty(PropertyName = "Opacity (0 - 100)")]
public readonly float Alpha;
[JsonIgnore] private string _color;
[JsonIgnore]
public string Get
{
get
{
if (string.IsNullOrEmpty(_color))
_color = GetColor();
return _color;
}
}
private string GetColor()
{
if (string.IsNullOrEmpty(Hex)) Hex = "#FFFFFF";
var str = Hex.Trim('#');
if (str.Length != 6) throw new Exception(Hex);
var r = byte.Parse(str.Substring(0, 2), NumberStyles.HexNumber);
var g = byte.Parse(str.Substring(2, 2), NumberStyles.HexNumber);
var b = byte.Parse(str.Substring(4, 2), NumberStyles.HexNumber);
return $"{(double) r / 255} {(double) g / 255} {(double) b / 255} {Alpha / 100}";
}
public IColor()
{
}
public IColor(string hex, float alpha = 100)
{
Hex = hex;
Alpha = alpha;
}
}
private class CustomVendingConf
{
[JsonProperty(PropertyName = "Categories (Titles) [* - all]",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> Categories;
}
private class WipeSettings
{
[JsonProperty(PropertyName = "Wipe Cooldowns?")]
public bool Cooldown;
[JsonProperty(PropertyName = "Wipe Players?")]
public bool Players;
[JsonProperty(PropertyName = "Wipe Limits?")]
public bool Limits;
}
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;
[JsonProperty(PropertyName = "Select Currency Settings")]
public SelectCurrencyUI SelectCurrency;
}
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 = string.Empty;
[JsonProperty(PropertyName = "Command (%steamid%)")]
public string Command;
[JsonProperty(PropertyName = "Kit")] public string Kit = string.Empty;
[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 = 0;
[JsonProperty(PropertyName = "Sell Cooldown (0 - disable)")]
public float SellCooldown = 0;
[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 = "Daily Buy Limits (0 - no limit)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> DailyBuyLimits = new Dictionary<string, int>();
[JsonProperty(PropertyName = "Daily Sell Limits (0 - no limit)",
ObjectCreationHandling = ObjectCreationHandling.Replace)]
public Dictionary<string, int> DailySellLimits = new Dictionary<string, int>();
[JsonProperty(PropertyName = "Max Buy Amount (0 - disable)")]
public int BuyMaxAmount;
[JsonProperty(PropertyName = "Max Sell Amount (0 - disable)")]
public int SellMaxAmount;
[JsonProperty(PropertyName = "Force Buy")]
public bool ForceBuy;
[JsonIgnore] private int _itemId = -1;
[JsonIgnore]
public int itemId
{
get
{
if (_itemId == -1)
_itemId = ItemManager.FindItemDefinition(ShortName)?.itemid ?? -1;
return _itemId;
}
}
[JsonIgnore] private string _publicTitle;
[JsonIgnore]
public string PublicTitle
{
get
{
if (string.IsNullOrEmpty(_publicTitle))
_publicTitle = GetName();
return _publicTitle;
}
}
[JsonIgnore] private ICuiComponent _image;
public CuiElement GetImage(string aMin, string aMax, string oMin, string oMax, string parent,
string name = null)
{
if (_image == null)
{
if (_instance._enabledImageLibrary && !string.IsNullOrEmpty(Image))
_image = new CuiRawImageComponent
{
Png = _instance.ImageLibrary.Call<string>("GetImage", Image)
};
else
_image = new CuiImageComponent
{
ItemId = itemId,
SkinId = Skin
};
}
return new CuiElement
{
Name = string.IsNullOrEmpty(name) ? CuiHelper.GetGuid() : name,
Parent = parent,
Components =
{
_image,
new CuiRectTransformComponent
{
AnchorMin = aMin, AnchorMax = aMax,
OffsetMin = oMin, OffsetMax = oMax
}
}
};
}
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,
_config.UI.RoundDigits);
}
public int GetDiscount(BasePlayer player)
{
var result = 0;
Discount.Where(check => player.HasPermission(check.Key)).ForEach(
check =>
{
if (check.Value > result)
result = check.Value;
});
return result;
}
public int GetLimit(BasePlayer player, bool buy = true, bool daily = false)
{
var dict = daily ? buy ? DailyBuyLimits : DailySellLimits
: buy ? BuyLimits : SellLimits;
if (dict.Count == 0)
return 0;
var result = 0;
dict.Where(check => player.HasPermission(check.Key)).ForEach(
check =>
{
if (check.Value > result)
result = check.Value;
});
return result;
}
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('|'))
if (check.Contains("chat.say"))
{
var args = check.Split(' ');
player.SendConsoleCommand(
$"{args[0]} \" {string.Join(" ", args.ToList().GetRange(1, args.Length - 1))}\" 0");
}
else
{
_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;
}
public override string ToString()
{
switch (Type)
{
case ItemType.Item:
return $"[ITEM-{ID}] {ShortName}x{Amount}(DN: {DisplayName}, SKIN: {Skin})";
case ItemType.Command:
return $"[COMMAND-{ID}] {Command}";
case ItemType.Plugin:
return
$"[PLUGIN-{ID}] Name: {Plugin?.Plugin}, Hook: {Plugin?.Hook}, Amount: {Plugin?.Amount ?? 0}";
case ItemType.Kit:
return $"[KIT-{ID}] {Kit}";
default:
return base.ToString();
}
}
}
private class PluginItem
{
[JsonProperty(PropertyName = "Hook")] public string Hook = string.Empty;
[JsonProperty(PropertyName = "Plugin Name")]
public string Plugin = string.Empty;
[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 class AdditionalEconomy : EconomyConf
{
[JsonProperty(PropertyName = "ID")] public int ID;
[JsonProperty(PropertyName = "Enabled")]
public bool Enabled;
public bool IsSame(EconomyConf configEconomy)
{
return Type == configEconomy.Type &&
Plug == configEconomy.Plug &&
ShortName == configEconomy.ShortName &&
Skin == configEconomy.Skin;
}
public AdditionalEconomy(EconomyConf configEconomy)
{
Type = configEconomy.Type;
Plug = configEconomy.Plug;
AddHook = configEconomy.AddHook;
RemoveHook = configEconomy.RemoveHook;
BalanceHook = configEconomy.BalanceHook;
ShortName = configEconomy.ShortName;
DisplayName = configEconomy.DisplayName;
Skin = configEconomy.Skin;
TitleLangKey = configEconomy.TitleLangKey;
BalanceLangKey = configEconomy.BalanceLangKey;
ID = 0;
Enabled = true;
}
[JsonConstructor]
public AdditionalEconomy()
{
}
}
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;
[JsonProperty(PropertyName = "Lang Key (for Title)")]
public string TitleLangKey;
[JsonProperty(PropertyName = "Lang Key (for Balance)")]
public string BalanceLangKey;
public string GetTitle(BasePlayer player)
{
return _instance.Msg(player, TitleLangKey);
}
public string GetBalanceTitle(BasePlayer player)
{
return _instance.Msg(player, BalanceLangKey, ShowBalance(player));
}
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)), 2);
}
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;
}
}
public bool Transfer(BasePlayer player, BasePlayer targetPlayer, double amount)
{
if (!RemoveBalance(player, amount))
return false;
AddBalance(targetPlayer, amount);
return true;
}
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
};
item.DailyBuyLimits = new Dictionary<string, int>
{
["shop.default"] = 0,
["shop.vip"] = 0
};
item.DailySellLimits = 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();
SaveSelectEconomy();
}
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 SaveSelectEconomy()
{
Interface.Oxide.DataFileSystem.WriteObject($"{Name}/EconomyChoice", _economyChoice);
}
private void LoadData()
{
try
{
_data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>($"{Name}/Players");
_cooldown =
Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, CooldownInfo>>($"{Name}/Cooldown");
_limits = Interface.Oxide.DataFileSystem.ReadObject<PlayerLimits>($"{Name}/Limits");
_economyChoice = Interface.Oxide.DataFileSystem.ReadObject<EconomyChoice>($"{Name}/EconomyChoice");
}
catch (Exception e)
{
PrintError(e.ToString());
}
if (_data == null) _data = new PluginData();
if (_cooldown == null) _cooldown = new Dictionary<ulong, CooldownInfo>();
if (_limits == null) _limits = new PlayerLimits();
if (_economyChoice == null) _economyChoice = new EconomyChoice();
}
private class PluginData
{
[JsonProperty(PropertyName = "Players", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public readonly 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>();
}
private class DataCart
{
public readonly Dictionary<ShopItem, int> Items = new Dictionary<ShopItem, int>();
public void AddCartItem(ShopItem item, BasePlayer player)
{
int result;
int amount;
if (Items.TryGetValue(item, out amount))
{
if (item.BuyMaxAmount > 0 && amount >= item.BuyMaxAmount) return;
if (!CanCartAdd(player, item, amount + 1, out result))
{
_instance.SendNotify(player, result == 1 ? BuyLimitReached : DailyBuyLimitReached, 1,
item.PublicTitle);
return;
}
Items[item]++;
}
else
{
if (!CanCartAdd(player, item, 1, out result))
{
_instance.SendNotify(player, result == 1 ? BuyLimitReached : DailyBuyLimitReached, 1,
item.PublicTitle);
return;
}
Items.Add(item, 1);
}
}
private bool CanCartAdd(BasePlayer player, ShopItem item, int amount, out int result)
{
int leftLimit;
if (HasLimit(player, item, true, out leftLimit) && amount >= leftLimit) //total Limit
{
result = 1;
return false;
}
if (HasLimit(player, item, true, out leftLimit, true) && amount > leftLimit) //daily Limit
{
result = 2;
return false;
}
result = 0;
return true;
}
public void RemoveCartItem(ShopItem item)
{
Items.Remove(item);
}
public void ChangeAmountItem(BasePlayer player, ShopItem item, int amount)
{
if (amount > 0)
{
int totalLimit;
if (HasLimit(player, item, true, out totalLimit) && amount >= totalLimit)
amount = Math.Min(totalLimit, amount);
int dailyLimit;
if (HasLimit(player, item, true, out dailyLimit, true) && amount >= dailyLimit)
amount = Math.Min(dailyLimit, amount);
if (amount <= 0) return;
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
// ... [Code preview truncated due to length. Full source in attached file] ...