private static void Multiplayer_PeerContextReceived(object sender, PeerContextReceivedEventArgs e)
        {
            //  Whenever a new client connects to the host, force the NetStrings that store bag data to get re-loaded on the other clients
            if (Context.IsMainPlayer)
            {
                ItemBag.GetAllBags(false).ForEach(x => x.Resync());

                //  I have no idea why, but it seems like the items in the connected farmhand's inventory are getting replaced with new instances after I've synchronized the current instances.
                //  So to maintain bags in their inventory, send the data to the peer using IMultiplayerEvents.SendMessage/IMultiplayerEvents.ModMessageReceived.
                //  This will force the connected client to overwrite their inventory with the correct data.
                Farmer ConnectedFarmer = Game1.getAllFarmers().First(x => x.UniqueMultiplayerID == e.Peer.PlayerID);
                Dictionary <int, string> PendingSync = new Dictionary <int, string>();
                for (int i = 0; i < ConnectedFarmer.Items.Count; i++)
                {
                    Item Item = ConnectedFarmer.Items[i];
                    if (Item != null && Item is ItemBag Bag && Bag.TrySerializeToString(out string DataString, out Exception Error))
                    {
                        PendingSync.Add(i, DataString);
                    }
                }
                if (PendingSync.Any())
                {
                    Helper.Multiplayer.SendMessage(PendingSync, ForceResyncCommandType, new string[] { ItemBagsMod.ModUniqueId }, new long[] { ConnectedFarmer.UniqueMultiplayerID });
                }

                Helper.Multiplayer.SendMessage("", OnConnectedCommandType, new string[] { ItemBagsMod.ModUniqueId }, new long[] { ConnectedFarmer.UniqueMultiplayerID });
            }
        }
Пример #2
0
        public static void MonsterDrop_Postfix(GameLocation __instance, Monster monster, int x, int y, Farmer who)
        {
            try
            {
                MonsterLootSettings LootSettings = MonsterLootSettings;
                if (who.UniqueMultiplayerID == Game1.player.UniqueMultiplayerID && LootSettings.CanReceiveBagsAsDrops)
                {
                    //  Roll chance at receiving an ItemBag
                    double Chance  = LootSettings.GetItemBagDropChance(__instance, monster, out double BaseChance, out double LocationMultiplier, out double ExpMultiplier, out double HPMultiplier);
                    bool   Success = Randomizer.NextDouble() <= Chance;
                    string LogMessage;
                    if (Success)
                    {
                        if (MonsterLootSettings.LogDropChancesToConsole)
                        {
                            LogMessage = string.Format("Succeeded drop chance: Location = {0}, monster.ExperienceGained = {1}, monster.MaxHealth = {2}\n"
                                                       + "BaseChance = {3} ({4}%), LocationMultiplier = {5} (+{6}%), ExpMultiplier = {7}, HPMultiplier = {8} (+{9}%), TotalChance = {10} ({11}%)",
                                                       __instance.Name, monster.ExperienceGained, monster.MaxHealth,
                                                       BaseChance, (BaseChance * 100.0).ToString("0.##"), LocationMultiplier, ((LocationMultiplier - 1.0) * 100.0).ToString("0.##"),
                                                       ExpMultiplier.ToString("#.####"), HPMultiplier, ((HPMultiplier - 1.0) * 100.0).ToString("0.##"), Chance, (Chance * 100.0).ToString("0.###"));
                            Monitor.Log(LogMessage, LogLevel.Info);
                        }

                        int SpawnDirection = Randomizer.Next(4);

                        List <ItemBag> OwnedBags = ItemBag.GetAllBags(true);

                        //  Compute the odds of receiving each type of bag
                        bool CanReceiveRucksack    = LootSettings.RucksackDropSettings.SizeWeights.Any(size => size.Value > 0);
                        int  RucksackWeight        = CanReceiveRucksack ? LootSettings.RucksackDropSettings.TypeWeight : 0;
                        bool CanReceiveOmniBag     = LootSettings.OmniBagDropSettings.SizeWeights.Any(size => size.Value > 0);
                        int  OmniBagWeight         = CanReceiveOmniBag ? LootSettings.OmniBagDropSettings.TypeWeight : 0;
                        bool CanReceiveBundleBag   = LootSettings.BundleBagDropSettings.SizeWeights.Any(size => BundleBag.ValidSizes.Contains(size.Key) && size.Value > 0 && !IsSizeObsolete(OwnedBags, BundleBag.BundleBagTypeId, size.Key));
                        int  BundleBagWeight       = CanReceiveBundleBag ? LootSettings.BundleBagDropSettings.TypeWeight : 0;
                        bool CanReceiveStandardBag = LootSettings.StandardBagDropSettings.SizeWeights.Any(size => size.Value > 0);
                        int  StandardBagWeight     = CanReceiveStandardBag ? LootSettings.StandardBagDropSettings.TypeWeight : 0;

                        int TotalTypeWeight = RucksackWeight + OmniBagWeight + BundleBagWeight + StandardBagWeight;
                        if (TotalTypeWeight > 0)
                        {
                            ItemBag ChosenBag;

                            //  Pick the type of bag to spawn (Rucksack, OmniBag, BundleBag or a standard BoundedBag)
                            int ChosenTypeWeight = Randomizer.Next(0, TotalTypeWeight);
                            if (ChosenTypeWeight < RucksackWeight)
                            {
                                ContainerSize CurrentSize = GetWeightedRandomSize(LootSettings.RucksackDropSettings.SizeWeights);

                                //  Try to force a non-obsolete bag to spawn
                                if (RollDice(LootSettings.ForceNewBagTypeChance))
                                {
                                    List <ContainerSize> ValidSizes = LootSettings.RucksackDropSettings.SizeWeights.Where(size => size.Value > 0).Select(size => size.Key).ToList();
                                    ContainerSize        MaxSize    = ValidSizes.DefaultIfEmpty(ContainerSize.Small).Max();

                                    while (CurrentSize < MaxSize && IsSizeObsolete(OwnedBags, Rucksack.RucksackTypeId, CurrentSize))
                                    {
                                        CurrentSize = ValidSizes.Where(size => size > CurrentSize).OrderBy(size => size).First();
                                    }
                                }

                                //  Spawn a Rucksack
                                ChosenBag = new Rucksack(CurrentSize, false);
                            }
                            else if (ChosenTypeWeight < RucksackWeight + OmniBagWeight)
                            {
                                ContainerSize CurrentSize = GetWeightedRandomSize(LootSettings.OmniBagDropSettings.SizeWeights);

                                //  Try to force a non-obsolete bag to spawn
                                if (RollDice(LootSettings.ForceNewBagTypeChance))
                                {
                                    List <ContainerSize> ValidSizes = LootSettings.OmniBagDropSettings.SizeWeights.Where(size => size.Value > 0).Select(size => size.Key).ToList();
                                    ContainerSize        MaxSize    = ValidSizes.DefaultIfEmpty(ContainerSize.Small).Max();

                                    while (CurrentSize < MaxSize && IsSizeObsolete(OwnedBags, OmniBag.OmniBagTypeId, CurrentSize))
                                    {
                                        CurrentSize = ValidSizes.Where(size => size > CurrentSize).OrderBy(size => size).First();
                                    }
                                }

                                //  Spawn an OmniBag
                                ChosenBag = new OmniBag(CurrentSize);
                            }
                            else if (ChosenTypeWeight < RucksackWeight + OmniBagWeight + BundleBagWeight)
                            {
                                //  Spawn a BundleBag
                                ContainerSize Size = GetWeightedRandomSize(LootSettings.BundleBagDropSettings.SizeWeights.Where(size => BundleBag.ValidSizes.Contains(size.Key) && !IsSizeObsolete(OwnedBags, BundleBag.BundleBagTypeId, size.Key)));
                                ChosenBag = new BundleBag(Size, true);
                            }
                            else
                            {
                                ContainerSize CurrentSize = GetWeightedRandomSize(LootSettings.StandardBagDropSettings.SizeWeights);

                                //  Get all standard BagTypes that are available in the chosen size
                                List <BagType> StandardTypes = ItemBagsMod.BagConfig.BagTypes.Where(type => type.SizeSettings.Any(sizeCfg => sizeCfg.Size == CurrentSize)).ToList();

                                //  Try to force a non-obsolete bag to spawn
                                if (RollDice(LootSettings.ForceNewBagTypeChance))
                                {
                                    StandardTypes.RemoveAll(type => IsSizeObsolete(OwnedBags, type.Id, CurrentSize));

                                    //  If all bag types were obsolete, then keep incrementing the size until we find a non-obsolete bag to spawn
                                    if (!StandardTypes.Any())
                                    {
                                        List <ContainerSize> ValidSizes = LootSettings.StandardBagDropSettings.SizeWeights.Where(size => size.Value > 0).Select(size => size.Key).ToList();
                                        ContainerSize        MaxSize    = ValidSizes.DefaultIfEmpty(ContainerSize.Small).Max();

                                        while (CurrentSize < MaxSize && !StandardTypes.Any())
                                        {
                                            CurrentSize   = ValidSizes.Where(size => size > CurrentSize).OrderBy(size => size).First();
                                            StandardTypes = ItemBagsMod.BagConfig.BagTypes.Where(type => type.SizeSettings.Any(sizeCfg => sizeCfg.Size == CurrentSize) && !IsSizeObsolete(OwnedBags, type.Id, CurrentSize)).ToList();
                                        }
                                    }
                                }

                                if (StandardTypes.Any())
                                {
                                    //  Spawn a standard BoundedBag
                                    int ChosenTypeIndex = Randomizer.Next(StandardTypes.Count);
                                    ChosenBag = new BoundedBag(StandardTypes[ChosenTypeIndex], CurrentSize, false);
                                }
                                else
                                {
                                    ChosenBag = null;
                                }
                            }

                            if (ChosenBag != null)
                            {
                                Game1.createItemDebris(ChosenBag, Game1.player.getStandingPosition(), SpawnDirection, null, -1);
                            }
                        }
                    }
                    else if (MonsterLootSettings.LogDropChancesToConsole)
                    {
                        LogMessage = string.Format("Failed drop chance: Location = {0}, monster.ExperienceGained = {1}, monster.MaxHealth = {2}\n"
                                                   + "BaseChance = {3} ({4}%), LocationMultiplier = {5} (+{6}%), ExpMultiplier = {7}, HPMultiplier = {8} (+{9}%), TotalChance = {10} ({11}%)",
                                                   __instance.Name, monster.ExperienceGained, monster.MaxHealth,
                                                   BaseChance, (BaseChance * 100.0).ToString("0.##"), LocationMultiplier, ((LocationMultiplier - 1.0) * 100.0).ToString("0.##"),
                                                   ExpMultiplier.ToString("#.####"), HPMultiplier, ((HPMultiplier - 1.0) * 100.0).ToString("0.##"), Chance, (Chance * 100.0).ToString("0.###"));
                        Monitor.Log(LogMessage, LogLevel.Info);
                    }
                }
            }
            catch (Exception ex)
            {
                Monitor.Log(string.Format("Unhandled Error in {0}:\n{1}", nameof(MonsterDrop_Postfix), ex), LogLevel.Error);
            }
        }
Пример #3
0
        private static void OnJsonAssetsIdsFixed(IJsonAssetsAPI API, BagConfig Target)
        {
            try
            {
                ItemBagsMod.ModdedItems.ImportModdedItems(API, ItemBagsMod.BagConfig);

                if (ItemBagsMod.TemporaryModdedBagTypes.Any())
                {
                    Dictionary <string, int> AllBigCraftableIds = new Dictionary <string, int>();
                    foreach (System.Collections.Generic.KeyValuePair <int, string> KVP in Game1.bigCraftablesInformation)
                    {
                        string ObjectName = KVP.Value.Split('/').First();
                        if (!AllBigCraftableIds.ContainsKey(ObjectName))
                        {
                            AllBigCraftableIds.Add(ObjectName, KVP.Key);
                        }
                    }

                    Dictionary <string, int> AllObjectIds = new Dictionary <string, int>();
                    foreach (System.Collections.Generic.KeyValuePair <int, string> KVP in Game1.objectInformation)
                    {
                        string ObjectName = KVP.Value.Split('/').First();
                        if (!AllObjectIds.ContainsKey(ObjectName))
                        {
                            AllObjectIds.Add(ObjectName, KVP.Key);
                        }
                    }

                    IDictionary <string, int> JABigCraftableIds = API.GetAllBigCraftableIds();
                    IDictionary <string, int> JAObjectIds       = API.GetAllObjectIds();

                    //  Now that JsonAssets has finished loading the modded items, go through each one, and convert the items into StoreableBagItems (which requires an Id instead of just a Name)
                    foreach (System.Collections.Generic.KeyValuePair <ModdedBag, BagType> KVP in ItemBagsMod.TemporaryModdedBagTypes)
                    {
                        foreach (BagSizeConfig SizeCfg in KVP.Value.SizeSettings)
                        {
                            HashSet <string>        FailedItemNames = new HashSet <string>();
                            List <StoreableBagItem> Items           = new List <StoreableBagItem>();

                            foreach (ModdedItem DesiredItem in KVP.Key.Items.Where(x => x.Size <= SizeCfg.Size))
                            {
                                StoreableBagItem Item = DesiredItem.ToStoreableBagItem(JABigCraftableIds, JAObjectIds, AllBigCraftableIds, AllObjectIds);
                                if (Item == null)
                                {
                                    FailedItemNames.Add(DesiredItem.Name);
                                }
                                else
                                {
                                    Items.Add(Item);
                                }
                            }

                            SizeCfg.Items = Items;

                            if (FailedItemNames.Any())
                            {
                                int    MaxNamesShown = 5;
                                string MissingItems  = string.Format("{0}{1}", string.Join(", ", FailedItemNames.Take(MaxNamesShown)),
                                                                     FailedItemNames.Count <= MaxNamesShown ? "" : string.Format(" + {0} more", (FailedItemNames.Count - MaxNamesShown)));
                                string WarningMsg = string.Format("Warning - {0} items could not be found for modded bag '{1} {2}'. Missing Items: {3}",
                                                                  FailedItemNames.Count, SizeCfg.Size.ToString(), KVP.Key.BagName, MissingItems);
                                ItemBagsMod.ModInstance.Monitor.Log(WarningMsg, LogLevel.Warn);
                            }
                        }
                    }

                    ItemBag.GetAllBags(true).ForEach(x => x.OnJsonAssetsItemIdsFixed(API, true));
                }
            }
            catch (Exception ex)
            {
                ItemBagsMod.ModInstance.Monitor.Log(string.Format("Failed to import modded bags. Error: {0}", ex.Message), LogLevel.Error);
            }
        }
Пример #4
0
        private void Display_MenuChanged(object sender, MenuChangedEventArgs e)
        {
            //  Refresh completed Bundles in the community center
            if (e.OldMenu != null && e.OldMenu is JunimoNoteMenu)
            {
                CommunityCenterBundles.Instance = new CommunityCenterBundles();
            }

            if (e.NewMenu is ShopMenu SM)
            {
                //  Determine if the shop menu belongs to one of our managed shops
                bool    IsModifiableShop = false;
                BagShop BagShop          = BagShop.Pierre;
                if (SM.portraitPerson?.Name != null)
                {
                    //TODO test if the Stardew Valley Expanded shops like Isaac/Sophia/Alesia have non-null values for ShopMenu.portraitPerson.Name
                    if (Enum.TryParse(SM.portraitPerson.Name, out BagShop))
                    {
                        IsModifiableShop = true;
                    }
                }
                else if (SM.storeContext != null)
                {
                    if (SM.storeContext.Equals("Forest", StringComparison.CurrentCultureIgnoreCase))
                    {
                        if (SM.onPurchase?.GetMethodInfo().Name == "onTravelingMerchantShopPurchase") // nameof(Utility.onTravelingMerchantShopPurchase)
                        {
                            BagShop = BagShop.TravellingCart;
                        }
                        else
                        {
                            BagShop = BagShop.HatMouse;
                        }
                        IsModifiableShop = true;
                    }
                    else if (SM.storeContext.Equals("Town", StringComparison.CurrentCultureIgnoreCase) && SM.potraitPersonDialogue != null && SM.potraitPersonDialogue.Contains("Khadija"))
                    {
                        BagShop          = BagShop.Khadija;
                        IsModifiableShop = true;
                    }
                }

                //  Add Bag items to the shop's stock
                if (IsModifiableShop)
                {
                    Dictionary <ISalable, int[]> Stock = SM.itemPriceAndStock;

                    bool ShouldModifyStock = true;
                    if (BagShop == BagShop.Clint)
                    {
                        //  Assume user is viewing Clint tool upgrades if the stock doesn't contain Coal
                        if (!Stock.Any(x => x.Key is Object Obj && Obj.Name.Equals("Coal", StringComparison.CurrentCultureIgnoreCase)))
                        {
                            ShouldModifyStock = false;
                        }
                    }

                    if (ShouldModifyStock)
                    {
                        bool HasChangedStock = false;

                        List <ItemBag> OwnedBags = UserConfig.HideObsoleteBagsFromShops ? ItemBag.GetAllBags(true) : new List <ItemBag>();

                        //  Add Bounded Bags to stock
                        foreach (BagType Type in BagConfig.BagTypes)
                        {
                            foreach (BagSizeConfig SizeCfg in Type.SizeSettings)
                            {
                                bool IsSoldByShop = UserConfig.IsSizeVisibleInShops(SizeCfg.Size) && SizeCfg.Sellers.Contains(BagShop);
#if DEBUG
                                //IsSoldByShop = true;
#endif
                                if (IsSoldByShop)
                                {
                                    bool IsObsolete = false;
                                    if (UserConfig.HideObsoleteBagsFromShops)
                                    {
                                        IsObsolete = OwnedBags.Any(x => x is BoundedBag BB && BB.TypeInfo == Type && (int)BB.Size > (int)SizeCfg.Size);
                                    }

                                    if (!IsObsolete)
                                    {
                                        BoundedBag SellableInstance = new BoundedBag(Type, SizeCfg.Size, false);
                                        int        Price            = SellableInstance.GetPurchasePrice();
#if DEBUG
                                        //Price = 1 + (int)SizeCfg.Size;
#endif
                                        Stock.Add(SellableInstance, new int[] { Price, ShopMenu.infiniteStock });
                                        HasChangedStock = true;
                                    }
                                }
                            }
                        }

                        //  Add Bundle Bags to stock
                        foreach (BundleBagSizeConfig SizeCfg in UserConfig.BundleBagSettings)
                        {
                            ContainerSize Size = SizeCfg.Size;
                            if (BundleBag.ValidSizes.Contains(Size) && SizeCfg.Sellers.Contains(BagShop) && UserConfig.IsSizeVisibleInShops(Size))
                            {
                                bool IsObsolete = false;
                                if (UserConfig.HideObsoleteBagsFromShops)
                                {
                                    IsObsolete = OwnedBags.Any(x => x is BundleBag BB && (int)BB.Size > (int)Size);
                                }

                                if (!IsObsolete)
                                {
                                    BundleBag BundleBag = new BundleBag(Size, true);
                                    int       Price     = BundleBag.GetPurchasePrice();
                                    Stock.Add(BundleBag, new int[] { Price, ShopMenu.infiniteStock });
                                    HasChangedStock = true;
                                }
                            }
                        }

                        //  Add Rucksacks to stock
                        foreach (RucksackSizeConfig SizeCfg in UserConfig.RucksackSettings)
                        {
                            ContainerSize Size = SizeCfg.Size;
                            if (SizeCfg.Sellers.Contains(BagShop) && UserConfig.IsSizeVisibleInShops(Size))
                            {
                                bool IsObsolete = false;
                                if (UserConfig.HideObsoleteBagsFromShops)
                                {
                                    IsObsolete = OwnedBags.Any(x => x is Rucksack RS && (int)RS.Size > (int)Size);
                                }

                                if (!IsObsolete)
                                {
                                    Rucksack Rucksack = new Rucksack(Size, false, AutofillPriority.Low);
                                    int      Price    = Rucksack.GetPurchasePrice();
                                    Stock.Add(Rucksack, new int[] { Price, ShopMenu.infiniteStock });
                                    HasChangedStock = true;
                                }
                            }
                        }

                        //  Add Omni Bags to stock
                        foreach (OmniBagSizeConfig SizeCfg in UserConfig.OmniBagSettings)
                        {
                            ContainerSize Size = SizeCfg.Size;
                            if (SizeCfg.Sellers.Contains(BagShop) && UserConfig.IsSizeVisibleInShops(Size))
                            {
                                bool IsObsolete = false;
                                if (UserConfig.HideObsoleteBagsFromShops)
                                {
                                    IsObsolete = OwnedBags.Any(x => x is OmniBag OB && (int)OB.Size > (int)Size);
                                }

                                if (!IsObsolete)
                                {
                                    OmniBag OmniBag = new OmniBag(Size);
                                    int     Price   = OmniBag.GetPurchasePrice();
                                    Stock.Add(OmniBag, new int[] { Price, ShopMenu.infiniteStock });
                                    HasChangedStock = true;
                                }
                            }
                        }

                        if (HasChangedStock)
                        {
                            SM.setItemPriceAndStock(Stock);
                        }
                    }
                }
            }
        }