using System; using System.Text; using System.Collections.Generic; using System.Collections; using System.Linq; using UnityEngine; using Steamworks; using Oxide.Core; using Oxide.Core.Libraries; using Oxide.Core.Plugins; using Newtonsoft.Json; using Oxide.Game.Rust.Cui; namespace Oxide.Plugins { [Info("SkinBox", "FuJiCuRa", "1.16.10", ResourceId = 17)] [Description("SkinBox is a plugin to convert any skinnable item into each skin variant")] internal class SkinBox : RustPlugin { [PluginReference] private Plugin QuickSort, ServerRewards, Economics, StacksExtended; private bool skinsLoaded; private bool Initialized; private bool Changed; private static SkinBox skinBox = null; private bool activeServerRewards; private bool activeEconomics; private bool activeScrap; private bool activePointSystem; private int scrapItemId; private int maxItemsShown; private bool _stacksExtendedExtrasDisabled; private Dictionary> skinsCache = new Dictionary>(); private Dictionary> skinsCacheLimited = new Dictionary>(); private Dictionary approvedSkinsCount = new Dictionary(); private Dictionary cooldownTimes = new Dictionary(); private Dictionary NameToItemName = new Dictionary(); private Dictionary ItemNameToName = new Dictionary(); private Dictionary manualAddedSkinsPre = new Dictionary(); private Dictionary> manualAddedSkins = new Dictionary>(); private List excludedSkins = new List(); private List excludedSkinsPre = new List(); private Dictionary activeSkinBoxes = new Dictionary(); private Dictionary skinWorkshopNames = new Dictionary(); private List altSkinBoxCommand; private string skinBoxCommand; private string permissionUse; private string permissionAdmin; private bool showLoadedSkinCounts; private int exludedSkinsAuthLevel; private bool hideQuickSort; private string steamApiKey; private int accessOverrideAuthLevel; private bool allowStackedItems; private bool enableCustomPerms; private string permCustomPlayerwearable; private string permCustomWeapon; private string permCustomDeployable; private bool useInbuiltSkins; private bool useApprovedSkins; private int approvedSkinsLimit; private bool useManualAddedSkins; private int maxPagesShown; private bool enableCooldown; private int cooldownBox; private bool cooldownOverrideAdmin; private int cooldownOverrideAuthLevel; private bool activateAfterSkinTaken; private bool enableUsageCost; private bool useServerRewards; private bool useEconomics; private bool useScrap; private int costBoxOpen; private int costWeapon; private int costPlayerwearable; private int costDeployable; private bool costExcludeAdmins; private string costExcludePerm; private bool costExcludePermEnabled; private object GetConfig(string menu, string datavalue, object defaultValue) { Dictionary data = Config[menu] as Dictionary; if (data == null) { data = new Dictionary(); Config[menu] = data; Changed = true; } object value; if (!data.TryGetValue(datavalue, out value)) { value = defaultValue; data[datavalue] = value; Changed = true; } return value; } private object getSkincache() { if (skinsLoaded) return new Dictionary>(skinsCache); else return false; } private void LoadVariables() { useInbuiltSkins = Convert.ToBoolean(GetConfig("AvailableSkins", "useInbuiltSkins", true)); useApprovedSkins = Convert.ToBoolean(GetConfig("AvailableSkins", "useApprovedSkins", false)); approvedSkinsLimit = Convert.ToInt32(GetConfig("AvailableSkins", "approvedSkinsLimit", -1)); useManualAddedSkins = Convert.ToBoolean(GetConfig("AvailableSkins", "useManualAddedSkins", true)); maxPagesShown = Convert.ToInt32(GetConfig("AvailableSkins", "maxPagesShown", 2)); skinBoxCommand = Convert.ToString(GetConfig("Settings", "skinBoxCommand", "skinbox")); altSkinBoxCommand = (List)GetConfig("Settings", "altSkinBoxCommands", new List()); permissionUse = Convert.ToString(GetConfig("Settings", "permissionUse", "skinbox.use")); permissionAdmin = Convert.ToString(GetConfig("Settings", "permissionAdmin", "skinbox.admin")); showLoadedSkinCounts = Convert.ToBoolean(GetConfig("Settings", "showLoadedSkinCounts", true)); exludedSkinsAuthLevel = Convert.ToInt32(GetConfig("Settings", "exludedSkinsAuthLevel", 2)); accessOverrideAuthLevel = Convert.ToInt32(GetConfig("Settings", "accessOverrideAuthLevel", 2)); hideQuickSort = Convert.ToBoolean(GetConfig("Settings", "hideQuickSort", true)); allowStackedItems = Convert.ToBoolean(GetConfig("Settings", "allowStackedItems", false)); steamApiKey = Convert.ToString(GetConfig("Settings", "steamApiKey", "https://steamcommunity.com/dev/apikey << get it THERE and saved it HERE")); enableCustomPerms = Convert.ToBoolean(GetConfig("CustomPermissions", "enableCustomPerms", false)); permCustomPlayerwearable = Convert.ToString(GetConfig("CustomPermissions", "permCustomPlayerwearable", "skinbox.playerwearable")); permCustomWeapon = Convert.ToString(GetConfig("CustomPermissions", "permCustomWeapon", "skinbox.weapon")); permCustomDeployable = Convert.ToString(GetConfig("CustomPermissions", "permCustomDeployable", "skinbox.deployable")); enableCooldown = Convert.ToBoolean(GetConfig("Cooldown", "enableCooldown", false)); cooldownBox = Convert.ToInt32(GetConfig("Cooldown", "cooldownBox", 60)); cooldownOverrideAdmin = Convert.ToBoolean(GetConfig("Cooldown", "cooldownOverrideAdmin", true)); cooldownOverrideAuthLevel = Convert.ToInt32(GetConfig("Cooldown", "cooldownOverrideAuthLevel", 2)); activateAfterSkinTaken = Convert.ToBoolean(GetConfig("Cooldown", "activateAfterSkinTaken", true)); manualAddedSkinsPre = (Dictionary) GetConfig("SkinsAdded", "SkinList", new Dictionary { }); excludedSkinsPre = (List) GetConfig("SkinsExcluded", "SkinList", new List { }); enableUsageCost = Convert.ToBoolean(GetConfig("UsageCost", "enableUsageCost", false)); useServerRewards = Convert.ToBoolean(GetConfig("UsageCost", "useServerRewards", true)); useEconomics = Convert.ToBoolean(GetConfig("UsageCost", "useEconomics", false)); useScrap = Convert.ToBoolean(GetConfig("UsageCost", "useScrap", false)); costBoxOpen = Convert.ToInt32(GetConfig("UsageCost", "costBoxOpen", 5)); costWeapon = Convert.ToInt32(GetConfig("UsageCost", "costWeapon", 30)); costPlayerwearable = Convert.ToInt32(GetConfig("UsageCost", "costPlayerwearable", 20)); costDeployable = Convert.ToInt32(GetConfig("UsageCost", "costDeployable", 10)); costExcludeAdmins = Convert.ToBoolean(GetConfig("UsageCost", "costExcludeAdmins", true)); costExcludePerm = Convert.ToString(GetConfig("UsageCost", "costExcludePerm", "skinbox.costexcluded")); costExcludePermEnabled = Convert.ToBoolean(GetConfig("UsageCost", "costExcludePermEnabled", false)); bool configremoval = false; if ((Config.Get("AvailableSkins") as Dictionary).ContainsKey("useWebskinsRankedByTrend")) { (Config.Get("AvailableSkins") as Dictionary).Remove("useWebskinsRankedByTrend"); (Config.Get("AvailableSkins") as Dictionary).Remove("usedRankedByTrendDays"); (Config.Get("AvailableSkins") as Dictionary).Remove("usedConnectionsToWorkshop"); configremoval = true; } if (!Changed & !configremoval) return; SaveConfig(); Changed = false; configremoval = false; } protected override void LoadDefaultConfig() { Config.Clear(); LoadVariables(); } protected override void LoadDefaultMessages() { lang.RegisterMessages( new Dictionary { {"NoPermission", "You don't have permission to use the SkinBox"}, {"ToNearPlayer", "The SkinBox is currently not usable at this place"}, {"CooldownTime", "You need to wait {0} seconds to re-open the SkinBox again"}, {"NotEnoughBalanceOpenRP", "You need at least '{0}' RP to open the SkinBox"}, {"NotEnoughBalanceOpenEco", "You need at least '{0}' bucks to open the SkinBox"}, {"NotEnoughBalanceOpenScrap", "You need at least '{0}' scrap to open the SkinBox"}, {"NotEnoughBalanceUseRP", "You would need at least '{0}' RP to skin '{1}'"}, {"NotEnoughBalanceUseEco", "You would need at least '{0}' bucks to skin '{1}'"}, {"NotEnoughBalanceUseScrap", "You would need at least '{0}' scrap to skin '{1}'"}, {"NotEnoughBalanceTakeRP", "'{0}' was not skinned. You do not have enough RP"}, {"NotEnoughBalanceTakeEco", "'{0}' was not skinned. You do not have enough bucks"}, {"NotEnoughBalanceTakeScrap", "'{0}' was not skinned. You do not have enough scrap"}, }, this); } private void Loaded() { LoadVariables(); LoadDefaultMessages(); if (allowStackedItems) SbscrbSplt(); else UnsbscrbSplt(); cmd.AddChatCommand(skinBoxCommand, this, "cmdSknBx"); for (int i = 0; i < altSkinBoxCommand.Count; i++) cmd.AddChatCommand(altSkinBoxCommand[i].ToString(), this, "cmdSknBx"); permission.RegisterPermission(permissionAdmin, this); permission.RegisterPermission(permissionUse, this); permission.RegisterPermission(permCustomPlayerwearable, this); permission.RegisterPermission(permCustomWeapon, this); permission.RegisterPermission(permCustomDeployable, this); permission.RegisterPermission(costExcludePerm, this); skinsCache = new Dictionary>(); skinsCacheLimited = new Dictionary>(); approvedSkinsCount = new Dictionary(); NameToItemName = new Dictionary(); ItemNameToName = new Dictionary(); skinsLoaded = false; skinBox = this; if (maxPagesShown < 1) maxPagesShown = 1; maxItemsShown = 42 * maxPagesShown; } private void Unload() { List objs = UnityEngine.Object.FindObjectsOfType().ToList(); if (objs.Count > 0) foreach (SBH obj in objs) { if (obj.looter == null) continue; obj.looter.EndLooting(); obj.PlayerStoppedLooting(obj.looter); UnityEngine.Object.Destroy(obj); } if (Interface.Oxide.IsShuttingDown) return; } private void OnServerInitialized() { if (steamApiKey == null || steamApiKey == string.Empty || steamApiKey.Length != 32) { PrintWarning(_("FxvaObk pbasvt arrqf `fgrnzNcvXrl` sebz `uggcf://fgrnzpbzzhavgl.pbz/qri/ncvxrl` >> Cyhtva haybnqrq")); Interface.Oxide.UnloadPlugin(Name); return; } if (enableUsageCost) { if (ServerRewards != null && useServerRewards) activeServerRewards = true; if (Economics != null && useEconomics) activeEconomics = true; if (useScrap) { scrapItemId = ItemManager.FindItemDefinition("scrap").itemid; activeServerRewards = false; activeEconomics = false; activeScrap = true; } if (activeServerRewards && activeEconomics) activeEconomics = false; if (activeServerRewards || activeEconomics || activeScrap) activePointSystem = true; } if (allowStackedItems && StacksExtended) { _stacksExtendedExtrasDisabled = (bool) StacksExtended.CallHook("DisableExtraFeatures"); if (!_stacksExtendedExtrasDisabled) { Unsubscribe(nameof(CanStackItem)); Unsubscribe(nameof(OnItemSplit)); } else { Subscribe(nameof(CanStackItem)); Subscribe(nameof(OnItemSplit)); } } foreach (Skinnable skin in Skinnable.All.ToList()) { if (skin.Name == null || skin.Name == string.Empty) continue; if (skin.ItemName == null || skin.ItemName == string.Empty) continue; if (!NameToItemName.ContainsKey(skin.Name.ToLower())) NameToItemName.Add(skin.Name.ToLower(), skin.ItemName.ToLower()); if (!ItemNameToName.ContainsKey(skin.ItemName.ToLower())) ItemNameToName.Add(skin.ItemName.ToLower(), skin.Name.ToLower()); } excludedSkins = excludedSkinsPre.ConvertAll(obj => Convert.ToUInt64(obj)); Puts(_("FxvaObk pbzznaq bireivrj: > fxvaobk.pzqf <")); if (useManualAddedSkins) { List s = new List(); foreach (KeyValuePair m in manualAddedSkinsPre) s.AddRange((m.Value as List).ConvertAll(obj => Convert.ToUInt64(obj))); Puts(_("Dhrelvat Fgrnz sbe znahnyyl nqqrq jbexfubc fxvaf")); CllMnlSkinsWb(s, 0); } else { GtItmSkns(); } Initialized = true; } private void FnllyLdd() { skinsLoaded = true; Puts(_("Cyhtva unf svavfurq vzcbegvat nyy fxvaf")); } private void GtItmSkns() { if ((Steamworks.SteamInventory.Definitions?.Length ?? 0) == 0) { PrintWarning("Waiting for Steamworks to update item definitions...."); Steamworks.SteamInventory.OnDefinitionsUpdated += GtItmSkns; return; } Steamworks.SteamInventory.OnDefinitionsUpdated -= GtItmSkns; int countInbuilt = 0; foreach (ItemDefinition itemDef in ItemManager.GetItemDefinitions()) { List skins = new List {0}; if (useInbuiltSkins) skins.AddRange(ItemSkinDirectory.ForItem(itemDef).Select(skin => Convert.ToUInt64(skin.id))); skinsCache.Add(itemDef.shortname, new LinkedList(skins)); if (skins.Count > 1) countInbuilt += skins.Count - 1; } if (showLoadedSkinCounts && useInbuiltSkins) Puts(_("Ybnqrq {0} vaohvyg fxvaf"), countInbuilt); if (useManualAddedSkins) { int countManual = 0; foreach (KeyValuePair> manualskins in manualAddedSkins) { string shortname = manualskins.Key; HashSet fileids = manualskins.Value; foreach (ulong fileid in fileids) { if (!skinsCache.ContainsKey(shortname)) { skinsCache.Add(shortname, new LinkedList()); skinsCache[shortname].AddFirst(0); } if (!skinsCache[shortname].Contains(fileid)) { skinsCache[shortname].AddAfter(skinsCache[shortname].First, fileid); countManual++; } } } if (showLoadedSkinCounts && countManual > 0) Puts(_("Ybnqrq {0} znahny nqqrq fxvaf"), countManual); } if (useApprovedSkins) { ChckApprvdSkns(); return; } FnllyLdd(); } private string BldDtlsSt(List list, int pg) { int st = pg * 100; int ed = st + 100 > list.Count ? list.Count : st + 100; string details = string.Format(_("?xrl={0}&vgrzpbhag={1}"), steamApiKey, ed - st); for (int i = st; i < ed; i++) details += string.Format(_("&choyvfurqsvyrvqf[{0}]={1}"), i - st, list[i]); return details; } private void CllMnlSkinsWb(List i, int pg) { int ttlPgs = Mathf.CeilToInt((float)i.Count / 100f) - 1; string b = BldDtlsSt(i, pg); try { webrequest.Enqueue(u1, b, (cd, res) => ServerMgr.Instance.StartCoroutine(PrfMnlSkinsWb(cd, res, i, pg, ttlPgs)), this, RequestMethod.POST); } catch { GtItmSkns(); } } private IEnumerator PrfMnlSkinsWb(int cd, string res, List i, int pg, int ttlPgs) { if (res != null && cd == 200) { GtPblshdFlDtls pfd = JsonConvert.DeserializeObject(res); if (pfd != null && pfd.response != null && pfd.response.publishedfiledetails?.Count > 0) { Puts(string.Format(_("Cebprffvat jbexfubc erfcbafr. Cntr: {0} / {1}"), pg + 1, ttlPgs + 1)); foreach (GtPblshdFlDtls.Response.Publishedfiledetail det in pfd.response.publishedfiledetails) { if (det.tags != null && det.tags.Count > 2) { foreach (GtPblshdFlDtls.Tag tag in det.tags) { string t = tag.tag.ToLower(); string sn = string.Empty; if (NameToItemName.ContainsKey(t)) sn = NameToItemName[t]; else continue; skinWorkshopNames[det.publishedfileid] = det.title; if (!manualAddedSkins.ContainsKey(sn)) manualAddedSkins.Add(sn, new HashSet()); if (!manualAddedSkins[sn].Contains(det.publishedfileid)) manualAddedSkins[sn].Add(det.publishedfileid); } } } yield return CoroutineEx.waitForEndOfFrame; yield return CoroutineEx.waitForEndOfFrame; if (pg < ttlPgs) { CllMnlSkinsWb(i, pg + 1); yield break; } } } if (pg < ttlPgs) { CllMnlSkinsWb(i, pg + 1); yield break; } else GtItmSkns(); } private void ChckApprvdSkns() { int count = 0; List itemSkinDirectory = Facepunch.Pool.GetList(); itemSkinDirectory.AddRange(ItemSkinDirectory.Instance.skins.Select(x => x.id)); foreach (InventoryDef item in Steamworks.SteamInventory.Definitions) { string shortname = item.GetProperty("itemshortname"); if (string.IsNullOrEmpty(shortname) || item.Id < 100) continue; ulong wsid; if (itemSkinDirectory.Contains(item.Id)) wsid = (ulong)item.Id; else { if (!ulong.TryParse(item.GetProperty("workshopid"), out wsid)) continue; } skinWorkshopNames[wsid] = item.Name; if (!approvedSkinsCount.ContainsKey(shortname)) approvedSkinsCount[shortname] = 0; if (approvedSkinsLimit > 0 && approvedSkinsCount[shortname] >= approvedSkinsLimit) { if (!skinsCacheLimited.ContainsKey(shortname)) skinsCacheLimited[shortname] = new LinkedList(); skinsCacheLimited[shortname].AddLast(wsid); } if (skinsCacheLimited.ContainsKey(shortname) && skinsCacheLimited[shortname].Contains(wsid)) continue; if (!skinsCache.ContainsKey(shortname)) skinsCache[shortname] = new LinkedList(); if (!skinsCache[shortname].Contains(wsid) && skinsCache[shortname].Count < maxItemsShown) { skinsCache[shortname].AddLast(wsid); approvedSkinsCount[shortname]++; count++; } } Facepunch.Pool.FreeList(ref itemSkinDirectory); if (showLoadedSkinCounts && count > 0) { Puts(_("Vzcbegrq {0} nccebirq fxvaf sbe '{1}' glcrf"), count, skinsCache.Where(c => c.Value.Count > 1).ToList().Count); } FnllyLdd(); } //void ChckApprvdSknsWb(int cd, string res) //{ // if (res == null || cd != 200) // { // FnllyLdd(); // return; // } // var schm = JsonConvert.DeserializeObject(res); // if (schm == null || !(schm is Rust.Workshop.ItemSchema) || schm.items.Length == 0) // { // FnllyLdd(); // return; // } // int count = 0; // foreach (var item in schm.items) // { // if (string.IsNullOrEmpty(item.itemshortname) || string.IsNullOrEmpty(item.workshopid) || string.IsNullOrEmpty(item.workshopdownload)) // continue; // ulong wsid = Convert.ToUInt64(item.workshopid); // skinWorkshopNames[wsid] = item.name; // string shortname = item.itemshortname; // if (!approvedSkinsCount.ContainsKey(shortname)) // approvedSkinsCount[shortname] = 0; // if (approvedSkinsLimit > 0 && approvedSkinsCount[shortname] >= approvedSkinsLimit) // { // if (!skinsCacheLimited.ContainsKey(shortname)) // skinsCacheLimited[shortname] = new LinkedList(); // skinsCacheLimited[shortname].AddLast(wsid); // } // if (skinsCacheLimited.ContainsKey(shortname) && skinsCacheLimited[shortname].Contains(wsid)) // continue; // if (!skinsCache.ContainsKey(shortname)) // skinsCache[shortname] = new LinkedList(); // if (!skinsCache[shortname].Contains(wsid) && skinsCache[shortname].Count < maxItemsShown) // { // skinsCache[shortname].AddLast(wsid); // approvedSkinsCount[shortname]++; // count++; // } // } // if (showLoadedSkinCounts && count > 0) // Puts(_("Vzcbegrq {0} nccebirq fxvaf sbe '{1}' glcrf"), count, skinsCache.Where(c => c.Value.Count > 1).ToList().Count); // FnllyLdd(); //} [ConsoleCommand("skinbox.cmds")] private void cmdListCmds(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; StringBuilder sb = new StringBuilder(); sb.AppendLine("\n> SkinBox command overview <"); TextTable textTable = new TextTable(); textTable.AddColumn("Command"); textTable.AddColumn("Description"); textTable.AddRow(new string[] {"skinbox.addskin", "Does add one or multiple skin-id\'s to the manual skin list"}); textTable.AddRow(new string[] {"skinbox.removeskin", "Does remove one or multiple skin-id\'s from the manual skin list"}); textTable.AddRow(new string[] {"skinbox.addexcluded", "Does add one or multiple skin-id\'s to the exclusion list (for players)"}); textTable.AddRow(new string[] {"skinbox.removeexcluded", "Does remove one or multiple skin-id\'s from the exclusion list"}); textTable.AddRow(new string[] {"skinbox.addcollection", "Adds a whole skin-collection to the manual skins list"}); textTable.AddRow(new string[] {"skinbox.removecollection", "Removes a whole collection from the manual skin list"}); sb.AppendLine(textTable.ToString()); SendReply(arg, sb.ToString()); } [ConsoleCommand("skinbox.addskin")] private void consoleAddSkin(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; if (arg.Args == null || arg.Args.Length < 1) { SendReply(arg, "You need to type in one or more Workshop FileId's"); return; } List fileIds = new List(); for (int i = 0; i < arg.Args.Length; i++) { ulong fileId = 0uL; if (!ulong.TryParse(arg.Args[i], out fileId)) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not a number"); continue; } else { if (arg.Args[i].Length < 9 || arg.Args[i].Length > 10) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not 9/10-Digits"); continue; } fileIds.Add(fileId); } } CallSkinsImportWeb(fileIds, arg); } [ConsoleCommand("skinbox.removeskin")] private void consoleRemoveSkin(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; if (arg.Args == null || arg.Args.Length < 1) { SendReply(arg, "You need to type in one or more Workshop FileId's"); return; } List fileIds = new List(); for (int i = 0; i < arg.Args.Length; i++) { ulong fileId = 0uL; if (!ulong.TryParse(arg.Args[i], out fileId)) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not a number"); continue; } else { if (arg.Args[i].Length < 9 || arg.Args[i].Length > 10) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not 9/10-Digits"); continue; } fileIds.Add(fileId); } } bool doSave = false; int removed = 0; foreach (KeyValuePair> addedSkins in manualAddedSkins) { foreach (ulong fileId in fileIds) { if (addedSkins.Value.Contains(fileId)) { manualAddedSkins[addedSkins.Key].Remove(fileId); skinsCache[addedSkins.Key].Remove(fileId); removed++; doSave = true; } } } if (doSave) { Config["SkinsAdded", "SkinList"] = manualAddedSkins; Config.Save(); SendReply(arg, $"Removed {removed} FileId's"); } } private void CallSkinsImportWeb(List i, ConsoleSystem.Arg arg = null) { string b = string.Format(_("?xrl={0}&vgrzpbhag={1}"), steamApiKey, i.Count); int p = 0; foreach (ulong f in i) { b += string.Format(_("&choyvfurqsvyrvqf[{0}]={1}"), p, f); p++; } try { webrequest.Enqueue(u1, b, (cd, res) => ProofSkinsImportWeb(cd, res, arg), this, RequestMethod.POST); } catch { } } private void ProofSkinsImportWeb(int cd, string res, ConsoleSystem.Arg arg = null) { if (res == null || cd != 200) return; GtPblshdFlDtls pfd = JsonConvert.DeserializeObject(res); if (pfd == null || !(pfd is GtPblshdFlDtls) || pfd.response.result == 0 || pfd.response.resultcount == 0) return; bool doSave = false; foreach (GtPblshdFlDtls.Response.Publishedfiledetail det in pfd.response.publishedfiledetails) { if (det.tags != null && det.tags.Count > 2) { string sn = string.Empty; ulong wsid = det.publishedfileid; foreach (GtPblshdFlDtls.Tag tag in det.tags) { string t = tag.tag.ToLower(); if (NameToItemName.ContainsKey(t)) sn = NameToItemName[t]; else continue; if (manualAddedSkins.ContainsKey(sn)) { if (manualAddedSkins[sn].Contains(wsid)) { SndRplyCl(arg, $"'{det.title} ({wsid})' was already added"); continue; } } if (skinsCache.ContainsKey(sn)) { if ((skinsCache[sn] as LinkedList).Contains(wsid)) { SndRplyCl(arg, $"'{det.title} ({wsid})' belongs already to approved/ranked"); continue; } } if (!manualAddedSkins.ContainsKey(sn)) manualAddedSkins.Add(sn, new HashSet()); manualAddedSkins[sn].Add(wsid); if (!skinsCache.ContainsKey(sn)) { skinsCache.Add(sn, new LinkedList()); skinsCache[sn].AddLast(0); } skinsCache[sn].AddAfter(skinsCache[sn].First, wsid); skinWorkshopNames[wsid] = det.title; SndRplyCl(arg, $"'{det.title} ({wsid})' added to the list for '{sn}'"); doSave = true; } } } if (doSave) { Config["SkinsAdded", "SkinList"] = manualAddedSkins; Config.Save(); } } [ConsoleCommand("skinbox.addexcluded")] private void consoleAddExcluded(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; if (arg.Args == null || arg.Args.Length < 1) { SendReply(arg, "You need to type in one or more Workshop FileId's"); return; } List fileIds = new List(); for (int i = 0; i < arg.Args.Length; i++) { ulong fileId = 0uL; if (!ulong.TryParse(arg.Args[i], out fileId)) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not a number"); continue; } else { if (arg.Args[i].Length < 9 || arg.Args[i].Length > 10) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not 9/10-Digits"); continue; } fileIds.Add(fileId); } } int countAdded = 0; foreach (ulong fileId in fileIds) if (!excludedSkins.Contains(fileId)) { excludedSkins.Add(fileId); countAdded++; } if (countAdded > 0) { Config["SkinsExcluded", "SkinList"] = excludedSkins; Config.Save(); SendReply(arg, $"Added {countAdded} skins to exclusion list"); } } [ConsoleCommand("skinbox.removeexcluded")] private void consoleRemoveExcluded(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; if (arg.Args == null || arg.Args.Length < 1) { SendReply(arg, "You need to type in one or more Workshop FileId's"); return; } List fileIds = new List(); for (int i = 0; i < arg.Args.Length; i++) { ulong fileId = 0uL; if (!ulong.TryParse(arg.Args[i], out fileId)) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not a number"); continue; } else { if (arg.Args[i].Length < 9 || arg.Args[i].Length > 10) { SendReply(arg, $"Ignored '{arg.Args[i]}' as of not 9/10-Digits"); continue; } fileIds.Add(fileId); } } int countRemoved = 0; foreach (ulong fileId in fileIds) if (excludedSkins.Contains(fileId)) { excludedSkins.Remove(fileId); countRemoved++; } if (countRemoved > 0) { Config["SkinsExcluded", "SkinList"] = excludedSkins; Config.Save(); SndRplyCl(arg, $"Removed {countRemoved} skins from exclusion"); } } [ConsoleCommand("skinbox.addcollection")] private void consoleAddCollection(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; if (arg.Args == null || arg.Args.Length < 1) { SendReply(arg, "You need to type in a valid collection id"); return; } ulong collId = 0; if (!ulong.TryParse(arg.Args[0], out collId)) { SendReply(arg, $"Collection ID not correct: '{arg.Args[0]}' is not a number"); return; } else { if (arg.Args[0].Length < 9 || arg.Args[0].Length > 10) { SendReply(arg, $"Collection ID not correct: '{arg.Args[0]}' has not 9/10-Digits"); return; } } string b = string.Format(_("?xrl={0}&pbyyrpgvbapbhag=1&choyvfurqsvyrvqf[0]={1}"), steamApiKey, arg.Args[0]); try { webrequest.Enqueue(u2, b, (cd, res) => PstCllbckAdd(cd, res, arg), this, RequestMethod.POST); } catch { SndRplyCl(arg, "Steam webrequest failed!"); } } public void PstCllbckAdd(int cd, string res, ConsoleSystem.Arg arg = null) { if (res == null || cd != 200) { SndRplyCl(arg, "Steam webrequest failed by wrong response!"); return; } GtCllctnDtls col = JsonConvert.DeserializeObject(res); if (col == null || !(col is GtCllctnDtls)) { SndRplyCl(arg, "No Collection data received!"); return; } if (col.response.resultcount == 0 || col.response.collectiondetails == null || col.response.collectiondetails.Count == 0 || col.response.collectiondetails[0].result != 1) { SndRplyCl(arg, "The Steam collection could not be found!"); return; } List fileIds = new List(); foreach (GtCllctnDtls.Response.Collectiondetail.Child child in col.response.collectiondetails[0].children) try { fileIds.Add(Convert.ToUInt64(child.publishedfileid)); } catch { } if (fileIds.Count == 0) { SndRplyCl(arg, "No skin numbers found. Workshop search cancelled."); return; } CallSkinsImportWeb(fileIds, arg); } [ConsoleCommand("skinbox.removecollection")] private void consoleRemoveCollection(ConsoleSystem.Arg arg) { if (arg.Connection != null && (arg.Connection.authLevel < 2 && !permission.UserHasPermission(arg.Connection.userid.ToString(), permissionAdmin))) return; if (arg.Args == null || arg.Args.Length < 1) { SendReply(arg, "You need to type in a valid collection id"); return; } ulong collId = 0; if (!ulong.TryParse(arg.Args[0], out collId)) { SendReply(arg, $"Collection ID not correct: '{arg.Args[0]}' is not a number"); return; } else { if (arg.Args[0].Length < 9 || arg.Args[0].Length > 10) { SendReply(arg, $"Collection ID not correct: '{arg.Args[0]}' has not 9/10-Digits"); return; } } string b = string.Format(_("?xrl={0}&pbyyrpgvbapbhag=1&choyvfurqsvyrvqf[0]={1}"), steamApiKey, arg.Args[0]); try { webrequest.Enqueue(u2, b, (cd, res) => PostCallbackRemove(cd, res, arg), this, RequestMethod.POST); } catch { SndRplyCl(arg, "Steam webrequest failed!"); } } public void PostCallbackRemove(int cd, string res, ConsoleSystem.Arg arg = null) { if (res == null || cd != 200) { SndRplyCl(arg, "Steam webrequest failed by wrong response!"); return; } GtCllctnDtls col = JsonConvert.DeserializeObject(res); if (col == null || !(col is GtCllctnDtls)) { SndRplyCl(arg, "No Collection data received!"); return; } if (col.response.resultcount == 0 || col.response.collectiondetails == null || col.response.collectiondetails.Count == 0 || col.response.collectiondetails[0].result != 1) { SndRplyCl(arg, "The Steam collection could not be found!"); return; } List fileIds = new List(); foreach (GtCllctnDtls.Response.Collectiondetail.Child child in col.response.collectiondetails[0].children) try { fileIds.Add(Convert.ToUInt64(child.publishedfileid)); } catch { } if (fileIds.Count == 0) { SndRplyCl(arg, "No skin numbers found. Workshop search cancelled."); return; } int removed = 0; foreach (KeyValuePair> addSkins in new Dictionary>(manualAddedSkins)) { foreach (ulong skin in addSkins.Value.ToList()) { if (fileIds.Contains(skin)) { manualAddedSkins[addSkins.Key].Remove(skin); if (skinsCache.ContainsKey(addSkins.Key)) skinsCache[addSkins.Key].Remove(skin); removed++; } } } if (removed > 0) { SndRplyCl(arg, $"Removed '{removed}' manual skins by collection remove."); Config["SkinsAdded", "SkinList"] = manualAddedSkins; Config.Save(); } else { SndRplyCl(arg, $"No manual skins to remove by collection remove."); } } [ConsoleCommand("skinbox.open")] private void consoleSkinboxOpen(ConsoleSystem.Arg arg) { if (arg == null) return; if (arg.Connection == null) { if (arg.Args == null || arg.Args.Length == 0) { SendReply(arg, $"'skinbox.open' cmd needs a passed steamid "); return; } ulong argId = 0uL; if (!ulong.TryParse(arg.Args[0], out argId)) { SendReply(arg, $"'skinbox.open' cmd for '{arg.Args[0]}' failed (no valid number)"); return; } BasePlayer argPlayer = BasePlayer.FindByID(argId); if (argPlayer == null) { SendReply(arg, $"'skinbox.open' cmd for userID '{argId}' failed (player not found)"); return; } if (!argPlayer.inventory.loot.IsLooting()) OpnSknBx(argPlayer); } else if (arg.Connection != null && arg.Connection.player != null) { BasePlayer player = arg.Player(); if (player.inventory.loot.IsLooting()) return; if (!(player.IsAdmin || player.net.connection.authLevel >= accessOverrideAuthLevel) && !permission.UserHasPermission(player.UserIDString, permissionUse)) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (!ChckOpnBlnc(player)) return; if (enableCooldown && !(cooldownOverrideAdmin && (player.IsAdmin || player.net.connection.authLevel >= cooldownOverrideAuthLevel))) { DateTime now = DateTime.UtcNow; DateTime time; string key = player.UserIDString + "-box"; if (cooldownTimes.TryGetValue(key, out time)) if (time > now.AddSeconds(-cooldownBox)) { player.ChatMessage(string.Format(lang.GetMessage("CooldownTime", this, player.UserIDString), (time - now.AddSeconds(-cooldownBox)).Seconds)); return; } } OpnSknBx(player); } } private void cmdSknBx(BasePlayer player, string command, string[] args) { if (player.inventory.loot.IsLooting()) return; if (!(player.IsAdmin || player.net.connection.authLevel >= accessOverrideAuthLevel) && !permission.UserHasPermission(player.UserIDString, permissionUse)) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (!ChckOpnBlnc(player)) return; if (enableCooldown && !(cooldownOverrideAdmin && (player.IsAdmin || player.net.connection.authLevel >= cooldownOverrideAuthLevel))) { DateTime now = DateTime.UtcNow; DateTime time; string key = player.UserIDString + "-box"; if (cooldownTimes.TryGetValue(key, out time)) if (time > now.AddSeconds(-cooldownBox)) { player.ChatMessage(string.Format(lang.GetMessage("CooldownTime", this, player.UserIDString), (time - now.AddSeconds(-cooldownBox)).Seconds)); return; } } timer.Once(0.2f, () => { OpnSknBx(player); }); } public bool ChckOpnBlnc(BasePlayer player) { if (!activePointSystem || costBoxOpen <= 0 || player.IsAdmin && costExcludeAdmins || costExcludePermEnabled && permission.UserHasPermission(player.UserIDString, costExcludePerm)) return true; int playerMoney = 0; if (activeServerRewards) playerMoney = (int)(Interface.Oxide.CallHook("CheckPoints", player.userID) ?? 0); if (activeEconomics) playerMoney = Convert.ToInt32((double)(Interface.Oxide.CallHook("Balance", player.UserIDString) ?? 0.0)); if (activeScrap) playerMoney = player.inventory.GetAmount(scrapItemId); if (playerMoney < costBoxOpen) { player.ChatMessage(string.Format(lang.GetMessage(activeServerRewards ? "NotEnoughBalanceOpenRP" : activeEconomics ? "NotEnoughBalanceOpenEco" : "NotEnoughBalanceOpenScrap", this, player.UserIDString), costBoxOpen)); return false; } if (activeServerRewards) Interface.Oxide.CallHook("TakePoints", player.userID, costBoxOpen); if (activeEconomics) Interface.Oxide.CallHook("Withdraw", player.userID, Convert.ToDouble(costBoxOpen)); if (activeScrap) player.inventory.Take(null, scrapItemId, costBoxOpen); return true; } public bool ChckSknBlnc(BasePlayer player, Item item) { if (!activePointSystem || player.IsAdmin && costExcludeAdmins || costExcludePermEnabled && permission.UserHasPermission(player.UserIDString, costExcludePerm)) return true; int playerMoney = 0; if (activeServerRewards) playerMoney = (int) (Interface.Oxide.CallHook("CheckPoints", player.userID) ?? 0); if (activeEconomics) playerMoney = Convert.ToInt32((double) (Interface.Oxide.CallHook("Balance", player.UserIDString) ?? 0.0)); if (activeScrap) playerMoney = player.inventory.GetAmount(scrapItemId); bool hasBalance = false; int getCost = 0; switch (item.info.category.ToString()) { case "Weapon": case "Tool": if (costWeapon <= 0 || playerMoney > costWeapon) hasBalance = true; getCost = costWeapon; break; case "Attire": if (costPlayerwearable <= 0 || playerMoney > costPlayerwearable) hasBalance = true; getCost = costPlayerwearable; break; case "Items": case "Construction": if (costDeployable <= 0 || playerMoney > costDeployable) hasBalance = true; getCost = costDeployable; break; default: hasBalance = true; break; } if (!hasBalance) { player.ChatMessage(string.Format(lang.GetMessage(activeServerRewards ? "NotEnoughBalanceUseRP" : activeEconomics ? "NotEnoughBalanceUseEco" : "NotEnoughBalanceUseScrap", this, player.UserIDString), getCost, item.info.displayName.translated)); return false; } return true; } public bool WthdrwBlnc(BasePlayer player, Item item) { if (!activePointSystem || player.IsAdmin && costExcludeAdmins || costExcludePermEnabled && permission.UserHasPermission(player.UserIDString, costExcludePerm)) return true; int getCost = 0; switch (item.info.category.ToString()) { case "Weapon": case "Tool": getCost = costWeapon; break; case "Attire": getCost = costPlayerwearable; break; case "Items": case "Construction": getCost = costDeployable; break; default: break; } bool hadMoney = false; if (activeServerRewards && (bool) Interface.Oxide.CallHook("TakePoints", player.userID, getCost)) hadMoney = true; if (activeEconomics && (bool) Interface.Oxide.CallHook("Withdraw", player.userID, Convert.ToDouble(getCost))) hadMoney = true; if (player.inventory.GetAmount(scrapItemId) >= getCost) { player.inventory.Take(null, scrapItemId, getCost); hadMoney = true; } if (!hadMoney) { player.ChatMessage(string.Format(lang.GetMessage(activeServerRewards ? "NotEnoughBalanceTakeRP" : activeEconomics ? "NotEnoughBalanceTakeEco" : "NotEnoughBalanceTakeScrap", this, player.UserIDString), item.info.displayName.translated)); return false; } return true; } internal class SBH : FacepunchBehaviour { public bool isCreating; public bool isBlocked; public bool isEmptied; public int itemId; public int itemAmount; public Item currentItem; public BasePlayer looter; public ItemContainer loot; public BaseEntity entityOwner; public ulong skinId; public int currentPage; public int totalPages; public LinkedList itemSkins; public int skinsTotal; public int perPageTotal; public int maxPages; public bool refundItem; public int lastItemAmount; public Item lastItemRemoved; private void Awake() { isCreating = false; isBlocked = false; isEmptied = false; skinId = 0uL; currentPage = 1; totalPages = 1; skinsTotal = 1; perPageTotal = 1; itemAmount = 1; maxPages = skinBox.maxPagesShown; itemSkins = new LinkedList(); } public void ShwUi() { if (totalPages > 1 && maxPages > 1) { int p = Math.Min(maxPages, totalPages); skinBox.CrtUi(looter, currentPage, p); } } public void ClsUi() { skinBox.DstryUi(looter); } public void PgNxt() { if (totalPages > 1 && currentPage < maxPages && currentPage < totalPages && !isCreating) { currentPage++; FllSknBx(currentPage); ShwUi(); } } public void PgPrv() { if (totalPages > 1 && currentPage > 1 && !isCreating) { currentPage--; FllSknBx(currentPage); ShwUi(); } } public void StrtNwItm(ItemContainer container, Item item) { isBlocked = true; currentItem = item; lastItemAmount = 0; lastItemRemoved = null; itemAmount = item.amount; itemId = item.info.itemid; skinId = item.skin; string shortname = currentItem.info.shortname == _("evsyr.ye300") ? _("ye300.vgrz") : currentItem.info.shortname; itemSkins = new LinkedList(skinBox.skinsCache[shortname] as LinkedList); itemSkins.Remove(0uL); itemSkins.Remove(skinId); skinsTotal = itemSkins.Count; perPageTotal = skinId == 0uL ? 41 : 40; currentPage = 1; totalPages = Mathf.CeilToInt(skinsTotal / (float) perPageTotal); loot = container; entityOwner = loot.entityOwner; } public void FllSknBx(int page = 1) { isCreating = true; string origname = currentItem.info.shortname; bool hasCondition = currentItem.hasCondition; float condition = currentItem.condition; float maxCondition = currentItem.maxCondition; bool isWeapon = currentItem.GetHeldEntity() is BaseProjectile; bool hasMods = false; int contents = 0; int capacity = 0; ItemDefinition ammoType = null; Dictionary itemMods = new Dictionary(); if (isWeapon) { contents = (currentItem.GetHeldEntity() as BaseProjectile).primaryMagazine.contents; capacity = (currentItem.GetHeldEntity() as BaseProjectile).primaryMagazine.capacity; ammoType = (currentItem.GetHeldEntity() as BaseProjectile).primaryMagazine.ammoType; if (currentItem.contents != null && currentItem.contents.itemList.Count > 0) { hasMods = true; foreach (Item mod in currentItem.contents.itemList) itemMods.Add(mod.info.itemid, mod.condition); } } isEmptied = false; if (currentItem.contents != null && currentItem.contents.itemList.Count > 0) { Item[] array = currentItem.contents.itemList.ToArray(); for (int i = 0; i < array.Length; i++) { if (array[i].info.category == ItemCategory.Weapon) continue; Item item = array[i]; looter.inventory.GiveItem(item, null); } } skinBox.RmvItm(loot, currentItem); skinBox.ClrCntnr(loot); int startIndex = page * perPageTotal - perPageTotal; int amount = page < totalPages ? perPageTotal : skinsTotal - ((page - 1) * perPageTotal);// page == totalPages ? lastPageCount : perPageTotal; List skins = new List {0uL}; if (skinId != 0uL) skins.Add(skinId); if (maxPages > 1 && totalPages > 1) skins.AddRange(itemSkins.ToList().GetRange(startIndex, amount)); else skins.AddRange(itemSkins.ToList()); loot.capacity = skins.Count(); ItemDefinition itemDef = ItemManager.FindItemDefinition(origname); loot.capacity = Mathf.Min(42, skins.Count); foreach (ulong skin in skins) { if (loot.IsFull()) break; if (skinBox.excludedSkins.Contains(skin) && looter.net.connection.authLevel < skinBox.exludedSkinsAuthLevel) continue; Item newItem = ItemManager.Create(itemDef, 1, skin); if (skinBox.skinWorkshopNames.ContainsKey(skin)) newItem.name = skinBox.skinWorkshopNames[skin]; if (hasCondition) { newItem.condition = condition; newItem.maxCondition = maxCondition; } if (isWeapon) { BaseProjectile gun = newItem.GetHeldEntity() as BaseProjectile; gun.primaryMagazine.contents = contents; gun.primaryMagazine.capacity = capacity; gun.primaryMagazine.ammoType = ammoType; if (hasMods) { foreach (KeyValuePair mod in itemMods) { Item newMod = ItemManager.CreateByItemID((int) mod.Key, 1); newMod.condition = Convert.ToSingle(mod.Value); newMod.MoveToContainer(newItem.contents, -1, false); } newItem.contents.SetFlag(ItemContainer.Flag.IsLocked, true); newItem.contents.SetFlag(ItemContainer.Flag.NoItemInput, true); newItem.contents.MarkDirty(); } } newItem.MarkDirty(); skinBox.InsrtItm(loot, newItem); } isCreating = false; loot.MarkDirty(); } public void PlayerStoppedLooting(BasePlayer player) { if (!isEmptied && currentItem != null) { isEmptied = true; if (refundItem) player.GiveItem(currentItem); } if (!GetComponent().IsDestroyed) GetComponent().Kill(BaseNetworkable.DestroyMode.None); if (skinBox.enableCooldown) skinBox.cooldownTimes[player.UserIDString + "-box"] = DateTime.UtcNow; } private void OnDestroy() { skinBox.DstryUi(looter); skinBox.activeSkinBoxes.Remove(looter.userID); if (!isEmptied && currentItem != null) { isEmptied = true; looter.GiveItem(currentItem); } looter.EndLooting(); } } private void OpnSknBx(BasePlayer player, bool refundItem = true) { BaseEntity skinBox = GameManager.server.CreateEntity(StringPool.Get(4080262419), player.transform.position - new Vector3(0, 250f + UnityEngine.Random.Range(-25f, 25f), 0)); (skinBox as BaseNetworkable).limitNetworking = true; UnityEngine.Object.Destroy(skinBox.GetComponent()); UnityEngine.Object.Destroy(skinBox.GetComponent()); skinBox.Spawn(); SBH lootHandler = skinBox.gameObject.AddComponent(); lootHandler.looter = player; lootHandler.refundItem = refundItem; StorageContainer container = skinBox.GetComponent(); if (!allowStackedItems) { container.maxStackSize = 1; container.inventory.maxStackSize = 1; } container.inventory.capacity = 1; container.SetFlag(BaseEntity.Flags.Open, true, false); if (QuickSort && hideQuickSort) StrtLtngEntty(player.inventory.loot, container); else player.inventory.loot.StartLootingEntity(container, false); player.inventory.loot.AddContainer(container.inventory); player.inventory.loot.SendImmediate(); player.ClientRPCPlayer(null, player, _("ECP_BcraYbbgCnary"), _("trarevpynetr")); container.SendNetworkUpdate(BasePlayer.NetworkQueue.Update); activeSkinBoxes.Add(player.userID, lootHandler); } public void StrtLtngEntty(PlayerLoot loot, BaseEntity targetEntity) { loot.Clear(); if (!targetEntity) return; loot.PositionChecks = false; loot.entitySource = targetEntity; loot.itemSource = null; loot.MarkDirty(); } public void ClrCntnr(ItemContainer container) { while (container.itemList.Count > 0) { Item removeItem = container.itemList[0]; //if (removeItem.contents?.itemList?.Count > 0) // ClrCntnr(removeItem.contents); RmvItm(container, removeItem); //removeItem.RemoveFromContainer(); removeItem.Remove(0f); } } private object CanAcceptItem(ItemContainer container, Item item) { if (container.entityOwner == null) return null; SBH lootHandler; if ((lootHandler = container.entityOwner.GetComponent()) == null) return null; string shortname = item.info.shortname == _("evsyr.ye300") ? _("ye300.vgrz") : item.info.shortname; if (lootHandler.isCreating || lootHandler.isBlocked || enableCustomPerms && !ChckItmPrms(lootHandler.looter, item) || item.isBroken || !skinsCache.ContainsKey(shortname) || (skinsCache[shortname] as LinkedList).Count <= 1 || !ChckSknBlnc(lootHandler.looter, item)) return ItemContainer.CanAcceptResult.CannotAccept; return null; } public bool ChckItmPrms(BasePlayer player, Item item) { string category = item.info.category.ToString(); switch (category) { case "Weapon": if (permission.UserHasPermission(player.UserIDString, permCustomWeapon)) return true; break; case "Tool": if (permission.UserHasPermission(player.UserIDString, permCustomWeapon)) return true; break; case "Attire": if (permission.UserHasPermission(player.UserIDString, permCustomPlayerwearable)) return true; break; case "Items": if (permission.UserHasPermission(player.UserIDString, permCustomDeployable)) return true; break; case "Construction": if (permission.UserHasPermission(player.UserIDString, permCustomDeployable)) return true; break; default: return true; } return false; } private void OnItemAddedToContainer(ItemContainer container, Item item) { if (container == null || item == null) return; if (container.entityOwner != null) { SBH lootHandler = container.entityOwner.GetComponent(); if (lootHandler == null || lootHandler.isBlocked) return; lootHandler.StrtNwItm(container, item); lootHandler.FllSknBx(); if (maxPagesShown > 1) lootHandler.ShwUi(); } } private object CanMoveItem(Item movedItem, PlayerInventory inventory, uint targetContainerID, int targetSlot, int amount) { if (movedItem.parent?.entityOwner != null) { SBH lootHandler = movedItem.parent?.entityOwner?.GetComponent(); if (lootHandler != null) { if (lootHandler.itemAmount > 1) { ItemContainer targetContainer = inventory.FindContainer(targetContainerID); if (targetContainer != null && targetContainer.GetSlot(targetSlot) != null) return false; } } } return null; } public bool InsrtItm(ItemContainer container, Item item, bool mark = false) { if (container.itemList.Contains(item)) return false; if (container.IsFull()) return false; container.itemList.Add(item); item.parent = container; if (!container.FindPosition(item)) return false; if (mark) container.MarkDirty(); if (container.onItemAddedRemoved != null) container.onItemAddedRemoved(item, true); return true; } public bool RmvItm(ItemContainer container, Item item, bool mark = false) { if (!container.itemList.Contains(item)) return false; if (container.onPreItemRemove != null) container.onPreItemRemove(item); container.itemList.Remove(item); item.parent = null; if (mark) container.MarkDirty(); if (container.onItemAddedRemoved != null) container.onItemAddedRemoved(item, false); return true; } private void OnItemRemovedFromContainer(ItemContainer container, Item item) { if (container == null || item == null || container.entityOwner == null) return; SBH lootHandler = container.entityOwner.GetComponent(); if (lootHandler == null || !lootHandler.isBlocked) return; if (item.GetHeldEntity() is BaseProjectile && item.contents != null) { item.contents.SetFlag(ItemContainer.Flag.IsLocked, false); item.contents.SetFlag(ItemContainer.Flag.NoItemInput, false); } if (lootHandler.itemAmount > 1) { item.amount = lootHandler.itemAmount; item.MarkDirty(); lootHandler.lastItemRemoved = item; lootHandler.lastItemAmount = lootHandler.itemAmount; lootHandler.itemAmount = 1; } ClrCntnr(container); if (lootHandler.currentItem != null) { lootHandler.currentItem.Remove(0f); lootHandler.currentItem = null; } container.MarkDirty(); lootHandler.isEmptied = true; lootHandler.ClsUi(); container.capacity = 1; if (item.skin == 0uL) { lootHandler.skinId = 0uL; lootHandler.isBlocked = false; return; } if (!WthdrwBlnc(lootHandler.looter, item)) { item.skin = lootHandler.skinId; if (item.GetHeldEntity()) item.GetHeldEntity().skinID = lootHandler.skinId; item.MarkDirty(); } if (enableCooldown && activateAfterSkinTaken && !(cooldownOverrideAdmin && (lootHandler.looter.IsAdmin || lootHandler.looter.net.connection.authLevel >= cooldownOverrideAuthLevel) ) && item.skin != lootHandler.skinId) { lootHandler.looter.EndLooting(); skinBox.cooldownTimes[lootHandler.looter.UserIDString + "-box"] = DateTime.UtcNow; } lootHandler.skinId = 0uL; lootHandler.isBlocked = false; } public void UnsbscrbSplt() { Unsubscribe(nameof(OnItemSplit)); Unsubscribe(nameof(CanStackItem)); } public void SbscrbSplt() { Subscribe(nameof(OnItemSplit)); Subscribe(nameof(CanStackItem)); } public void SndRplyCl(ConsoleSystem.Arg arg, string format) { if (arg != null && arg.Connection != null) SendReply(arg, format); Puts(format); } private static string _(string i) { return !string.IsNullOrEmpty(i) ? new string(i.Select(x => x >= 'a' && x <= 'z' ? (char) ((x - 'a' + 13) % 26 + 'a') : x >= 'A' && x <= 'Z' ? (char) ((x - 'A' + 13) % 26 + 'A') : x).ToArray()) : i; } public void DstryUi(BasePlayer player) { CuiHelper.DestroyUi(player, "SkinBoxUI"); } public void CrtUi(BasePlayer player, int page = 1, int total = 1) { string panelName = "SkinBoxUI"; CuiHelper.DestroyUi(player, panelName); string contentColor = "0.7 0.7 0.7 1.0"; string buttonColor = "0.75 0.75 0.75 0.1"; string buttonTextColor = "0.77 0.68 0.68 1"; CuiElementContainer result = new CuiElementContainer(); string rootPanelName = result.Add( new CuiPanel { Image = new CuiImageComponent {Color = "0 0 0 0"}, RectTransform = {AnchorMin = "0.9505 0.15", AnchorMax = "0.99 0.6"} }, "Hud.Menu", panelName); result.Add( new CuiPanel { Image = new CuiImageComponent {Color = "0.65 0.65 0.65 0.06"}, RectTransform = {AnchorMin = "0 0", AnchorMax = "1 1"} }, rootPanelName); result.Add( new CuiButton { RectTransform = {AnchorMin = "0.025 0.7", AnchorMax = "0.975 1.0"}, Button = {Command = _("fxvaobk.cntrceri"), Color = buttonColor}, Text = {Align = TextAnchor.MiddleCenter, Text = "◀", Color = buttonTextColor, FontSize = 50} }, rootPanelName); result.Add( new CuiLabel { RectTransform = {AnchorMin = "0.025 0.3", AnchorMax = "0.975 0.7"}, Text = { Align = TextAnchor.MiddleCenter, Text = $"{page}\nof\n{total}", Color = contentColor, FontSize = 20 } }, rootPanelName); result.Add( new CuiButton { RectTransform = {AnchorMin = "0.025 0", AnchorMax = "0.975 0.3"}, Button = {Command = _("fxvaobk.cntrarkg"), Color = buttonColor}, Text = {Align = TextAnchor.MiddleCenter, Text = "▶", Color = buttonTextColor, FontSize = 50} }, rootPanelName); CuiHelper.AddUi(player, result); } [ConsoleCommand("skinbox.pagenext")] private void cmdPageNext(ConsoleSystem.Arg arg) { if (maxPagesShown <= 1 || arg == null || arg.Connection == null) return; BasePlayer player = arg.Connection?.player as BasePlayer; if (player == null) return; if (activeSkinBoxes.ContainsKey(player.userID)) activeSkinBoxes[player.userID].PgNxt(); } [ConsoleCommand("skinbox.pageprev")] private void cmdPagePrev(ConsoleSystem.Arg arg) { if (maxPagesShown <= 1 || arg == null || arg.Connection == null) return; BasePlayer player = arg.Connection?.player as BasePlayer; if (player == null) return; if (activeSkinBoxes.ContainsKey(player.userID)) activeSkinBoxes[player.userID].PgPrv(); } private bool IsSkinBoxPlayer(ulong playerId) => activeSkinBoxes.ContainsKey(playerId); private void OnPluginUnloaded(Plugin name) { if (Initialized && name.Name == _("FgnpxfRkgraqrq")) ChckSbscrptns(true); } private void OnPluginLoaded(Plugin name) { if (Initialized && name.Name == _("FgnpxfRkgraqrq")) ChckSbscrptns(false); } public void ChckSbscrptns(bool wasUnload) { if (!allowStackedItems) return; if (wasUnload) { _stacksExtendedExtrasDisabled = false; Subscribe(nameof(CanStackItem)); Subscribe(nameof(OnItemSplit)); } else { _stacksExtendedExtrasDisabled = (bool) StacksExtended.CallHook("DisableExtraFeatures"); if (!_stacksExtendedExtrasDisabled) { Unsubscribe(nameof(CanStackItem)); Unsubscribe(nameof(OnItemSplit)); } else { Subscribe(nameof(CanStackItem)); Subscribe(nameof(OnItemSplit)); } } } private object OnItemSplit(Item thisI, int split_Amount) { if (thisI.skin == 0uL) return null; Item item = null; item = ItemManager.CreateByItemID(thisI.info.itemid, 1, thisI.skin); if (item != null) { thisI.amount -= split_Amount; thisI.MarkDirty(); item.amount = split_Amount; item.OnVirginSpawn(); if (thisI.IsBlueprint()) item.blueprintTarget = thisI.blueprintTarget; if (thisI.hasCondition) item.condition = thisI.condition; item.MarkDirty(); return item; } return null; } private object CanStackItem(Item thisI, Item item) { if (thisI.skin == item.skin) return null; if (thisI.skin != item.skin) return false; if (thisI.skin == item.skin) { if (thisI.hasCondition && item.hasCondition) { if (item.condition != thisI.condition) return false; } return true; } return null; } private string u1 = _("uggcf://ncv.fgrnzcbjrerq.pbz/VFgrnzErzbgrFgbentr/TrgChoyvfurqSvyrQrgnvyf/i1/"); private string u2 = _("uggcf://ncv.fgrnzcbjrerq.pbz/VFgrnzErzbgrFgbentr/TrgPbyyrpgvbaQrgnvyf/i1/"); //private string u3 = _("uggc://f3.nznmbanjf.pbz/f3.cynlehfg.pbz/vpbaf/vairagbel/ehfg/fpurzn.wfba"); public class GtPblshdFlDtls { [JsonProperty("response")] public Response response; public class Tag { [JsonProperty("tag")] public string tag; } public class Response { [JsonProperty("result")] public int result; [JsonProperty("resultcount")] public int resultcount; [JsonProperty("publishedfiledetails")] public List publishedfiledetails; public class Publishedfiledetail { [JsonProperty("publishedfileid")] public ulong publishedfileid; [JsonProperty("result")] public int result; [JsonProperty("creator")] public string creator; [JsonProperty("creator_app_id")] public int creator_app_id; [JsonProperty("consumer_app_id")] public int consumer_app_id; [JsonProperty("filename")] public string filename; [JsonProperty("file_size")] public int file_size; [JsonProperty("preview_url")] public string preview_url; [JsonProperty("hcontent_preview")] public string hcontent_preview; [JsonProperty("title")] public string title; [JsonProperty("description")] public string description; [JsonProperty("time_created")] public int time_created; [JsonProperty("time_updated")] public int time_updated; [JsonProperty("visibility")] public int visibility; [JsonProperty("banned")] public int banned; [JsonProperty("ban_reason")] public string ban_reason; [JsonProperty("subscriptions")] public int subscriptions; [JsonProperty("favorited")] public int favorited; [JsonProperty("lifetime_subscriptions")] public int lifetime_subscriptions; [JsonProperty("lifetime_favorited")] public int lifetime_favorited; [JsonProperty("views")] public int views; [JsonProperty("tags")] public List tags; } } } public class GtCllctnDtls { [JsonProperty("response")] public Response response; public class Response { [JsonProperty("result")] public int result; [JsonProperty("resultcount")] public int resultcount; [JsonProperty("collectiondetails")] public List collectiondetails; public class Collectiondetail { [JsonProperty("publishedfileid")] public string publishedfileid; [JsonProperty("result")] public int result; [JsonProperty("children")] public List children; public class Child { [JsonProperty("publishedfileid")] public string publishedfileid; [JsonProperty("sortorder")] public int sortorder; [JsonProperty("filetype")] public int filetype; } } } } } }