Ejemplo n.º 1
0
        /// <summary>Restores custom items used by this mod that were modified by <see cref="OnSaving"/>. Intended to be used after the game is saved or a save file is loaded.<para/>
        /// (On PC versions of this mod, the bags are saved using PyTK, but PyTK doesn't work with Android)</summary>
        private static void LoadCustomItems()
        {
            PlayerBags OwnedBags = PlayerBags.DeserializeFromCurrentSaveFile();

            if (OwnedBags == null)
            {
                return;
            }
            else
            {
                BagConfig GlobalConfig = ItemBagsMod.BagConfig;

                //  Index the saved bags by their instance ids
                Dictionary <int, BagInstance> IndexedBagInstances = new Dictionary <int, BagInstance>();
                foreach (BagInstance BagInstance in OwnedBags.Bags)
                {
                    if (!IndexedBagInstances.ContainsKey(BagInstance.InstanceId))
                    {
                        IndexedBagInstances.Add(BagInstance.InstanceId, BagInstance);
                    }
                    else
                    {
                        string Warning = string.Format("Warning - multiple bag instances were found with the same InstanceId. Did you manually edit your {0} json file or add multiple .json files to the 'Modded Bags' folder with the same ModUniqueId values? Only the first bag with InstanceId = {1} will be loaded.",
                                                       PlayerBags.OwnedBagsDataKey, BagInstance.InstanceId);
                        ItemBagsMod.ModInstance.Monitor.Log(Warning, LogLevel.Warn);
                    }
                }

                //  Decode all of our Encoded custom items back into their original form
                ReplaceAllInstances(IsEncodedCustomItem, Encoded =>
                {
                    int BagInstanceId = Encoded.ParentSheetIndex - EncodedItemStartIndex;
                    if (IndexedBagInstances.TryGetValue(BagInstanceId, out BagInstance BagInstance))
                    {
                        if (BagInstance.TryDecode(out ItemBag Replacement))
                        {
                            return(Replacement);
                        }
Ejemplo n.º 2
0
        /// <summary>Converts all custom items used by this mod into items that actually exist in the vanilla StardewValley game, so that the game won't crash while trying to save.<para/>
        /// The custom items are saved to a separate file using <see cref="StardewModdingAPI.IDataHelper.WriteSaveData{TModel}(string, TModel)"/></summary>
        internal static void OnSaving()
        {
            if (Constants.TargetPlatform == GamePlatform.Android)
            {
                ItemBagsMod.ModInstance.Monitor.Log("ItemBags OnSaving started.", LogLevel.Debug);

                int CurrentBagId = 0;
                List <BagInstance> BagInstances = new List <BagInstance>();

                //  Pre-emptive error-handling - try to find any encoded bags that, for whatever unknown reason, weren't able to be converted back into ItemBags during a Load.
                //  If any were found, then we need to retain the SaveData's BagInstance associated with that item (and not re-use it's Bag InstanceId when assigning to the bags that didn't have any issues during loading)
                //  so that the mod can still try again to load that bag during the next load.
                //  If someone mysteriously loses a bag, I can at least do some manual save editing to restore it, as the data will still be there.
                List <Item> CorruptedBags = new List <Item>();
                ReplaceAllInstances(x => IsEncodedCustomItem(x), x =>
                {
                    CorruptedBags.Add(x);
                    return(x);
                });
                HashSet <int> CorruptedBagIds = new HashSet <int>(CorruptedBags.Select(x => x.ParentSheetIndex - EncodedItemStartIndex));

                PlayerBags PreviousBagData = null;
                if (CorruptedBagIds.Any())
                {
                    PreviousBagData = PlayerBags.DeserializeFromCurrentSaveFile();
                    if (PreviousBagData != null && PreviousBagData.Bags != null)
                    {
                        Dictionary <int, BagInstance> IndexedInstances = new Dictionary <int, BagInstance>();
                        foreach (BagInstance Instance in PreviousBagData.Bags)
                        {
                            if (!IndexedInstances.ContainsKey(Instance.InstanceId))
                            {
                                IndexedInstances.Add(Instance.InstanceId, Instance);
                            }
                        }

                        foreach (int CorruptedId in CorruptedBagIds)
                        {
                            if (IndexedInstances.TryGetValue(CorruptedId, out BagInstance CorruptedInstance))
                            {
                                BagInstances.Add(CorruptedInstance);
                            }
                        }
                    }
                }

                //  Encode all bags as a regular non-modded item
                ReplaceAllInstances(IsCustomItem, CustomItem =>
                {
                    if (CustomItem is ItemBag IB)
                    {
                        try
                        {
                            while (CorruptedBagIds.Contains(CurrentBagId))
                            {
                                CurrentBagId++;
                            }

                            BagInstance Instance = new BagInstance(CurrentBagId, IB);
                            BagInstances.Add(Instance);

                            //  Replace the Bag with an arbitrary low-value/non-stackable item (in this case, a Rusty Sword) and store the bag instance's Id in the replacement item's ParentSheetIndex
                            MeleeWeapon Replacement      = new MeleeWeapon(0);
                            Replacement.ParentSheetIndex = EncodedItemStartIndex + CurrentBagId;
                            return(Replacement);
                        }
                        finally { CurrentBagId++; }
                    }
                    else
                    {
                        return(CustomItem);
                    }
                });

                PlayerBags OwnedBags = new PlayerBags();
                OwnedBags.Bags = BagInstances.ToArray();
                OwnedBags.SerializeToCurrentSaveFile();

                ItemBagsMod.ModInstance.Monitor.Log("ItemBags OnSaving finished.", LogLevel.Debug);
            }
        }