Иконка ресурса

FREE LootManager : 1.0.3 1.0.3

Нет прав для скачивания
C#:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using Facepunch.Extend;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Oxide.Plugins.LootManagerExtensionMethods;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Random = UnityEngine.Random;
namespace Oxide.Plugins {
    [Info("LootManager", "Adem", "1.0.3")]
    internal class LootManager : RustPlugin {
#region Variables
        [PluginReference]
        Plugin AlphaLoot, CustomLoot;
        private static LootManager _ins;
        private readonly HashSet<string> _subscribeMethods = new HashSet<string> {
            "OnCrateSpawned", "OnCorpsePopulate", "OnEntityKill", "OnContainerPopulate", "CanPopulateLoot"
        }
        ;
        private ItemDefinition _bluePrintItemDefinition;
        private readonly Dictionary<string, string> _imageIDs = new Dictionary<string, string>();
        private readonly Dictionary<string, LootTableData> _lootTables = new Dictionary<string, LootTableData>();
        private readonly Dictionary<ulong, EditingLootTableData> _editingLootTables = new Dictionary<ulong, EditingLootTableData>();
        private readonly Dictionary<ulong, string> _crates = new Dictionary<ulong, string>();
        private readonly Dictionary<ulong, string> _npcs = new Dictionary<ulong, string>();
        private readonly Dictionary<ulong, string> _corpses = new Dictionary<ulong, string>();
        private readonly Dictionary<ulong, string> _bradleys = new Dictionary<ulong, string>();
        private readonly Dictionary<ulong, string> _helies = new Dictionary<ulong, string>();
#endregion Variables
#region Api
        private HashSet<string> GetMissingLootTables(HashSet<string> lootTableNames) {
            HashSet<string> result = lootTableNames.Where(x => !string.IsNullOrEmpty(x) && !_lootTables.ContainsKey(x));
            if (result.Count == 0) return result;
            LoadAllLootTables();
            result = lootTableNames.Where(x => !string.IsNullOrEmpty(x) && !_lootTables.ContainsKey(x));
            return result;
        }
        private string TryAddLootTable(string lootTablePreset, string pluginName, JObject lootTableJson, bool returnSame, HashSet<string> pluginFilters, string lootTableNameFilter) {
            LootTableData lootTableData = lootTableJson.ToObject<LootTableData>();
            if (lootTableData == null) return String.Empty;
            lootTableData.CheckAndUpdateValues();
            if (returnSame) {
                KeyValuePair<string, LootTableData> identicalLootTable = _lootTables.FirstOrDefault(x => (string.IsNullOrEmpty(lootTableNameFilter) || x.Key.Contains(lootTableNameFilter)) && (pluginFilters.IsNullOrEmpty() || pluginFilters.Any(y => x.Value.Description.Contains(y))) && x.Value.DeepEquals(lootTableData));
                if (!string.IsNullOrEmpty(identicalLootTable.Key)) return identicalLootTable.Key;
            }
            lootTablePreset = GetNameForNewLootTable(lootTablePreset);
            if (_lootTables.TryAdd(lootTablePreset, lootTableData)) SaveLootTable(lootTablePreset, lootTableData);
            return lootTablePreset;
        }
        private void AddCrate(StorageContainer storageContainer, string lootTableName) {
            if (string.IsNullOrEmpty(lootTableName) || storageContainer == null || storageContainer.net == null || storageContainer.inventory == null) return;
            if (!_lootTables.TryGetValue(lootTableName, out LootTableData lootTableData)) return;
            LootContainer lootContainer = storageContainer as LootContainer;
            if (lootContainer != null) {
                LootController.UpdateLootContainer(lootContainer, lootTableData);
                return;
            }
            LootController.FillContainer(storageContainer.inventory, lootTableData);
        }
        private void AddCrate(Fridge fridge, string lootTableName) {
            if (string.IsNullOrEmpty(lootTableName) || fridge == null || fridge.net == null) return;
            if (!_lootTables.TryGetValue(lootTableName, out LootTableData lootTableData)) return;
            LootController.UpdateFridge(fridge, lootTableData);
        }
        private void AddCrate(DroppedItemContainer droppedItemContainer, string lootTableName) {
            if (string.IsNullOrEmpty(lootTableName) || droppedItemContainer == null || droppedItemContainer.net == null) return;
            if (!_lootTables.TryGetValue(lootTableName, out LootTableData lootTableData)) return;
            LootController.FillContainer(droppedItemContainer.inventory, lootTableData);
        }
        private void AddNpc(ulong netId, string lootTableName) {
            if (string.IsNullOrEmpty(lootTableName) || !_lootTables.ContainsKey(lootTableName)) return;
            _npcs.TryAdd(netId, lootTableName);
        }
        private void AddBradley(ulong netId, string lootTableName) {
            if (string.IsNullOrEmpty(lootTableName) || !_lootTables.ContainsKey(lootTableName)) return;
            _bradleys.TryAdd(netId, lootTableName);
        }
        private void AddHeli(ulong netId, string lootTableName) {
            if (string.IsNullOrEmpty(lootTableName) || !_lootTables.ContainsKey(lootTableName)) return;
            _helies.TryAdd(netId, lootTableName);
        }
#endregion Api
#region Hooks
        private void Init() {
            Unsubscribes();
        }
        private void OnServerInitialized() {
            _ins = this;
            RegisterPermissions();
            LoadDefaultMessages();
            ImageLoader.LoadImages();
            LoadAllLootTables();
            PrefabController.CachePrefabs();
            _bluePrintItemDefinition = ItemManager.FindItemDefinition("blueprintbase");
            Subscribes();
        }
        private void Unload() {
            DestroyGuiForAllPlayers();
        }
        private void OnCrateSpawned(BradleyAPC bradleyApc, LockedByEntCrate crate) {
            if (bradleyApc == null || bradleyApc.net == null || crate == null) return;
            if (!_bradleys.TryGetValue(bradleyApc.net.ID.Value, out string lootTableName)) return;
            LootController.UpdateLootContainer(crate, lootTableName);
        }
        private void OnCrateSpawned(PatrolHelicopter patrolHelicopter, LockedByEntCrate crate) {
            if (patrolHelicopter == null || patrolHelicopter.net == null || crate == null) return;
            if (!_helies.TryGetValue(patrolHelicopter.net.ID.Value, out string lootTableName)) return;
            LootController.UpdateLootContainer(crate, lootTableName);
        }
        private void OnCorpsePopulate(ScientistNPC scientistNpc, NPCPlayerCorpse corpse) {
            if (scientistNpc == null || corpse == null || scientistNpc.net == null || corpse.net == null) return;
            if (!_npcs.TryGetValue(scientistNpc.net.ID.Value, out string lootTableName)) return;
            LootController.UpdateNpc(corpse, lootTableName);
            _corpses.TryAdd(corpse.net.ID.Value, lootTableName);
        }
        private void OnEntityKill(LootContainer lootContainer) {
            if (lootContainer == null || lootContainer.net == null) return;
            _crates.Remove(lootContainer.net.ID.Value);
        }
        private void OnEntityKill(Fridge fridge) {
            if (fridge == null || fridge.net == null) return;
            _crates.Remove(fridge.net.ID.Value);
        }
        private void OnEntityKill(DroppedItemContainer droppedItemContainer) {
            if (droppedItemContainer == null || droppedItemContainer.net == null) return;
            _crates.Remove(droppedItemContainer.net.ID.Value);
        }
        private void OnEntityKill(BradleyAPC bradley) {
            if (bradley == null || bradley.net == null) return;
            _bradleys.Remove(bradley.net.ID.Value);
        }
        private void OnEntityKill(PatrolHelicopter heli) {
            if (heli == null || heli.net == null) return;
            _helies.Remove(heli.net.ID.Value);
        }
        private void OnEntityKill(ScientistNPC npc) {
            if (npc == null || npc.net == null) return;
            _npcs.Remove(npc.net.ID.Value);
        }
        private void OnEntityKill(NPCPlayerCorpse corpse) {
            if (corpse == null || corpse.net == null) return;
            _corpses.Remove(corpse.net.ID.Value);
        }
#region LootTablePlugin
        private object OnContainerPopulate(LootContainer lootContainer) {
            if (lootContainer == null || lootContainer.net == null) return null;
            return HandleOtherPluginPopulate(lootContainer.net.ID.Value, _crates, data => !data.IsLootTablePlugin);
        }
        private object OnCorpsePopulate(NPCPlayerCorpse corpse) {
            if (corpse == null || corpse.net == null) return null;
            return HandleOtherPluginPopulate(corpse.net.ID.Value, _corpses, data => !data.IsLootTablePlugin);
        }
#endregion LootTablePlugin
#region AlphaLoot
        private object CanPopulateLoot(LootContainer lootContainer) {
            if (lootContainer == null || lootContainer.net == null) return null;
            return HandleOtherPluginPopulate(lootContainer.net.ID.Value, _crates, data => !data.IsAlphaLoot || !string.IsNullOrEmpty(data.AlphaLootPreset));
        }
        private object CanPopulateLoot(ScientistNPC scientistNpc, NPCPlayerCorpse corpse) {
            if (scientistNpc == null || scientistNpc.net == null) return null;
            return HandleOtherPluginPopulate(scientistNpc.net.ID.Value, _npcs, data => !data.IsAlphaLoot || !string.IsNullOrEmpty(data.AlphaLootPreset));
        }
#endregion AlphaLoot
#region CustomLoot
        private object OnCustomLootContainer(NetworkableId net) {
            return HandleOtherPluginPopulate(net.Value, _crates, data => !data.IsCustomLoot);
        }
        private object OnCustomLootNPC(NetworkableId net) {
            return HandleOtherPluginPopulate(net.Value, _npcs, data => !data.IsCustomLoot);
        }
#endregion CustomLoot
        private static object HandleOtherPluginPopulate(ulong netId, Dictionary<ulong, string> targetDictionary, Func<LootTableData, bool> cancelFunction) {
            if (!targetDictionary.TryGetValue(netId, out string presetName)) return null;
            LootTableData ltd = LootController.GetDataByPresetName(presetName);
            if (ltd == null) return null;
            return cancelFunction(ltd) ? true : null;
        }
#endregion Hooks
#region Methods
        private void Unsubscribes() {
            foreach (string hook in _subscribeMethods) Unsubscribe(hook);
        }
        private void Subscribes() {
            foreach (string hook in _subscribeMethods) Subscribe(hook);
        }
        private static void Debug(params object[] arg) {
            string result = "";
            foreach (object obj in arg) result += obj.ToString() + " ";
            _ins.Puts(result);
        }
        private void RegisterPermissions() {
            permission.RegisterPermission(_config.Permission, this);
        }
        private bool IsPlayerHavePermission(string userIDString) {
            return _ins.permission.UserHasPermission(userIDString, _ins._config.Permission);
        }
        private string GetNameForNewLootTable(string name) {
            if (!_lootTables.ContainsKey(name)) return name;
            HashSet<string> matchingNames = _lootTables.Keys.Where(x => x.Contains(name));
            int number = 0;
            foreach (string matchName in matchingNames) {
                string fileNumberString = matchName.Split('_').Last();
                if (int.TryParse(fileNumberString, out int fileNumber) && fileNumber > number) number = fileNumber;
            }
            number++;
            return $"{name}_{number}";
        }
#endregion Methods
#region Classes
        private readonly Dictionary<string, PrefabLootInfo> _prefabLootTables = new Dictionary<string, PrefabLootInfo>();
        private static class LootController {
            public static LootTableData GetDataByPresetName(string presetName) {
                return _ins._lootTables.GetValueOrDefault(presetName);
            }
            public static void UpdateLootContainer(LootContainer lootContainer, string lootTableName) {
                if (!_ins._lootTables.TryGetValue(lootTableName, out LootTableData lootTableData)) return;
                UpdateLootContainer(lootContainer, lootTableData);
            }
            public static void UpdateLootContainer(LootContainer lootContainer, LootTableData lootTableData) {
                lootContainer.Invoke(() => {
                    FillContainer(lootContainer.inventory, lootTableData);
                }
                , 2f);
            }
            public static void UpdateFridge(Fridge fridge, LootTableData lootTableData) {
                fridge.OnlyAcceptCategory = ItemCategory.All;
                FillContainer(fridge.inventory, lootTableData);
            }
            public static void UpdateNpc(NPCPlayerCorpse corpse, string lootTableName) {
                if (!_ins._lootTables.TryGetValue(lootTableName, out LootTableData lootTableData)) return;
                if (corpse.containers.IsNullOrEmpty() || corpse.containers[0] == null) return;
                ItemContainer container = corpse.containers[0];
                _ins.NextTick(() => {
                    if (container != null) FillContainer(container, lootTableData);
                }
                );
            }
            public static void FillContainer(ItemContainer container, LootTableData lootTableData) {
                if (lootTableData.ClearDefaultItems) ClearContainer(container);
                if (lootTableData.UseItemList) {
                    if (lootTableData.UseMinMaxForItems) {
                        int itemsAmount = Random.Range(lootTableData.MinItemsAmount, lootTableData.MaxItemsAmount + 1);
                        HashSet<ItemData> itemsForSpawn = GetElementsForSpawn(lootTableData.Items, itemsAmount);
                        if (itemsForSpawn.Count > 0) ItemListController.FillContainer(container, itemsForSpawn);
                    }
                    else if (lootTableData.Items.Count > 0) {
                        ItemListController.FillContainerWithoutMinMax(container, lootTableData.Items);
                    }
                }
                if (lootTableData.UsePrefabList) {
                    int prefabsAmount = Random.Range(lootTableData.MinPrefabsAmount, lootTableData.MaxPrefabsAmount + 1);
                    HashSet<PrefabData> prefabsForSpawn = GetElementsForSpawn(lootTableData.Prefabs, prefabsAmount);
                    PrefabController.FillContainer(container, prefabsForSpawn);
                }
                if (!string.IsNullOrEmpty(lootTableData.AlphaLootPreset)) {
                    if (_ins.plugins.Exists("AlphaLoot") && (bool)_ins.AlphaLoot.Call("ProfileExists", lootTableData.AlphaLootPreset)) {
                        _ins.AlphaLoot.Call("PopulateLoot", container, lootTableData.AlphaLootPreset);
                    }
                }
                if (!string.IsNullOrEmpty(lootTableData.CustomLootPreset)) {
                    List<Item> items = (List<Item>)_ins.CustomLoot?.Call("MakeLoot", lootTableData.CustomLootPreset);
                    if (items != null) foreach (Item item in items) if (item == null || !item.MoveToContainer(container)) item.Remove();
                }
            }
            private static void ClearContainer(ItemContainer container) {
                for (int i = container.itemList.Count - 1; i >= 0; i--) {
                    Item item = container.itemList[i];
                    item.RemoveFromContainer();
                    item.Remove();
                }
            }
            private static HashSet<T> GetElementsForSpawn<T>(List<T> elements, int targetAmount) where T : LootElementChance {
                HashSet<T> result = new HashSet<T>();
                if (elements.Count == 0 || targetAmount <= 0) return result;
                HashSet<int> includedIndexes = new HashSet<int>();
                int counter = 50;
                while (result.Count < targetAmount && counter-- > 0) {
                    for (int i = 0; i < elements.Count && result.Count < targetAmount; i++) {
                        if (includedIndexes.Contains(i)) continue;
                        T lootElement = elements[i];
                        float chance = elements[i].Chance;
                        float roll = Random.Range(0f, 100f);
                        if (roll >= chance) continue;
                        includedIndexes.Add(i);
                        result.Add(lootElement);
                    }
                }
                return result;
            }
        }
        private static class ItemListController {
            public static void FillContainer(ItemContainer container, HashSet<ItemData> items) {
                int itemsCount = container.itemList.Count + items.Count;
                if (container.capacity < itemsCount) container.capacity = itemsCount;
                foreach (ItemData itemData in items) {
                    Item item = CreateItem(itemData);
                    if (item == null || !item.MoveToContainer(container)) item.Remove();
                }
            }
            public static void FillContainerWithoutMinMax(ItemContainer container, List<ItemData> items) {
                foreach (ItemData itemData in items) {
                    float roll = Random.Range(0f, 100f);
                    if (roll >= itemData.Chance) continue;
                    Item item = CreateItem(itemData);
                    if (item == null || !item.MoveToContainer(container)) item.Remove();
                }
            }
            private static Item CreateItem(ItemData itemData) {
                int amount = Random.Range(itemData.MinAmount, itemData.MaxAmount + 1);
                Item item;
                if (itemData.IsBluePrint) {
                    item = ItemManager.CreateByName("blueprintbase");
                    item.blueprintTarget = itemData.ItemId;
                }
                else {
                    item = ItemManager.CreateByName(itemData.ShortName, amount, itemData.Skin);
                }
                if (item == null) {
                    _ins.PrintWarning($"Failed to create item! ({itemData.ShortName})");
                    return null;
                }
                if (!string.IsNullOrEmpty(itemData.CustomDisplayName)) item.name = itemData.CustomDisplayName;
                if (!string.IsNullOrEmpty(itemData.Genomes)) {
                    string[] genomes = itemData.Genomes.Replace(" ", "").Split(",");
                    string genome = genomes.GetRandom();
                    UpdateGenome(item, genome);
                }
                return item;
            }
            private static void UpdateGenome(Item item, string genome) {
                if (genome.Length != 6) return;
                GrowableGenes growableGenes = new GrowableGenes();
                for (int i = 0; i < 6 && i < genome.Length; ++i) {
                    GrowableGenetics.GeneType geneType = GrowableGenetics.GeneType.Empty;
                    switch (genome[i]) {
                        case 'g' : geneType = GrowableGenetics.GeneType.GrowthSpeed;
                        break;
                        case 'y' : geneType = GrowableGenetics.GeneType.Yield;
                        break;
                        case 'h' : geneType = GrowableGenetics.GeneType.Hardiness;
                        break;
                        case 'w' : geneType = GrowableGenetics.GeneType.WaterRequirement;
                        break;
                    }
                    growableGenes.Genes[i].Set(geneType, true);
                }
                GrowableGeneEncoding.EncodeGenesToItem(GrowableGeneEncoding.EncodeGenesToInt(growableGenes), item);
            }
        }
        private static class PrefabController {
            public static void CachePrefabs() {
                foreach (LootTableData lootTableData in _ins._lootTables.Values) {
                    if (!lootTableData.UsePrefabList) continue;
                    foreach (PrefabData prefabData in lootTableData.Prefabs) CachePrefab(prefabData);
                }
            }
            public static void CachePrefab(PrefabData prefabData) {
                if (_ins._prefabLootTables.ContainsKey(prefabData.PrefabName)) return;
                GameObject gameObject = GameManager.server.FindPrefab(prefabData.PrefabName);
                if (gameObject == null) return;
                LootContainer lootContainer = gameObject.GetComponent<LootContainer>();
                if (lootContainer != null) {
                    SavePrefabLootInfo(prefabData.PrefabName, lootContainer.LootSpawnSlots, lootContainer.scrapAmount, lootContainer.lootDefinition, lootContainer.maxDefinitionsToSpawn);
                    return;
                }
                global : : HumanNPC humanNpc = gameObject.GetComponent<global : : HumanNPC>();
                if (humanNpc != null) {
                    SavePrefabLootInfo(prefabData.PrefabName, humanNpc.LootSpawnSlots);
                    return;
                }
                global : : ScarecrowNPC scarecrowNpc = gameObject.GetComponent<global : : ScarecrowNPC>();
                if (scarecrowNpc != null) {
                    SavePrefabLootInfo(prefabData.PrefabName, scarecrowNpc.LootSpawnSlots);
                }
            }
            private static void SavePrefabLootInfo(string prefabName, LootContainer.LootSpawnSlot[] lootSpawnSlot, int scrapAmount = 0, LootSpawn lootDefinition = null, int maxDefinitionsToSpawn = 0) {
                PrefabLootInfo prefabLootInfo = new PrefabLootInfo {
                    LootSpawnSlots = lootSpawnSlot, LootDefinition = lootDefinition, MaxDefinitionsToSpawn = maxDefinitionsToSpawn, ScrapAmount = scrapAmount
                }
                ;
                _ins._prefabLootTables.TryAdd(prefabName, prefabLootInfo);
            }
            public static void FillContainer(ItemContainer container, HashSet<PrefabData> prefabs) {
                foreach (PrefabData prefabData in prefabs) FillContainer(container, prefabData);
            }
            private static void FillContainer(ItemContainer container, PrefabData prefabData) {
                if (!_ins._prefabLootTables.TryGetValue(prefabData.PrefabName, out PrefabLootInfo prefabLootInfo)) return;
                int lootScale = Random.Range(prefabData.MinAmount, prefabData.MaxAmount + 1);
                for (int i = 0; i < lootScale; i++) {
                    if (prefabLootInfo.LootSpawnSlots != null) {
                        foreach (LootContainer.LootSpawnSlot lootSpawnSlot in prefabLootInfo.LootSpawnSlots) {
                            if (lootSpawnSlot.eras == null || lootSpawnSlot.eras.Length == 0 || Array.IndexOf(lootSpawnSlot.eras, ConVar.Server.Era) != -1) {
                                for (int j = 0; j < lootSpawnSlot.numberToSpawn; j++) {
                                    if (Random.Range(0f, 1f) <= lootSpawnSlot.probability) {
                                        lootSpawnSlot.definition.SpawnIntoContainer(container);
                                    }
                                }
                            }
                        }
                    }
                    if (prefabLootInfo.LootDefinition != null) for (int j = 0; j < prefabLootInfo.MaxDefinitionsToSpawn; j++) prefabLootInfo.LootDefinition.SpawnIntoContainer(container);
                    if (prefabLootInfo.ScrapAmount > 0) {
                        Item item = ItemManager.CreateByName("scrap", prefabLootInfo.ScrapAmount);
                        if (!item.MoveToContainer(container)) item.Remove();
                    }
                }
            }
        }
        private class PrefabLootInfo {
            public LootContainer.LootSpawnSlot[] LootSpawnSlots;
            public LootSpawn LootDefinition;
            public int MaxDefinitionsToSpawn;
            public int ScrapAmount;
        }
        private static class ImageLoader {
            internal static void LoadImages() {
                ServerMgr.Instance.StartCoroutine(LoadIconsCoroutine());
            }
            private static IEnumerator LoadIconsCoroutine() {
                HashSet<ImageInfo> imageInfos = GetImagesInfosForLoad();
                char separator = Path.DirectorySeparatorChar;
                string path = $"file://{Interface.Oxide.DataDirectory}{separator}{_ins.Name}{separator}Images{separator}";
                foreach (ImageInfo imageInfo in imageInfos) {
                    string url = path + $"{imageInfo.FolderName}{separator}" + imageInfo.ImageName + ".png";
                    using UnityWebRequest unityWebRequest = UnityWebRequestTexture.GetTexture(url);
                    yield return unityWebRequest.SendWebRequest();
                    if (unityWebRequest.result != UnityWebRequest.Result.Success) {
                        OnImageSaveFailed(imageInfo.ImageName);
                        break;
                    }
                    Texture2D texture = DownloadHandlerTexture.GetContent(unityWebRequest);
                    uint imageId = FileStorage.server.Store(texture.EncodeToPNG(), FileStorage.Type.png, CommunityEntity.ServerInstance.net.ID);
                    _ins._imageIDs.Add(imageInfo.ImageName, imageId.ToString());
                    UnityEngine.Object.DestroyImmediate(texture);
                }
            }
            private static HashSet<ImageInfo> GetImagesInfosForLoad() {
                HashSet<ImageInfo> result = new HashSet<ImageInfo> {
                    new ImageInfo("Plus_Icon", "Icons"), new ImageInfo("Lock_Icon", "Icons"), new ImageInfo("Search_Icon", "Icons"), new ImageInfo("Copy_Icon", "Icons"), new ImageInfo("Delete_Icon", "Icons"), new ImageInfo("Edit_Icon", "Icons"), new ImageInfo("Error_Icon", "Icons")
                }
                ;
                foreach (PrefabInfo crateInfo in _ins._prefabInfos) {
                    if (result.Any(x => x.ImageName == crateInfo.ImageName)) continue;
                    result.Add(new ImageInfo(crateInfo.ImageName, "Prefabs"));
                }
                return result;
            }
            private static void OnImageSaveFailed(string imageName) {
                _ins.PrintError($"Image {imageName} was not found. Maybe you didn't upload it to the .../oxide/data/{_ins.Name}/Images/ folder");
                Interface.Oxide.UnloadPlugin(_ins.Name);
            }
            private class ImageInfo {
                public readonly string ImageName;
                public readonly string FolderName;
                internal ImageInfo(string imageName, string imageFolder) {
                    ImageName = imageName;
                    FolderName = imageFolder;
                }
            }
        }
#endregion Classes
#region Data
        private readonly HashSet<PrefabInfo> _prefabInfos = new HashSet<PrefabInfo> {
            new ("assets/bundled/prefabs/autospawn/resource/loot/loot-barrel-1.prefab", "loot-barrel-1", "Yellow Loot Barrel"), new ("assets/bundled/prefabs/autospawn/resource/loot/loot-barrel-2.prefab", "loot-barrel-2", "Blue Loot Barrel"), new ("assets/content/structures/excavator/prefabs/diesel_collectable.prefab", "diesel_collectable", "Diesel Fuel"), new ("assets/bundled/prefabs/radtown/oil_barrel.prefab", "oil_barrel", "Oil Barrel"), new ("assets/prefabs/misc/xmas/giftbox/giftbox_loot.prefab", "giftbox_loot", "Present"), new ("assets/bundled/prefabs/radtown/crate_basic.prefab", "crate_basic", "Basic Crate"), new ("assets/bundled/prefabs/radtown/crate_basic_jungle.prefab", "crate_basic_jungle", "Crate Basic Jungle"), new ("assets/bundled/prefabs/radtown/crate_elite.prefab", "crate_elite", "Elite Crate"), new ("assets/prefabs/npc/m2bradley/bradley_crate.prefab", "crate_elite", "Elite Crate - Bradley"), new ("assets/prefabs/npc/patrol helicopter/heli_crate.prefab", "crate_elite", "Elite Crate - Heli"), new ("assets/prefabs/misc/food cache/food_cache_001.prefab", "food_cache_001", "Food Cache"), new ("assets/bundled/prefabs/radtown/foodbox.prefab", "foodbox", "Foodbox"), new ("assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate.prefab", "codelockedhackablecrate", "Locked Crate"), new ("assets/prefabs/deployable/chinooklockedcrate/codelockedhackablecrate_oilrig.prefab", "codelockedhackablecrate", "Locked Crate - Oilrig"), new ("assets/bundled/prefabs/radtown/crate_normal.prefab", "crate_normal", "Military Crate"), new ("assets/bundled/prefabs/radtown/crate_normal_2.prefab", "crate_normal_2", "Normal Crate"), new ("assets/bundled/prefabs/radtown/crate_mine.prefab", "crate_normal_2", "Normal Crate - Cave"), new ("assets/bundled/prefabs/radtown/crate_normal_2_food.prefab", "crate_normal_2_food", "Normal Crate - Food"), new ("assets/bundled/prefabs/radtown/crate_normal_2_medical.prefab", "crate_normal_2_medical", "Normal Crate - Medical"), new ("assets/prefabs/misc/supply drop/supply_drop.prefab", "supply_drop", "Supply Drop"), new ("assets/bundled/prefabs/radtown/crate_tools.prefab", "crate_tools", "Tools Crate"), new ("assets/bundled/prefabs/radtown/crate_underwater_advanced.prefab", "crate_underwater_advanced", "Underwater Advanced Crate"), new ("assets/bundled/prefabs/radtown/crate_underwater_basic.prefab", "crate_basic", "Underwater Basic Crate"), new ("assets/bundled/prefabs/radtown/underwater_labs/crate_ammunition.prefab", "crate_ammunition", "Underwater Lab - Ammunition Crate"), new ("assets/bundled/prefabs/radtown/underwater_labs/crate_food_1.prefab", "crate_food_1", "Underwater Lab - Food Crate"), new ("assets/bundled/prefabs/radtown/underwater_labs/crate_fuel.prefab", "crate_fuel", "Underwater Lab - Fuel Crate"), new ("assets/bundled/prefabs/radtown/underwater_labs/crate_medical.prefab", "crate_medical", "Underwater Lab - Medical Crate"), new ("assets/bundled/prefabs/radtown/underwater_labs/tech_parts_1.prefab", "tech_parts_1", "Underwater Lab - Tier 2 Components"), new ("assets/bundled/prefabs/radtown/underwater_labs/tech_parts_2.prefab", "tech_parts_2", "Underwater Lab - Tier 3 Components"), new ("assets/bundled/prefabs/radtown/underwater_labs/vehicle_parts.prefab", "vehicle_parts", "Vehicle Parts"), new ("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_junkpile_pistol.prefab", "scientistnpc", "Road Scientist"), new ("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_excavator.prefab", "scientistnpc", "Monument Scientist"), new ("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_bradley_heavy.prefab", "scientistnpc_heavy", "Heavy Scientist"), new ("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_roam_nvg_variant.prefab", "scientistnpc_tunnel", "Missile Silo Scientist"), new ("assets/rust.ai/agents/npcplayer/humannpc/scientist/scientistnpc_full_shotgun.prefab", "scientistnpc_tunnel", "Military Tunnel Scientist"), new ("assets/rust.ai/agents/npcplayer/humannpc/tunneldweller/npc_tunneldweller.prefab", "npc_tunneldweller", "Tunnel/ Underwater Dweller"), new ("assets/prefabs/npc/gingerbread/gingerbread_dungeon.prefab", "gingerbread_dungeon", "Gingerbread"), new ("assets/prefabs/npc/scarecrow/scarecrow_dungeon.prefab", "scarecrow_dungeon", "Scarecrow"),
        }
        ;
        private class PrefabInfo {
            public readonly string PrefabName;
            public readonly string ShortPrefabName;
            public readonly string Name;
            public readonly string ImageName;
            public PrefabInfo(string prefabName, string imageName, string name) {
                PrefabName = prefabName;
                ImageName = imageName;
                ShortPrefabName = PrefabName.Split('/').Last().Split('.').First();
                Name = name;
            }
        }
        private class EditingLootTableData : LootTableData {
            public string PresetName;
            public string OldPresetName = string.Empty;
            public EditingLootTableData (string presetName, LootTableData lootTableData) : base(lootTableData) {
                PresetName = presetName;
            }
        }
        public class LootTableData {
            public string Description;
            public bool ClearDefaultItems;
            public bool IsAlphaLoot;
            public string AlphaLootPreset = string.Empty;
            public bool IsCustomLoot;
            public string CustomLootPreset = string.Empty;
            public bool IsLootTablePlugin;
            public string LootTablePluginLootPreset = string.Empty;
            public bool UseItemList;
            public bool UseMinMaxForItems = true;
            public int MinItemsAmount;
            public int MaxItemsAmount;
            public List<ItemData> Items = new List<ItemData>();
            public bool UsePrefabList;
            public int MinPrefabsAmount;
            public int MaxPrefabsAmount;
            public List<PrefabData> Prefabs = new List<PrefabData>();
            public LootTableData() {
            }
            public LootTableData(LootTableData other) {
                ClearDefaultItems = other.ClearDefaultItems;
                Description = other.Description;
                IsAlphaLoot = other.IsAlphaLoot;
                AlphaLootPreset = other.AlphaLootPreset;
                IsCustomLoot = other.IsCustomLoot;
                CustomLootPreset = other.CustomLootPreset;
                IsLootTablePlugin = other.IsLootTablePlugin;
                LootTablePluginLootPreset = other.LootTablePluginLootPreset;
                UseItemList = other.UseItemList;
                UseMinMaxForItems = other.UseMinMaxForItems;
                MinItemsAmount = other.MinItemsAmount;
                MaxItemsAmount = other.MaxItemsAmount;
                Items = other.Items.Select(i => i.Clone()).ToList();
                UsePrefabList = other.UsePrefabList;
                MinPrefabsAmount = other.MinPrefabsAmount;
                MaxPrefabsAmount = other.MaxPrefabsAmount;
                Prefabs = other.Prefabs.Select(i => i.Clone()).ToList();
            }
            public bool DeepEquals(LootTableData other) {
                if (ClearDefaultItems != other.ClearDefaultItems || IsAlphaLoot != other.IsAlphaLoot || AlphaLootPreset != other.AlphaLootPreset || IsCustomLoot != other.IsCustomLoot || CustomLootPreset != other.CustomLootPreset || IsLootTablePlugin != other.IsLootTablePlugin || LootTablePluginLootPreset != other.LootTablePluginLootPreset || UseItemList != other.UseItemList || UseMinMaxForItems != other.UseMinMaxForItems || MinItemsAmount != other.MinItemsAmount || MaxItemsAmount != other.MaxItemsAmount || UsePrefabList != other.UsePrefabList || MinPrefabsAmount != other.MinPrefabsAmount || MaxPrefabsAmount != other.MaxPrefabsAmount) return false;
                if (Items.Count != other.Items.Count || Prefabs.Count != other.Prefabs.Count) return false;
                for (int i = 0; i < Items.Count; i++) {
                    if (!Items[i].DeepEquals(other.Items[i])) return false;
                }
                for (int i = 0; i < Prefabs.Count; i++) {
                    if (!Prefabs[i].DeepEquals(other.Prefabs[i])) return false;
                }
                return true;
            }
            public void CheckAndUpdateValues() {
                Items = Items.OrderBy(x => x.Chance);
                Prefabs = Prefabs.OrderBy(x => x.Chance);
                foreach (ItemData itemData in Items) itemData.CheckAndUpdateValues();
                foreach (PrefabData prefabData in Prefabs) prefabData.CheckAndUpdateValues();
                int countOfGoodItems = Items.Where(x => x.Chance >= 0.1f).Count;
                MinItemsAmount = Mathf.Clamp(MinItemsAmount, 0, countOfGoodItems);
                MaxItemsAmount = Mathf.Clamp(MaxItemsAmount, 0, countOfGoodItems);
                int countOfGoodPrefabs = Prefabs.Where(x => x.Chance >= 0.1f).Count;
                MinPrefabsAmount = Mathf.Clamp(MinPrefabsAmount, 0, countOfGoodPrefabs);
                MaxPrefabsAmount = Mathf.Clamp(MaxPrefabsAmount, 0, countOfGoodPrefabs);
                if (UsePrefabList) foreach (PrefabData prefabData in Prefabs) PrefabController.CachePrefab(prefabData);
                if (ClearDefaultItems) {
                    if (IsAlphaLoot && string.IsNullOrEmpty(AlphaLootPreset) || IsCustomLoot && string.IsNullOrEmpty(CustomLootPreset) || IsLootTablePlugin && string.IsNullOrEmpty(LootTablePluginLootPreset)) ClearDefaultItems = false;
                }
            }
        }
        public class ItemData : LootElementChance {
            public string ShortName;
            public int ItemId;
            public string CustomDisplayName;
            public string DefaultDisplayName;
            public string OwnerDisplayName;
            public ulong Skin;
            public bool IsBluePrint;
            public string Genomes;
            private ItemData() {
            }
            public static ItemData CreateDefault(string shortName, int itemId, string defaultDisplayName) {
                return new ItemData {
                    ShortName = shortName, ItemId = itemId, CustomDisplayName = string.Empty, DefaultDisplayName = defaultDisplayName, OwnerDisplayName = string.Empty, Skin = 0, IsBluePrint = false, MinAmount = 1, MaxAmount = 1, Chance = 10f, Genomes = string.Empty
                }
                ;
            }
            public void CheckAndUpdateValues() {
                if (MinAmount > MaxAmount) MinAmount = MaxAmount;
                if (MaxAmount < MinAmount) MaxAmount = MinAmount;
                Chance = Mathf.Clamp(Chance, 0, 100);
                if (ItemId == 0 || string.IsNullOrEmpty(DefaultDisplayName)) {
                    ItemDefinition itemDefinition = ItemManager.FindItemDefinition(ShortName);
                    if (itemDefinition != null) {
                        DefaultDisplayName = itemDefinition.displayName.english.ToLower();
                        ItemId = itemDefinition.itemid;
                    }
                }
                UpdateGenomes();
            }
            private void UpdateGenomes() {
                if (string.IsNullOrEmpty(Genomes)) {
                    Genomes = string.Empty;
                    return;
                }
                Genomes = Genomes.Replace(" ", "");
                Genomes = Genomes.Replace(",", ", ");
            }
            public bool DeepEquals(ItemData other) {
                if (other == null) return false;
                return ShortName == other.ShortName && CustomDisplayName == other.CustomDisplayName && OwnerDisplayName == other.OwnerDisplayName && Skin == other.Skin && IsBluePrint == other.IsBluePrint && MinAmount == other.MinAmount && MaxAmount == other.MaxAmount && Math.Abs(Chance - other.Chance) < 0.0001f && Genomes == other.Genomes;
            }
            public ItemData Clone() {
                return new ItemData() {
                    ShortName = ShortName, ItemId = ItemId, CustomDisplayName = CustomDisplayName, DefaultDisplayName = DefaultDisplayName, OwnerDisplayName = OwnerDisplayName, Skin = Skin, IsBluePrint = IsBluePrint, MinAmount = MinAmount, MaxAmount = MaxAmount, Chance = Chance, Genomes = Genomes
                }
                ;
            }
        }
        public class PrefabData : LootElementChance {
            public string PrefabName;
            public string ShortPrefabName;
            private PrefabData() {
            }
            public PrefabData(string prefabName, string shortPrefabName) {
                PrefabName = prefabName;
                ShortPrefabName = shortPrefabName;
                MinAmount = 1;
                MaxAmount = 1;
                Chance = 10f;
            }
            public bool DeepEquals(PrefabData other) {
                if (other == null) return false;
                return PrefabName == other.PrefabName && MinAmount == other.MinAmount && MaxAmount == other.MaxAmount && Math.Abs(Chance - other.Chance) < 0.0001f;
            }
            public void CheckAndUpdateValues() {
                if (MinAmount > MaxAmount) MinAmount = MaxAmount;
                if (MaxAmount < MinAmount) MaxAmount = MinAmount;
                Chance = Mathf.Clamp(Chance, 0, 100);
                if (string.IsNullOrEmpty(ShortPrefabName)) ShortPrefabName = PrefabName.Split('/').Last().Replace(".prefab", string.Empty);
            }
            public PrefabData Clone() {
                return new PrefabData() {
                    PrefabName = PrefabName, ShortPrefabName = ShortPrefabName, MinAmount = MinAmount, MaxAmount = MaxAmount, Chance = Chance
                }
                ;
            }
        }
        public class LootElementChance {
            public int MinAmount;
            public int MaxAmount;
            public float Chance;
        }
        private static void DeleteLootTable(string presetName) {
            string path = $"{_ins.Name}/LootTables/{presetName}";
            Interface.Oxide.DataFileSystem.DeleteDataFile(path);
        }
        private void LoadAllLootTables() {
            string path = $"{_ins.Name}/LootTables/";
            foreach (string name in Interface.Oxide.DataFileSystem.GetFiles(path)) {
                string fileName = name.Split('/').Last().Split('.')[0].Replace(" ", "");
                if (_lootTables.ContainsKey(fileName)) continue;
                LootTableData lootTableData = LoadLootTable(fileName);
                if (lootTableData == null) {
                    PrintError($"File {fileName} is corrupted and cannot be loaded!");
                }
                else {
                    lootTableData.CheckAndUpdateValues();
                    _lootTables.TryAdd(fileName, lootTableData);
                }
            }
        }
        private static LootTableData LoadLootTable(string fileName) {
            string path = $"{_ins.Name}/LootTables/{fileName}";
            LootTableData lootTableData = Interface.Oxide.DataFileSystem.ReadObject<LootTableData>(path);
            return lootTableData;
        }
        private void SaveLootTable(string presetName, LootTableData lootTableData) {
            string path = $"{_ins.Name}/LootTables/{presetName}";
            Interface.Oxide.DataFileSystem.WriteObject(path, lootTableData);
        }
#endregion Data
#region GUI
        private const string BackgroundName = "LootManager_Background";
        private const string ErrorBackgroundName = "LootManager_ErrorBackground";
        private string GetStringFromArgs(string[] args, int startIndex) {
            string result = "";
            for (int i = startIndex; i < args.Length; i++) {
                if (i > startIndex) result += " ";
                string word = args[i];
                result += word;
            }
            return result;
        }
        [ChatCommand("lm")]
        private void OpenChatCommand(BasePlayer player, string command, string[] arg) {
            if (!IsPlayerHavePermission(player.UserIDString)) {
                PrintToChat(player, $"[{Name}] You don’t have permission!");
                return;
            }
            CreateGui(player);
        }
        private void CreateGui(BasePlayer player) {
            DestroyGuiForPlayer(player);
            CreateBackground(player);
            TableListPanelGUI.OpenTablesList(player, string.Empty, 0);
        }
        private void CreateBackground(BasePlayer player) {
            DestroyGuiForPlayer(player);
            CuiElementContainer container = new CuiElementContainer();
            CuiPanel cuiPanel = new CuiPanel() {
                Image = {
                    Color = "0 0 0 0.6", Material = "assets/content/ui/uibackgroundblur.mat"
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
                , CursorEnabled = true, KeyboardEnabled = true
            }
            ;
            container.Add(cuiPanel, "Overlay", BackgroundName);
            CuiHelper.AddUi(player, container);
        }
        private static void OnPageChanged(BasePlayer player) {
            CuiHelper.DestroyUi(player, TableListPanelGUI.LayerName);
            CuiHelper.DestroyUi(player, "PresetEdit_LeftBackground");
            CuiHelper.DestroyUi(player, EditPanelGUI.RightPanel.LayerName);
        }
        [ConsoleCommand("Close_LootManager")]
        private void CloseGUICommand(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if (player == null) return;
            DestroyGuiForPlayer(player);
        }
        private void DestroyGuiForAllPlayers() {
            foreach (BasePlayer player in BasePlayer.activePlayerList) if (player != null) DestroyGuiForPlayer(player);
        }
        private void DestroyGuiForPlayer(BasePlayer player) {
            _editingLootTables.Remove(player.userID);
            CuiHelper.DestroyUi(player, BackgroundName);
            CuiHelper.DestroyUi(player, ErrorBackgroundName);
        }
        [ConsoleCommand("TablesList_SetPage_LootManager")]
        private void TablesListEditPagePresetCommand(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if (player == null || !IsPlayerHavePermission(player.UserIDString)) return;
            if (arg.Args == null || arg.Args.Length < 1) return;
            int page = arg.Args[0].ToInt();
            string filter = arg.Args.Length > 1 ? arg.Args[1] : String.Empty;
            TableListPanelGUI.OpenTablesList(player, filter, page);
        }
        [ConsoleCommand("TablesList_RemovePreset_LootManager")]
        private void TablesListRemoveCommand(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if (player == null || !IsPlayerHavePermission(player.UserIDString)) return;
            if (arg.Args == null || arg.Args.Length < 2) return;
            string preset = arg.Args[0];
            int page = arg.Args[1].ToInt();
            string filter = arg.Args.Length > 2 ? arg.Args[2] : string.Empty;
            _lootTables.Remove(preset);
            DeleteLootTable(preset);
            TableListPanelGUI.OpenTablesList(player, filter, page);
        }
        [ConsoleCommand("TablesList_SearchPreset_LootManager")]
        private void TablesListSearchCommand(ConsoleSystem.Arg arg) {
            BasePlayer player = arg.Player();
            if (player == null || !IsPlayerHavePermission(player.UserIDString)) return;
            if (arg.Args == null || arg.Args.Length < 1) {
                TableListPanelGUI.OpenTablesList(player, string.Empty, 0);
                return;
            }
            string filter = arg.Args[0];
            TableListPanelGUI.OpenTablesList(player, filter, 0);
        }
        [ConsoleCommand("TablesList_CreateNewPreset_LootManager")]
        private void TablesListCreateNewCommand(ConsoleSystem.Arg arg) {
            BasePlayer pla
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху