C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins {
[Info("ShoppyStock", "ThePitereq", "1.2.4")]
public class ShoppyStock : RustPlugin {
[PluginReference]
private readonly Plugin ImageLibrary, PopUpAPI, Economics, ServerRewards, RedeemStorageAPI, DiscordCore, Artifacts, BonusCore, NoEscape, BankSystem, IQEconomic;
private readonly Dictionary<BasePlayer, ShopCache> shopCache = new Dictionary<BasePlayer, ShopCache>();
private readonly Dictionary<BasePlayer, StockPosition> stockPosition = new Dictionary<BasePlayer, StockPosition>();
private readonly List<BasePlayer> openedUis = new List<BasePlayer>();
private readonly Dictionary<string, List<ItemDefinition>> stockCategories = new Dictionary<string, List<ItemDefinition>>();
private readonly Dictionary<string, StockItemDefinitionData> itemDefinitions = new Dictionary<string, StockItemDefinitionData>();
private readonly Dictionary<ulong, PermissionData> cachedListingCount = new Dictionary<ulong, PermissionData>();
private readonly Dictionary<BasePlayer, Mailbox> mailboxes = new Dictionary<BasePlayer, Mailbox>();
private readonly Dictionary<BasePlayer, BoxStorage> boxes = new Dictionary<BasePlayer, BoxStorage>();
private readonly Dictionary<string, Timer> stockTimers = new Dictionary<string, Timer>();
private readonly Dictionary<BasePlayer, BasePlayer> shopNpc = new Dictionary<BasePlayer, BasePlayer>();
private readonly Dictionary<BasePlayer, AddItemData> addingItemsCache = new Dictionary<BasePlayer, AddItemData>();
private readonly Dictionary<BasePlayer, DateTime> lastUsage = new Dictionary<BasePlayer, DateTime>();
private readonly List<string> newStocks = new List<string>();
private readonly bool privFeatures = false;
private bool anyStock = false;
private bool selling = false;
private class AddItemData {
public string shopName;
public string category;
public bool stockMarket;
public float var1 = 0;
public float var2 = 0;
public int var3 = 0;
}
private class ShopCache {
public string currentShop = "";
public string shopCategory;
public bool affordableOnly = false;
public string searchValue = "";
public int page = 1;
public int categoryPage = 1;
public bool transferOnline = false;
public CurrentListing currentListings;
public StockCache stockMarket = new StockCache();
public string lastVisit = "";
}
private class StockPosition {
public string currentItem = "";
}
private class CurrentListing {
public string listingKey;
public string shopName;
public ListingData listing;
public int amount;
}
private class StockCache {
public string shopName = "";
public string category;
public bool sellToServerOnly = false;
public char buySellOrders = ' ';
public int page = 1;
public string search = "";
public int categoryPage = 1;
public ListingCache listing = new ListingCache();
public RequestCache request = new RequestCache();
public bool quickList = false;
}
private class ListingCache {
public int page = 1;
public OrderData selected = null;
public bool hideOwned = true;
public bool buyOffers = true;
public int timestamp = 0;
public int index = -1;
public string key = "";
public int amount = 1;
}
private class RequestCache {
public int amount = 1;
public float price = 0;
public bool buyRequest = false;
public string itemShortname = "";
public ulong itemSkin = 0;
}
private void Init() {
config = Config.ReadObject<PluginConfig>();
Config.WriteObject(config);
LoadData();
}
private void OnServerInitialized() {
if (PopUpAPI == null) PrintWarning("PopUpAPI not found! Pop-Up messages will not appear!");
else if (PopUpAPI.Version.Major < 2) PrintWarning("PopUpAPI V2 not found! Update API to make this plugin works properly!");
if (ImageLibrary == null) PrintWarning("ImageLibrary not found! Images will not appear!");
if (config.debug) Puts("[DEBUG] Starting loading plugin...DEBUG ENABLED");
foreach (var shop in data.shops) {
if (shop.Value.categories.Count > 0) continue;
if (config.shops[shop.Key].generateAllDefaultItems) {
foreach (var item in ItemManager.itemList) {
string cat = item.category.ToString();
shop.Value.categories.TryAdd(cat, new CategoryData());
shop.Value.categories[cat].listings.Add($"{item.shortname}-0", new ListingData() {
displayName = item.displayName.english, shortname = item.shortname, price = 1
}
);
}
}
else {
shop.Value.categories.Add("tools", new CategoryData());
shop.Value.categories["tools"].listings.Add("pickaxe-0", new ListingData() {
displayName = "Pickaxe", shortname = "pickaxe", price = 150
}
);
shop.Value.categories["tools"].listings.Add("axe-0", new ListingData() {
displayName = "Axe", shortname = "axe", price = 150
}
);
shop.Value.categories.Add("resources", new CategoryData());
shop.Value.categories["resources"].listings.Add("wood-0", new ListingData() {
displayName = "Wood", shortname = "wood", price = 765000
}
);
}
Puts($"Generating default shop categories for shop {shop.Key}...");
}
if (config.debug) Puts("[DEBUG] Finished generating default categories.");
foreach (var stock in newStocks) {
data.stockMarkets.TryAdd(stock, new StockData());
data.stockMarkets[stock].stockConfig = new StockItemData();
data.stockMarkets[stock].stockConfig.customItems = new Dictionary<string, CustomItemData>() {
{
"coal-2871627272", new CustomItemData() {
amount = 1, category = "CustomItems", displayName = "Golden Cloth", shortname = "coal", skin = 2871627272
}
}
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.priceBarriers = new Dictionary<float, float>() {
{
50, 2
}
, {
47, 4
}
, {
44, 6
}
, {
41, 8
}
, {
38, 10
}
, {
35, 20
}
, {
32, 30
}
, {
29, 40
}
, {
26, 50
}
, {
23, 60
}
, {
20, 65
}
, {
17, 70
}
, {
14, 75
}
, {
11, 80
}
, {
8, 85
}
, {
5, 90
}
, {
2, 95
}
, {
0, 100
}
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.priceDropChart = new Dictionary<float, float>() {
{
5000, 4
}
, {
2500, 4
}
, {
1200, 3
}
, {
800, 2.5f
}
, {
500, 2
}
, {
250, 1.5f
}
, {
125, 1.2f
}
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.sellPricePentality = new Dictionary<float, PentalityData>() {
{
10000, new PentalityData() {
pentalityLength = 24, percentage = 25
}
}
, {
9000, new PentalityData() {
pentalityLength = 20, percentage = 30
}
}
, {
7000, new PentalityData() {
pentalityLength = 16, percentage = 40
}
}
, {
5000, new PentalityData() {
pentalityLength = 12, percentage = 50
}
}
, {
4000, new PentalityData() {
pentalityLength = 10, percentage = 50
}
}
, {
3000, new PentalityData() {
pentalityLength = 8, percentage = 50
}
}
, {
2000, new PentalityData() {
pentalityLength = 6, percentage = 60
}
}
, {
1000, new PentalityData() {
pentalityLength = 6, percentage = 70
}
}
,
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.goalAchievedChart = new Dictionary<float, float>() {
{
0, 3
}
, {
1, 2
}
, {
5, 1.7f
}
, {
10, 1.5f
}
, {
25, 1.4f
}
, {
50, 1.3f
}
, {
75, 1.2f
}
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.sellAmountOnlineMultiplier = new Dictionary<int, float>() {
{
20, 1.5f
}
, {
40, 2f
}
, {
60, 3f
}
, {
80, 4.5f
}
, {
100, 6f
}
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.multplierAmountChance = new Dictionary<float, float>() {
{
0, 20
}
, {
25, 15
}
, {
50, 10
}
, {
100, 5
}
, {
200, 1
}
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.positiveRandomEvents = new List<string>() {
"HighDemand", "VeryHighDemand", "ExtremeDemand"
}
;
data.stockMarkets[stock].stockConfig.priceCalculations.negativeRandomEvents = new List<string>() {
"NegativeDemand", "UltraNegativeDemand"
}
;
data.stockMarkets[stock].stockConfig.serverSell = new Dictionary<string, Dictionary<ulong, ServerSellData>>() {
{
"wood", new Dictionary<ulong, ServerSellData>() {
{
0, new ServerSellData() {
defaultAmount = 50000, displayName = "Wood", maximalPrice = 4, minimalPrice = 0.2f
}
}
, {
1567546863, new ServerSellData() {
defaultAmount = 100, displayName = "Magic Wood", maximalPrice = 19, minimalPrice = 1f, maxDailySoldPerms = new Dictionary<string, int>() {
{
"shoppystock.maxdailysell.1000", 1000
}
, {
"shoppystock.maxdailysell.5000", 5000
}
}
}
}
,
}
}
, {
"stones", new Dictionary<ulong, ServerSellData>() {
{
0, new ServerSellData() {
defaultAmount = 50000, displayName = "Stones", maximalPrice = 5, minimalPrice = 0.4f
}
}
}
}
}
;
Puts($"Generating default data values for stock market {stock}...");
}
if (config.debug) Puts("[DEBUG] Finished generating default stock market configurations.");
string today = DateTime.Now.ToShortDateString();
int removedCount = 0;
foreach (var shop in data.shops) foreach (var user in shop.Value.users) foreach (var dailyPurchase in user.Value.dailyPurchases.ToList()) if (dailyPurchase.Key != today) {
data.shops[shop.Key].users[user.Key].dailyPurchases.Remove(dailyPurchase.Key);
removedCount++;
}
if (removedCount > 0) Puts($"Removed {removedCount} old daily limits from data.");
if (config.debug) Puts("[DEBUG] Finished clearing daily limits.");
List<KeyValuePair<string, ulong>> imagesToDownload = new List<KeyValuePair<string, ulong>>();
foreach (var shop in config.shops) {
if (shop.Value.canDeposit && shop.Value.depositItem.url != "") AddImage(shop.Value.depositItem.url, shop.Value.depositItem.shortname, shop.Value.depositItem.skin);
if (shop.Value.stockConfig.canStockMarket) {
anyStock = true;
if (shop.Value.stockConfig.bankEnabled && shop.Value.stockConfig.bankPermission != "" && shop.Value.stockConfig.bankPermission.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(shop.Value.stockConfig.bankPermission, this)) permission.RegisterPermission(shop.Value.stockConfig.bankPermission, this);
if (shop.Value.stockConfig.favouritesEnabled && shop.Value.stockConfig.favouritesPermission != "" && shop.Value.stockConfig.favouritesPermission.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(shop.Value.stockConfig.favouritesPermission, this)) permission.RegisterPermission(shop.Value.stockConfig.favouritesPermission, this);
foreach (var perm in shop.Value.stockConfig.sellPriceMultipliers) if (!permission.PermissionExists(perm.Key, this)) permission.RegisterPermission(perm.Key, this);
foreach (var perm in shop.Value.stockConfig.maxBankIndividualItemsPerms) if (!permission.PermissionExists(perm.Key, this)) permission.RegisterPermission(perm.Key, this);
foreach (var perm in shop.Value.stockConfig.maxBankStacksPerms) if (!permission.PermissionExists(perm.Key, this)) permission.RegisterPermission(perm.Key, this);
}
if (shop.Value.iconUrl != "") AddImage(shop.Value.iconUrl, $"UI_ShoppyStock_{shop.Key}_Icon", 0);
foreach (var category in data.shops[shop.Key].categories) {
if (category.Value.iconUrl != "") AddImage(category.Value.iconUrl, $"UI_ShoppyStock_Category_{category.Key}", 0);
foreach (var (key, item) in category.Value.listings) {
if (item.iconUrl != "") {
if (item.commands.Count > 0) AddImage(item.iconUrl, key, 0);
else AddImage(item.iconUrl, item.shortname, item.skin);
}
else if (item.skin != 0) imagesToDownload.Add(new KeyValuePair<string, ulong>(item.shortname, item.skin));
}
}
if (shop.Value.permission != "" && shop.Value.permission.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(shop.Value.permission, this)) permission.RegisterPermission(shop.Value.permission, this);
foreach (var discount in shop.Value.discounts) if (discount.Key.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(discount.Key, this)) permission.RegisterPermission(discount.Key, this);
foreach (var category in data.shops[shop.Key].categories.Values) {
if (category.permission != "" && category.permission.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(category.permission, this)) permission.RegisterPermission(category.permission, this);
foreach (var discount in category.discounts) if (discount.Key.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(discount.Key, this)) permission.RegisterPermission(discount.Key, this);
foreach (var item in category.listings.Values) {
foreach (var discount in item.discounts) if (discount.Key.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(discount.Key, this)) permission.RegisterPermission(discount.Key, this);
if (item.permission != "" && item.permission.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(item.permission, this)) permission.RegisterPermission(item.permission, this);
if (item.blacklistPermission != "" && item.blacklistPermission.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(item.blacklistPermission, this)) permission.RegisterPermission(item.blacklistPermission, this);
}
}
}
if (config.debug) Puts("[DEBUG] Finished loading icons and permissions to shops.");
if (anyStock) {
if (RedeemStorageAPI == null) PrintWarning("RedeemStorageAPI not found! Players will be not able to redeem items from market!");
foreach (var item in ItemManager.itemList) {
if (config.ignoredShortnames.Contains(item.shortname)) continue;
string category = item.category.ToString();
stockCategories.TryAdd(category, new List<ItemDefinition>());
stockCategories[category].Add(item);
itemDefinitions.TryAdd($"{item.shortname}-0", new StockItemDefinitionData() {
category = category, displayName = item.displayName.english, shortname = item.shortname
}
);
}
if (config.debug) Puts("[DEBUG] Finished generating default categories.");
foreach (var stock in data.stockMarkets) {
if (!config.shops.ContainsKey(stock.Key)) {
Puts($"Stock {stock.Key} is somehow missing in your config.Skipping this stock data check...");
continue;
}
int maxHistory = 0;
foreach (var timestamp in config.timestamps) {
int calc = Mathf.CeilToInt(timestamp.Key / config.shops[stock.Key].stockConfig.updateInterval);
if (maxHistory < calc) maxHistory = calc;
}
foreach (var item in stock.Value.stockConfig.customItems) {
itemDefinitions.TryAdd($"{item.Key}", new StockItemDefinitionData() {
category = item.Value.category, displayName = item.Value.displayName, shortname = item.Value.shortname, skin = item.Value.skin
}
);
if (item.Value.url != "") AddImage(item.Value.url, item.Value.shortname, item.Value.skin);
else if (item.Value.skin != 0) imagesToDownload.Add(new KeyValuePair<string, ulong>(item.Value.shortname, item.Value.skin));
}
foreach (var stockShortname in stock.Value.sellCache) {
foreach (var stockItem in stockShortname.Value) {
List<float> clearedHistory1 = new List<float>(stockItem.Value.priceHistory.Take(maxHistory));
stockItem.Value.priceHistory = clearedHistory1;
List<int> clearedHistory2 = new List<int>(stockItem.Value.sellAmountHistory.Take(maxHistory));
stockItem.Value.sellAmountHistory = clearedHistory2;
}
}
foreach (var item in stock.Value.stockConfig.serverSell.Values) {
foreach (var skin in item.Values) {
if (skin.maxDailySold > 0 && !config.enableStockStats) PrintWarning($"You have to enable stock market logs to make daily sell values work.Set \"Enable Stock Market Logging\" to true in main config!");
foreach (var perm in skin.maxDailySoldPerms) if (!permission.PermissionExists(perm.Key, this)) permission.RegisterPermission(perm.Key, this);
}
}
foreach (var shortnames in data.stockMarkets[stock.Key].playerData.buyOrders) if (data.stockMarkets[stock.Key].playerData.buyOrders[shortnames.Key].ContainsKey(0)) foreach (var listing in data.stockMarkets[stock.Key].playerData.buyOrders[shortnames.Key][0]) if (listing.item.skin != 0) imagesToDownload.Add(new KeyValuePair<string, ulong>(listing.item.shortname, listing.item.skin));
foreach (var shortnames in data.stockMarkets[stock.Key].playerData.sellOrders) if (data.stockMarkets[stock.Key].playerData.sellOrders[shortnames.Key].ContainsKey(0)) foreach (var listing in data.stockMarkets[stock.Key].playerData.sellOrders[shortnames.Key][0]) if (listing.item.skin != 0) imagesToDownload.Add(new KeyValuePair<string, ulong>(listing.item.shortname, listing.item.skin));
}
if (config.debug) Puts("[DEBUG] Finished downloading images to market.");
if (imagesToDownload.Count > 0) ImageLibrary?.Call("LoadImageList", Name, imagesToDownload);
Puts($"Loaded {itemDefinitions.Count} stock market item definitions!");
foreach (var icon in config.categoryIcons) if (icon.Value != "") AddImage(icon.Value, $"UI_ShoppyStock_Category_{icon.Key}", 0);
foreach (var perm in config.listingPermissions) if (perm.Key.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(perm.Key, this)) permission.RegisterPermission(perm.Key, this);
foreach (var perm in config.timestamps) if (perm.Value.ToLower().Contains(Name.ToLower()) && !permission.PermissionExists(perm.Value, this)) permission.RegisterPermission(perm.Value, this);
bool setTime = false;
foreach (var shop in config.shops) {
if (shop.Value.stockConfig.updateIntervalHourMinutes.Count > 0) {
setTime = true;
break;
}
}
if (config.debug) Puts("[DEBUG] Finished misc things to market.");
if (setTime) {
stockTimers.TryAdd("hourSelect", timer.Every(50, () => {
int currentMinuite = DateTime.Now.Minute;
int notReady = 0;
foreach (var shop in config.shops) {
if (shop.Value.stockConfig.canStockMarket && !stockTimers.ContainsKey(shop.Key)) notReady++;
}
if (notReady == 0) {
Puts($"All start hours set succesfully!");
stockTimers["hourSelect"].Destroy();
}
foreach (var shop in config.shops) {
if (!shop.Value.stockConfig.canStockMarket || stockTimers.ContainsKey(shop.Key)) continue;
if (!shop.Value.stockConfig.updateIntervalHourMinutes.Contains(currentMinuite)) continue;
UpdateStockPrices(shop.Key);
stockTimers.TryAdd(shop.Key, timer.Every(shop.Value.stockConfig.updateInterval * 60, () => UpdateStockPrices(shop.Key)));
}
}
));
}
else {
foreach (var shop in config.shops) if (shop.Value.stockConfig.canStockMarket) {
UpdateStockPrices(shop.Key);
stockTimers.TryAdd(shop.Key, timer.Every(shop.Value.stockConfig.updateInterval * 60, () => UpdateStockPrices(shop.Key)));
}
}
if (config.debug) Puts("[DEBUG] Finished market basic setup.");
}
foreach (var market in data.stockMarkets) {
foreach (var name in market.Value.playerData.buyOrders) foreach (var skin in name.Value) foreach (var listing in skin.Value) {
cachedListingCount.TryAdd(listing.sellerId, new PermissionData());
cachedListingCount[listing.sellerId].buyListings++;
}
foreach (var name in market.Value.playerData.sellOrders) foreach (var skin in name.Value) foreach (var listing in skin.Value) {
cachedListingCount.TryAdd(listing.sellerId, new PermissionData());
cachedListingCount[listing.sellerId].sellListings++;
}
}
if (config.debug) Puts("[DEBUG] Finished making listing count cache.");
SaveData(true);
foreach (var category in config.customCategories) stockCategories.TryAdd(category, new List<ItemDefinition>());
LoadMessages();
AddImage("https://images.pvrust.eu/ui_icons/ShoppyStock/dollar_0.png", "UI_ShoppyStock_DefaultShopIcon", 0);
AddImage("https://images.pvrust.eu/ui_icons/ShoppyStock/arrow_left_0.png", "UI_ShoppyStock_ArrowLeft", 0);
AddImage("https://images.pvrust.eu/ui_icons/ShoppyStock/arrow_right_0.png", "UI_ShoppyStock_ArrowRight", 0);
AddImage("https://images.pvrust.eu/ui_icons/ShoppyStock/search_0.png", "UI_ShoppyStock_Search", 0);
AddImage("https://images.pvrust.eu/ui_icons/ShoppyStock/category_0.png", "UI_ShoppyStock_DefaultCategoryIcon", 0);
foreach (var command in config.commands) cmd.AddChatCommand(command, this, nameof(MarketCommand));
foreach (var command in config.quickSellCommands) cmd.AddChatCommand(command.Key, this, nameof(MarketSellCommand));
foreach (var command in config.quickListCommands) cmd.AddChatCommand(command.Key, this, nameof(MarketListCommand));
foreach (var command in config.depositCommands) cmd.AddChatCommand(command.Key, this, nameof(DepositCommand));
foreach (var command in config.shopOpenCommands) cmd.AddChatCommand(command.Key, this, nameof(OpenShopCommand));
foreach (var command in config.stockOpenCommands) cmd.AddChatCommand(command.Key, this, nameof(OpenStockCommand));
permission.RegisterPermission("shoppystock.admin", this);
permission.RegisterPermission("shoppystock.hidetransfer", this);
AddCovalenceCommand(config.adminCommand, nameof(CurrencyAdminCommand));
AddCovalenceCommand("updateprices", nameof(UpdatePricesCommand));
if (privFeatures) {
cmd.AddChatCommand("additems", this, nameof(AddStockItemsCommand));
cmd.AddChatCommand("rptop", this, nameof(RPTopTempCommand));
cmd.AddChatCommand("goldtop", this, nameof(GoldTopTempCommand));
}
GeneratePopUpConfig();
TryPatchingConfig();
if (config.debug) Puts("[DEBUG] Plugin init finished.");
/*int days = 0;
Dictionary<string, long> summedItems= new Dictionary<string, long>();
foreach (var day in data.stockMarkets["rp"].stats.globalDailyItems)
{
if (day.Value.Count < 10) continue;
foreach (var item in day.Value)
{
summedItems.TryAdd(item.Key, 0);
summedItems[item.Key] += item.Value;
}
days++;
}
Puts($"Days: {days}");
foreach (var item in summedItems)
Puts($"Item {item.Key}: {item.Value / days} daily, {item.Value / days / 48} per tick");*/
}
private void Unload() {
SaveData();
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, "Market_CreateOfferUI");
CuiHelper.DestroyUi(player, "Market_AnchorUI");
CuiHelper.DestroyUi(player, "Market_MainUI");
CuiHelper.DestroyUi(player, "Market_CurrencyInputUI");
}
foreach (var mailbox in mailboxes) {
if (mailbox.Value != null) {
if (mailbox.Key != null && !shopCache[mailbox.Key].stockMarket.request.buyRequest) foreach (var item in mailbox.Value.inventory.itemList.ToList()) if (!item.MoveToContainer(mailbox.Key.inventory.containerMain)) item.MoveToContainer(mailbox.Key.inventory.containerBelt);
mailbox.Value.Kill();
}
}
foreach (var storage in boxes) {
if (storage.Value != null) {
if (storage.Key != null) foreach (var item in storage.Value.inventory.itemList.ToList()) if (!item.MoveToContainer(storage.Key.inventory.containerMain)) item.MoveToContainer(storage.Key.inventory.containerBelt);
storage.Value.Kill();
}
}
}
private void TryPatchingConfig() {
bool changes = false;
foreach (var shop in config.quickListCommands.ToList()) {
if (!config.shops.ContainsKey(shop.Value)) {
PrintWarning($"Command {shop.Key} had unassigned shop with name {shop.Value}.It has been replaced with first shop in config.");
config.quickListCommands[shop.Key] = config.shops.FirstOrDefault().Key;
changes = true;
}
}
foreach (var shop in config.quickSellCommands.ToList()) {
if (!config.shops.ContainsKey(shop.Value)) {
PrintWarning($"Command {shop.Key} had unassigned shop with name {shop.Value}.It has been replaced with first shop in config.");
config.quickSellCommands[shop.Key] = config.shops.FirstOrDefault().Key;
changes = true;
}
}
foreach (var shop in config.depositCommands.ToList()) {
if (!config.shops.ContainsKey(shop.Value)) {
PrintWarning($"Command {shop.Key} had unassigned shop with name {shop.Value}.It has been replaced with first shop in config.");
config.depositCommands[shop.Key] = config.shops.FirstOrDefault().Key;
changes = true;
}
}
foreach (var shop in config.shops.ToList()) {
if (shop.Key.Contains(' ')) PrintWarning($"Shop {shop.Key} has spaces in their codename.Change them to underscores or plugin will print errors!");
}
if (changes) {
Config.WriteObject(config);
Puts("Saving changes in main configuration file...");
}
changes = false;
foreach (var shop in config.shops) {
foreach (var categories in data.shops[shop.Key].categories) {
if (categories.Key.Contains(' ')) {
changes = true;
PrintWarning($"Shop's {shop.Key} category {categories.Key} has spaces in their codename.Change them to underscores or plugin will print errors!");
}
foreach (var listing in categories.Value.listings) {
if (listing.Key.Contains(' ')) {
changes = true;
PrintWarning($"Shop's {shop.Key} category {categories.Key} item {listing.Key} has spaces in their codename.Change them to underscores or plugin will print errors!");
}
foreach (var command in listing.Value.commands) if (command.Contains('{') && !command.Contains("{userId}") && !command.Contains("{userName}")) {
changes = true;
PrintWarning($"Your ran command in shop {shop.Key} category {categories.Key} item {listing.Key} contains variable names, that are not valid for the plugin.Only working variables are {{userId}} and {{userName}} and they are case sensitive!");
}
}
}
if (shop.Value.stockConfig.canStockMarket) foreach (var customItem in data.stockMarkets[shop.Key].stockConfig.customItems) if (customItem.Key != $"{customItem.Value.shortname}-{customItem.Value.skin}") {
changes = true;
PrintWarning($"There is an error in your {shop.Key}'s custom stock item.Their codename is \"{customItem.Key}\" but it should be \"{customItem.Value.shortname}-{customItem.Value.skin}\"");
}
}
if (changes) PrintWarning("It's recommended to check your shop/stock data file.There might be some errors!");
}
private void OnNewSave() {
config = Config.ReadObject<PluginConfig>();
LoadData();
foreach (var shop in data.shops.ToList()) {
if (!config.shops.ContainsKey(shop.Key)) continue;
if (config.shops[shop.Key].wipeCurrency) data.shops[shop.Key].users.Clear();
else {
if (config.shops[shop.Key].percentageTook > 0) {
float multiplyValue = config.shops[shop.Key].percentageTook / 100f;
foreach (var user in shop.Value.users) TakeCurrency(shop.Key, user.Key, Mathf.RoundToInt(user.Value.currencyAmount * multiplyValue));
}
foreach (var user in shop.Value.users) data.shops[shop.Key].users[user.Key].wipePurchases.Clear();
}
if (config.shops[shop.Key].stockConfig.canStockMarket) {
if (config.shops[shop.Key].stockConfig.wipeBuyListings) data.stockMarkets[shop.Key].playerData.buyOrders.Clear();
if (config.shops[shop.Key].stockConfig.wipeSellListings) data.stockMarkets[shop.Key].playerData.sellOrders.Clear();
if (config.shops[shop.Key].stockConfig.wipeBankData) data.stockMarkets[shop.Key].playerData.playerBanks.Clear();
}
}
SaveData();
}
/*private object OnPlayerCommand(BasePlayer player)
{
if (openedUis.Contains(player) || mailboxes.ContainsKey(player)) return false;
return null;
}*/
private void OnPlayerConnected(BasePlayer player) {
foreach (var shop in data.shops) if (shop.Value.users.ContainsKey(player.userID)) shop.Value.users[player.userID].username = player.IPlayer.Name;
}
/*private object OnServerCommand(ConsoleSystem.Arg arg)
{
BasePlayer player = arg.Player();
if (player == null || arg.FullString == null) return null;
if (openedUis.Contains(player) || mailboxes.ContainsKey(player))
{
if (arg.cmd.Name.Contains("UI_") || arg.cmd.Name.Contains("endloot")) return null;
else return false;
}
return null;
}*/
private void OnPlayerDisconnected(BasePlayer player) => openedUis.Remove(player);
private object CanUseMailbox(BasePlayer player, Mailbox mailbox) {
if (mailboxes.ContainsKey(player)) return false;
else return null;
}
private void OnPlayerSleep(BasePlayer player) {
if (!player.IsConnected) return;
CuiHelper.DestroyUi(player, "Market_CreateOfferUI");
CuiHelper.DestroyUi(player, "Market_AnchorUI");
CuiHelper.DestroyUi(player, "Market_MainUI");
CuiHelper.DestroyUi(player, "Market_CurrencyInputUI");
}
private void OnLootEntityEnd(BasePlayer player, Mailbox mailbox) {
if (mailbox.net == null || !mailboxes.ContainsKey(player)) return;
if (!shopCache[player].stockMarket.request.buyRequest) foreach (var item in mailbox.InputContainer.itemList.ToList()) if (!item.MoveToContainer(player.inventory.containerMain)) item.Drop(player.transform.position, Vector3.zero);
mailboxes.Remove(player);
if (mailbox.skinID == 1) {
openedUis.Remove(player);
CuiHelper.DestroyUi(player, "Market_CreateOfferUI");
}
else if (mailbox.skinID == 2) {
openedUis.Remove(player);
CuiHelper.DestroyUi(player, "Market_MainUI");
}
else if (mailbox.skinID == 3) {
openedUis.Remove(player);
CuiHelper.DestroyUi(player, "Market_CurrencyInputUI");
if (shopCache[player].stockMarket.quickList) {
shopCache.Remove(player);
mailbox.Kill();
return;
}
if (shopCache[player].lastVisit == "shop") OpenShopUI(player, shopCache[player].currentShop, shopCache[player].searchValue, shopCache[player].shopCategory, shopCache[player].categoryPage, shopCache[player].page);
else if (shopCache[player].lastVisit == "stock") OpenStockMarketUI(player, shopCache[player].stockMarket.shopName, shopCache[player].stockMarket.search, shopCache[player].stockMarket.category, shopCache[player].stockMarket.page, shopCache[player].stockMarket.categoryPage);
mailbox.Kill();
return;
}
else if (mailbox.skinID == 4) {
openedUis.Remove(player);
CuiHelper.DestroyUi(player, "Market_CreateOfferUI");
mailbox.Kill();
return;
}
if (shopCache[player].stockMarket.quickList) {
shopCache.Remove(player);
mailbox.Kill();
return;
}
if (shopCache[player].stockMarket.category == "bank_management") shopCache[player].stockMarket.category = "";
OpenStockMarketUI(player, shopCache[player].stockMarket.shopName, shopCache[player].stockMarket.search, shopCache[player].stockMarket.category, shopCache[player].stockMarket.page, shopCache[player].stockMarket.categoryPage);
mailbox.Kill();
}
private void OnLootEntityEnd(BasePlayer player, BoxStorage storage) {
if (storage.net == null || !boxes.ContainsKey(player)) return;
if (boxes[player] == null) {
boxes.Remove(player);
openedUis.Remove(player);
CuiHelper.DestroyUi(player, "Market_MainUI");
CuiHelper.DestroyUi(player, "Market_MainUI");
if (!shopCache.ContainsKey(player)) storage.Kill();
return;
}
if (storage != boxes[player]) return;
foreach (var item in storage.inventory.itemList.ToList()) if (!item.MoveToContainer(player.inventory.containerMain)) item.Drop(player.transform.position, Vector3.zero);
boxes.Remove(player);
openedUis.Remove(player);
CuiHelper.DestroyUi(player, "Market_MainUI");
if (!shopCache.ContainsKey(player)) {
storage.Kill();
return;
}
if (!string.IsNullOrEmpty(shopCache[player].stockMarket.shopName)) OpenStockMarketUI(player, shopCache[player].stockMarket.shopName, shopCache[player].stockMarket.search, shopCache[player].stockMarket.category, shopCache[player].stockMarket.page, shopCache[player].stockMarket.categoryPage);
storage.Kill();
}
private object OnItemSubmit(Item item, Mailbox mailbox, BasePlayer player) {
if (mailbox.net == null || !mailboxes.ContainsKey(player) || item == null) return null;
if (mailbox.skinID == 1) TryMarketAction(item, player);
else if (mailbox.skinID == 2) TryAddToBank(item, player);
else if (mailbox.skinID == 3) TryAddCurrency(item, player);
else if (mailbox.skinID == 4) TryAddItemEntry(item, player);
return false;
}
private void MarketCommand(BasePlayer player) {
if (IsBlocked(player)) {
PopUpAPI?.Call("ShowPopUp", player, "Market", Lang("ShopRaidBlocked", player.UserIDString), config.popUpFontSize, config.popUpLength);
EffectNetwork.Send(new Effect("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player, 0, Vector3.zero, Vector3.up), player.net.connection);
return;
}
UpdateStockItemNames(player);
if (config.openInCached && shopCache.ContainsKey(player)) {
CuiHelper.DestroyUi(player, "Market_AnchorUI");
if (shopCache[player].lastVisit == "shop") OpenShopUI(player, shopCache[player].currentShop, shopCache[player].searchValue, shopCache[player].shopCategory, shopCache[player].categoryPage, shopCache[player].page);
else if (shopCache[player].stockMarket.shopName != "") {
if (shopCache[player].stockMarket.category == "bank_management") shopCache[player].stockMarket.category = "";
OpenStockMarketUI(player, shopCache[player].stockMarket.shopName, shopCache[player].stockMarket.search, shopCache[player].stockMarket.category, shopCache[player].stockMarket.page, shopCache[player].stockMarket.categoryPage);
}
else OpenShopSelectUI(player);
}
else OpenShopSelectUI(player);
}
private void MarketSellCommand(BasePlayer player, string command) {
if (IsBlocked(player)) {
PopUpAPI?.Call("ShowPopUp", player, "Market", Lang("ShopRaidBlocked", player.UserIDString), config.popUpFontSize, config.popUpLength);
EffectNetwork.Send(new Effect("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player, 0, Vector3.zero, Vector3.up), player.net.connection);
return;
}
UpdateStockItemNames(player);
string commandToLower = command.ToLower();
foreach (var sellCommand in config.quickSellCommands) if (sellCommand.Key.ToLower() == commandToLower) {
string shopKey = sellCommand.Value;
if (!data.stockMarkets.ContainsKey(shopKey) || !config.shops.ContainsKey(shopKey) || !config.shops[shopKey].stockConfig.canStockMarket) {
PopUpAPI?.Call("ShowPopUp", player, "Market", Lang("NotValidShopAssigned", player.UserIDString, shopKey), config.popUpFontSize, config.popUpLength);
return;
}
shopCache.Remove(player);
OpenSellUI(player, shopKey);
break;
}
}
private void MarketListCommand(BasePlayer player, string command) {
if (IsBlocked(player)) {
PopUpAPI?.Call("ShowPopUp", player, "Market", Lang("ShopRaidBlocked", player.UserIDString), config.popUpFontSize, config.popUpLength);
EffectNetwork.Send(new Effect("assets/prefabs/locks/keypad/effects/lock.code.denied.prefab", player, 0, Vector3.zero, Vector3.up), player.net.connection);
return;
}
UpdateStockItemNames(player);
foreach (var listCommand in config.quickListCommands) if (listCommand.Key == command) {
shopCache.Remove(player);
shopCache.Add(player, new ShopCache());
shopCache[player].stockMarket.quickList = true;
shopCache[player].stockMarket.shopName = listCommand.Value;
shopCache[player].stockMark
// ... [Code preview truncated due to length. Full source in attached file] ...