using Netcode; using PyTK.Extensions; using PyTK.Types; using StardewModdingAPI; using StardewModdingAPI.Events; using StardewValley; using StardewValley.Locations; using StardewValley.Objects; using System.Collections.Generic; using System.IO; using SObject = StardewValley.Object; namespace CustomCropsDecay { class ModEntry : Mod { internal static ModEntry _instance { get; set; } internal static IMonitor _monitor { get { return _instance.Monitor; } } internal static IReflectionHelper _reflection { get { return _instance.Helper.Reflection; } } public ModConfig ModConfig { get; private set; } private Api api; public static Dictionary cropsById = new Dictionary(); public static Dictionary cropsByName = new Dictionary(); public static Dictionary cropsByCategory = new Dictionary(); public override void Entry(IModHelper helper) { ModConfig = helper.ReadConfig(); if (ModConfig.FridgeEffect >= 1) { ModConfig.FridgeEffect = 1; } helper.WriteConfig(ModConfig); _instance = this; loadPacks(); addInventoryListener(); helper.Events.World.ChestInventoryChanged += World_ChestInventoryChanged; helper.Events.GameLoop.DayEnding += GameLoop_DayEnding; } private void GameLoop_DayEnding(object sender, DayEndingEventArgs e) { FarmHouse farmHouse = Game1.getLocationFromName("farmHouse") as FarmHouse; foreach(Item item in farmHouse.fridge.Value.items) { if(item is ICropWithDecay crop) { crop.decayDays += ModConfig.FridgeEffect; } } } private void World_ChestInventoryChanged(object sender, StardewModdingAPI.Events.ChestInventoryChangedEventArgs e) { foreach(Item item in e.Added) { if(!(item is ICropWithDecay)) { chestItemChanged(e.Chest.items, (SObject)item); } } foreach (ItemStackSizeChange changed in e.QuantityChanged) { Item item = changed.Item; if (!(item is ICropWithDecay)) { chestItemChanged(e.Chest.items, (SObject)item); } } } public override object GetApi() { return api ?? (api = new Api()); } private void addInventoryListener() { new ItemSelector(o => !(o is CropWithDecay) && !(o is ColoredCropWithDecay)).whenAddedToInventory((list) => { list.ForEach(item => { chestItemChanged(Game1.player.items, item); }); }); } private static void chestItemChanged(NetObjectList items, SObject item) { if (cropsById.TryGetValue(item.ParentSheetIndex, out CustomCropsDecayData data)) { transformObject(items, item, data); } else if (cropsByName.TryGetValue(item.name, out data)) { transformObject(items, item, data); } else if (cropsByCategory.TryGetValue(item.Category, out data)) { transformObject(items, item, data); } } private static void transformObject(NetObjectList items, SObject item, CustomCropsDecayData data) { if (data.decayDays.TryGetValue(item.Quality, out int decayDays)) { if (item is ColoredObject coloredObject) { ColoredCropWithDecay crop = ColoredCropWithDecay.copyFrom(coloredObject); crop.decayDays = decayDays; for (int i = 0; i < items.Count; i++) { if (items[i] == item) { items[i] = crop; } } } else { CropWithDecay crop = CropWithDecay.copyFrom(item); crop.decayDays = decayDays; for (int i = 0; i < items.Count; i++) { if (items[i] == item) { items[i] = crop; } } } } } private List loadContentPacks() { List packs = new List(); foreach (StardewModdingAPI.IContentPack pack in Helper.ContentPacks.GetOwned()) { List cpPacks = loadCP(pack); packs.AddRange(cpPacks); } return packs; } public List loadCP(StardewModdingAPI.IContentPack contentPack, SearchOption option = SearchOption.TopDirectoryOnly, string filesearch = "*.json") { List packs = new List(); string[] files = Directory.GetFiles(contentPack.DirectoryPath, filesearch, option); foreach (string file in files) { FileInfo fileInfo = new FileInfo(file); DirectoryInfo directoryInfo = fileInfo.Directory; string filename = fileInfo.Name; if (filename == "manifest.json") continue; CustomCropsDecayPack pack = contentPack.ReadJsonFile(filename); pack.fileName = filename; pack.folderName = directoryInfo.Name; pack.author = contentPack.Manifest.Author; pack.version = contentPack.Manifest.Version.ToString(); pack.baseFolder = "ContentPack"; pack.contentPack = contentPack; packs.Add(pack); } return packs; } private void loadPacks() { List packs = loadContentPacks(); int ruleCount = 0; foreach (CustomCropsDecayPack pack in packs) { foreach (CustomCropsDecayData data in pack.crops) { foreach (int id in data.id) { cropsById.AddOrReplace(id, data); ruleCount++; } foreach (string name in data.name) { if (!string.IsNullOrWhiteSpace(name)) { cropsByName.AddOrReplace(name, data); ruleCount++; } } foreach (Category_ category in data.category) { cropsByCategory.AddOrReplace((int)category, data); ruleCount++; } } } Monitor.Log(packs.Count + " Content Packs with " + ruleCount + " rules found.", LogLevel.Trace); } } }