/// <summary>Migrate legacy container data, if needed.</summary> /// <param name="location">The location whose chests to migrate.</param> private void MigrateLegacyData(GameLocation location) { foreach (var chest in this.ChestFactory.GetChests(RangeHandler.SpecificLocation(location))) { chest.Container.MigrateLegacyData(); } }
/// <summary>Open the menu UI.</summary> private void OpenMenu() { if (this.Config.Range == ChestRange.None) { return; } // handle disabled location if (this.IsDisabledLocation(Game1.currentLocation)) { CommonHelper.ShowInfoMessage(I18n.Errors_DisabledFromHere(), duration: 1000); return; } // get chests RangeHandler range = this.GetCurrentRange(); ManagedChest[] chests = this.ChestFactory.GetChests(range, excludeHidden: true).ToArray(); ManagedChest selectedChest = ChestFactory.GetBestMatch(chests, this.LastChest.Value) ?? chests.FirstOrDefault(p => object.ReferenceEquals(p.Location, Game1.currentLocation)) ?? chests.FirstOrDefault(); // show error if (selectedChest == null) { CommonHelper.ShowInfoMessage(this.GetNoChestsFoundError(), duration: 1000); return; } // render menu Game1.activeClickableMenu = selectedChest.OpenMenu(); }
/// <summary>Change the chest UI overlay if needed to match the current menu.</summary> /// <remarks>Since the menu gets reopened whenever the chest inventory changes, this method needs to be called before/after tick to avoid a visible UI flicker.</remarks> private void ChangeOverlayIfNeeded() { IClickableMenu menu = Game1.activeClickableMenu; // already matches menu if (this.CurrentOverlay?.ForMenuInstance == menu) { return; } // remove old overlay if (this.CurrentOverlay != null) { this.CurrentOverlay?.Dispose(); this.CurrentOverlay = null; } // get open chest ManagedChest chest = this.ChestFactory.GetChestFromMenu(menu); if (chest == null) { return; } // reopen shipping box in standard chest UI if needed // This is called in two cases: // - When the player opens the shipping bin directly, it opens the shipping bin view instead of the full chest view. // - When the player changes the items in the chest view, it reopens itself but loses the constructor args (e.g. highlight function). if (this.Config.EnableShippingBin && chest.Container is ShippingBinContainer) { if (menu is ItemGrabMenu chestMenu && (!chestMenu.showReceivingMenu || !(chestMenu.inventory.highlightMethod?.Target is ShippingBinContainer))) { menu = (ItemGrabMenu)chest.OpenMenu(); Game1.activeClickableMenu = menu; } } // add overlay RangeHandler range = this.GetCurrentRange(); ManagedChest[] chests = this.ChestFactory.GetChests(range, excludeHidden: true, alwaysIncludeContainer: chest.Container).ToArray(); bool isAutomateInstalled = this.Helper.ModRegistry.IsLoaded("Pathoschild.Automate"); switch (menu) { case ItemGrabMenu chestMenu: this.CurrentOverlay = new ChestOverlay(chestMenu, chest, chests, this.Config, this.Keys, this.Helper.Events, this.Helper.Input, this.Helper.Translation, showAutomateOptions: isAutomateInstalled && chest.CanConfigureAutomate); break; case ShopMenu shopMenu: this.CurrentOverlay = new ShopMenuOverlay(shopMenu, chest, chests, this.Config, this.Keys, this.Helper.Events, this.Helper.Input, this.Helper.Translation, showAutomateOptions: isAutomateInstalled && chest.CanConfigureAutomate); break; } this.CurrentOverlay.OnChestSelected += selected => { this.SelectedInventory = selected.Container.Inventory; Game1.activeClickableMenu = selected.OpenMenu(); }; }
/// <summary>Open the menu UI.</summary> private void OpenMenu() { if (this.Config.Range == ChestRange.None) { return; } // handle disabled location if (this.IsDisabledLocation(Game1.currentLocation)) { CommonHelper.ShowInfoMessage("Remote chest access is disabled here. :)", duration: 1000); return; } // get chests RangeHandler range = this.GetCurrentRange(); ManagedChest[] chests = this.ChestFactory.GetChests(range, excludeHidden: true).ToArray(); ManagedChest selectedChest = chests.FirstOrDefault(p => p.Container.IsSameAs(this.SelectedInventory)) ?? chests.FirstOrDefault(); // render menu if (selectedChest != null) { Game1.activeClickableMenu = selectedChest.OpenMenu(); } else { CommonHelper.ShowInfoMessage( "You don't have any chests " + (this.Config.Range == ChestRange.Unlimited ? "yet" : "in range") + ". :)", duration: 1000 ); } }
/// <summary>Open the menu UI.</summary> private void OpenMenu() { if (this.Config.Range == ChestRange.None) { return; } // handle disabled location if (this.IsDisabledLocation(Game1.currentLocation)) { CommonHelper.ShowInfoMessage(this.Helper.Translation.Get("errors.disabled-from-here"), duration: 1000); return; } // get chests RangeHandler range = this.GetCurrentRange(); ManagedChest[] chests = this.ChestFactory.GetChests(range, excludeHidden: true).ToArray(); ManagedChest selectedChest = chests.FirstOrDefault(p => p.Container.IsSameAs(this.SelectedInventory)) ?? chests.FirstOrDefault(); // show error if (selectedChest == null) { string translationKey = this.GetNoChestsFoundErrorKey(); CommonHelper.ShowInfoMessage(this.Helper.Translation.Get(translationKey), duration: 1000); return; } // render menu Game1.activeClickableMenu = selectedChest.OpenMenu(); }
/// <summary>Open the menu UI.</summary> private void OpenMenu() { if (this.Config.Range == ChestRange.None) { return; } // get chests RangeHandler rangeHandler = new RangeHandler(this.Data.WorldAreas, this.Config.Range, Game1.currentLocation); ManagedChest[] chests = this.ChestFactory.GetChests(rangeHandler, excludeHidden: true).ToArray(); ManagedChest selectedChest = chests.FirstOrDefault(p => p.Container.Inventory == this.SelectedInventory) ?? chests.FirstOrDefault(); // render menu if (selectedChest != null) { Game1.activeClickableMenu = selectedChest.OpenMenu(); } else { CommonHelper.ShowInfoMessage( "You don't have any chests " + (this.Config.Range == ChestRange.Unlimited ? "yet" : "in range") + ". :)", duration: 1000 ); } }
/// <summary>Get all player chests.</summary> /// <param name="range">Determines whether given locations are in range of the player for remote chest access.</param> /// <param name="excludeHidden">Whether to exclude chests marked as hidden.</param> /// <param name="alwaysIncludeContainer">A container to include even if it would normally be hidden.</param> public IEnumerable <ManagedChest> GetChests(RangeHandler range, bool excludeHidden = false, IContainer alwaysIncludeContainer = null) { IEnumerable <ManagedChest> Search() { // get location info var locations = ( from GameLocation location in this.GetAccessibleLocations() select new { Location = location, Category = this.GetCategory(location) } ) .ToArray(); IDictionary <string, int> defaultCategories = locations .GroupBy(p => p.Category) .Where(p => p.Count() > 1) .ToDictionary(p => p.Key, p => 0); // find chests foreach (var entry in locations) { // get info GameLocation location = entry.Location; string category = defaultCategories.ContainsKey(entry.Category) ? I18n.DefaultCategory_Duplicate(locationName: entry.Category, number: ++defaultCategories[entry.Category]) : entry.Category; // chests in location { int namelessChests = 0; int namelessGrabbers = 0; int namelessHoppers = 0; int namelessMiniShippingBins = 0; int junimoChestCount = 0; foreach (KeyValuePair <Vector2, SObject> pair in location.Objects.Pairs) { Vector2 tile = pair.Key; SObject obj = pair.Value; // chests if (obj is Chest chest && chest.playerChest.Value) { if (chest.SpecialChestType == Chest.SpecialChestTypes.JunimoChest && ++junimoChestCount > 1) { continue; // only list one Junimo Chest per location (since they share inventory) } yield return(new ManagedChest( container: new ChestContainer(chest, context: chest, showColorPicker: this.CanShowColorPicker(chest, location), this.Reflection), location: location, tile: tile, defaultDisplayName: chest.SpecialChestType switch { Chest.SpecialChestTypes.AutoLoader => I18n.DefaultName_Other(name: GameI18n.GetBigCraftableName(275), number: ++namelessHoppers), Chest.SpecialChestTypes.JunimoChest => GameI18n.GetBigCraftableName(256), Chest.SpecialChestTypes.MiniShippingBin => I18n.DefaultName_Other(name: GameI18n.GetBigCraftableName(248), number: ++namelessMiniShippingBins), _ => I18n.DefaultName_Other(name: GameI18n.GetBigCraftableName(130), number: ++namelessChests) },
/// <summary>Get the player chest on the specified tile (if any).</summary> /// <param name="tile">The tile to check.</param> public ManagedChest GetChestFromTile(Vector2 tile) { if (!Game1.currentLocation.Objects.TryGetValue(tile, out Object obj) || !(obj is Chest chest)) { return(null); } RangeHandler range = RangeHandler.CurrentLocation(); return(this.GetChests(range).FirstOrDefault(p => p.Container.IsSameAs(chest.items))); }
/// <summary> /// The awake function. /// </summary> private void Awake() { this.idleHandler = this.ResetStoppingDistance; this.battleHandler = this.ResetStoppingDistance; this.harvestHandler = this.ResetStoppingDistance; this.stockHandler = this.TallyResources; this.decontaminationHandler = this.ResetStoppingDistance; this.pickupHandler = this.ResetStoppingDistance; this.theMinerFsm.CreateState("Init", null); this.theMinerFsm.CreateState("Idle", this.idleHandler); this.theMinerFsm.CreateState("Battle", this.battleHandler); this.theMinerFsm.CreateState("Harvest", this.harvestHandler); this.theMinerFsm.CreateState("Stock", this.stockHandler); this.theMinerFsm.CreateState("Decontaminate", this.decontaminationHandler); this.theMinerFsm.CreateState("PickUp", this.pickupHandler); this.theMinerFsm.AddTransition("Init", "Idle", "auto"); this.theMinerFsm.AddTransition("Idle", "Battle", "IdleToBattle"); this.theMinerFsm.AddTransition("Battle", "Idle", "BattleToIdle"); this.theMinerFsm.AddTransition("Idle", "Harvest", "IdleToHarvest"); this.theMinerFsm.AddTransition("Harvest", "Idle", "HarvestToIdle"); this.theMinerFsm.AddTransition("Battle", "Harvest", "BattleToHarvest"); this.theMinerFsm.AddTransition("Harvest", "Battle", "HarvestToBattle"); this.theMinerFsm.AddTransition("Harvest", "Stock", "HarvestToStock"); this.theMinerFsm.AddTransition("Battle", "Stock", "BattleToStock"); this.theMinerFsm.AddTransition("Idle", "Stock", "IdleToStock"); this.theMinerFsm.AddTransition("Stock", "Idle", "StockToIdle"); this.theMinerFsm.AddTransition("Stock", "Battle", "StockToBattle"); this.theMinerFsm.AddTransition("Stock", "Harvest", "StockToHarvest"); this.theMinerFsm.AddTransition("Harvest", "Decontaminate", "HarvestToDecontaminate"); this.theMinerFsm.AddTransition("Stock", "Decontaminate", "StockToDecontaminate"); this.theMinerFsm.AddTransition("Decontaminate", "Stock", "DecontaminateToStock"); this.theMinerFsm.AddTransition("Decontaminate", "Harvest", "DecontaminateToHarvest"); this.theMinerFsm.AddTransition("Decontaminate", "Idle", "DecontaminateToIdle"); this.theMinerFsm.AddTransition("Idle", "Decontaminate", "IdleToDecontaminate"); this.theMinerFsm.AddTransition("Decontaminate", "Battle", "DecontaminateToBattle"); this.theMinerFsm.AddTransition("Battle", "Decontaminate", "BattleToDecontaminate"); this.theMinerFsm.AddTransition("PickUp", "Idle", "PickUpToIdle"); this.theMinerFsm.AddTransition("PickUp", "Battle", "PickUpToBattle"); this.theMinerFsm.AddTransition("PickUp", "Harvest", "PickUpToHarvest"); this.theMinerFsm.AddTransition("PickUp", "Decontaminate", "PickUpToDecontaminate"); this.theMinerFsm.AddTransition("PickUp", "Stock", "PickUpToStock"); this.theMinerFsm.AddTransition("Idle", "PickUp", "IdleToPickUp"); this.theMinerFsm.AddTransition("Battle", "PickUp", "BattleToPickUp"); this.theMinerFsm.AddTransition("Harvest", "PickUp", "HarvestToPickUp"); this.theMinerFsm.AddTransition("Stock", "PickUp", "StockToPickUp"); this.theMinerFsm.AddTransition("Decontaminate", "PickUp", "DecontaminateToPickUp"); }
/// <summary>Get all player chests.</summary> /// <param name="range">Determines whether given locations are in range of the player for remote chest access.</param> /// <param name="excludeHidden">Whether to exclude chests marked as hidden.</param> /// <param name="alwaysIncludeContainer">A container to include even if it would normally be hidden.</param> public IEnumerable <ManagedChest> GetChests(RangeHandler range, bool excludeHidden = false, IContainer alwaysIncludeContainer = null) { IEnumerable <ManagedChest> Search() { // get location info var locations = ( from GameLocation location in this.GetAccessibleLocations() select new { Location = location, Category = this.GetCategory(location) } ) .ToArray(); IDictionary <string, int> defaultCategories = locations .GroupBy(p => p.Category) .Where(p => p.Count() > 1) .ToDictionary(p => p.Key, p => 0); // find chests foreach (var entry in locations) { // get info GameLocation location = entry.Location; string category = defaultCategories.ContainsKey(entry.Category) ? I18n.DefaultCategory_Duplicate(locationName: entry.Category, number: ++defaultCategories[entry.Category]) : entry.Category; // chests in location { int namelessChests = 0; int namelessGrabbers = 0; foreach (KeyValuePair <Vector2, SObject> pair in location.Objects.Pairs) { Vector2 tile = pair.Key; SObject obj = pair.Value; // chests if (obj is Chest chest && chest.playerChest.Value) { yield return(new ManagedChest( container: new ChestContainer(chest, context: chest, showColorPicker: this.CanShowColorPicker(chest, location), this.Reflection), location: location, tile: tile, defaultDisplayName: I18n.DefaultName_Other(name: GameI18n.GetBigCraftableName(130), number: ++namelessChests), defaultCategory: category )); }
public void testingThatRangesAreRemovedCorrectly(int drawSize, int drawPool, int result) { RangeHandler rangeHandler = new RangeHandler(drawPool); NumberGenerator numberGenerator = new NumberGenerator(drawSize, drawPool); numberGenerator.generateList(new List <int>(), 0, 1, numberGenerator.highestStartPoint, false); Exclusions rangeExclusions = new Exclusions(); rangeExclusions.rangeFrequencyExclusions = new int[] { 4, 5 }; numberGenerator.exclusions = rangeExclusions; int rangeToRemove1 = rangeHandler.getFrequencyOfOccurrence(numberGenerator.numberCollection, 4); int rangeToRemove2 = rangeHandler.getFrequencyOfOccurrence(numberGenerator.numberCollection, 5); numberGenerator.numberCollection = new List <List <int> >(); numberGenerator.generateList(new List <int>(), 0, 1, numberGenerator.highestStartPoint, true); result = result - rangeToRemove1 - rangeToRemove2; Assert.Equal(result, numberGenerator.numberCollection.Count); }
/// <summary>Migrate legacy container data, if needed.</summary> private void MigrateLegacyData() { // chests foreach (var chest in this.ChestFactory.GetChests(RangeHandler.Unlimited())) { chest.Container.MigrateLegacyData(); } // shipping bin var binData = this.Helper.Data.ReadSaveData <ContainerData>("shipping-bin"); if (binData != null) { Farm farm = Game1.getFarm(); binData.ToModData(farm.modData, discriminator: ShippingBinContainer.ModDataDiscriminator); this.Helper.Data.WriteSaveData <ContainerData>("shipping-bin", null); } }
/// <summary>Get all player chests.</summary> /// <param name="range">Determines whether given locations are in range of the player for remote chest access.</param> /// <param name="excludeHidden">Whether to exclude chests marked as hidden.</param> /// <param name="alwaysIncludeContainer">A container to include even if it would normally be hidden.</param> public IEnumerable <ManagedChest> GetChests(RangeHandler range, bool excludeHidden = false, IContainer alwaysIncludeContainer = null) { IEnumerable <ManagedChest> Search() { foreach (GameLocation location in this.GetAccessibleLocations()) { // chests in location { int namelessChests = 0; int namelessGrabbers = 0; foreach (KeyValuePair <Vector2, SObject> pair in location.Objects.Pairs) { Vector2 tile = pair.Key; SObject obj = pair.Value; // chests if (obj is Chest chest && chest.playerChest.Value) { yield return(new ManagedChest(new ChestContainer(chest, this.Reflection), location, tile, this.Translations.Get("default-name.chest", new { number = ++namelessChests }))); }
/// <summary>The method invoked when the active menu changes.</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event arguments.</param> private void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged e) { // remove overlay if (e.PriorMenu is ItemGrabMenu) { this.ManageChestOverlay?.Dispose(); this.ManageChestOverlay = null; } // add overlay if (e.NewMenu is ItemGrabMenu chestMenu) { // get open chest ManagedChest chest = this.ChestFactory.GetChestFromMenu(chestMenu); if (chest == null) { return; } // reopen shipping box in standard chest UI if needed // This is called in two cases: // - When the player opens the shipping bin directly, it opens the shipping bin view instead of the full chest view. // - When the player changes the items in the chest view, it reopens itself but loses the constructor args (e.g. highlight function). if (this.Config.EnableShippingBin && chest.Container is ShippingBinContainer && (!chestMenu.showReceivingMenu || !(chestMenu.inventory.highlightMethod?.Target is ShippingBinContainer))) { chestMenu = chest.OpenMenu(); Game1.activeClickableMenu = chestMenu; } // add overlay RangeHandler range = this.GetCurrentRange(); ManagedChest[] chests = this.ChestFactory.GetChests(range, excludeHidden: true, alwaysIncludeContainer: chest.Container).ToArray(); bool isAutomateInstalled = this.Helper.ModRegistry.IsLoaded("Pathoschild.Automate"); this.ManageChestOverlay = new ManageChestOverlay(chestMenu, chest, chests, this.Config, this.Helper.Translation, showAutomateOptions: isAutomateInstalled); this.ManageChestOverlay.OnChestSelected += selected => { this.SelectedInventory = selected.Container.Inventory; Game1.activeClickableMenu = selected.OpenMenu(); }; } }
/// <summary>Get the player chest from the specified menu (if any).</summary> /// <param name="menu">The menu to check.</param> public ManagedChest GetChestFromMenu(ItemGrabMenu menu) { RangeHandler range = RangeHandler.Unlimited(); // get from opened inventory { object target = menu.behaviorOnItemGrab?.Target; List <Item> inventory = (target as Chest)?.items ?? (target as IContainer)?.Inventory; if (inventory != null) { ManagedChest chest = this.GetChests(range).FirstOrDefault(p => p.Container.IsSameAs(inventory)); if (chest != null) { return(chest); } } } // fallback to open chest return(this.GetChests(range).FirstOrDefault(p => p.Container.IsOpen())); }
/// <summary>The method invoked when the active menu changes.</summary> /// <param name="sender">The event sender.</param> /// <param name="e">The event arguments.</param> private void MenuEvents_MenuChanged(object sender, EventArgsClickableMenuChanged e) { // remove overlay if (e.PriorMenu is ItemGrabMenu) { this.ManageChestOverlay?.Dispose(); this.ManageChestOverlay = null; } // add overlay if (e.NewMenu is ItemGrabMenu chestMenu) { // get open chest ManagedChest chest = this.ChestFactory.GetChestFromMenu(chestMenu); if (chest == null) { return; } // reopen shipping box in standard chest UI if (chest.Container is ShippingBinContainer && !chestMenu.showReceivingMenu) { Game1.activeClickableMenu = chest.OpenMenu(); } // add overlay RangeHandler range = new RangeHandler(this.Data.WorldAreas, this.Config.Range, Game1.currentLocation); ManagedChest[] chests = this.ChestFactory.GetChests(range, excludeHidden: true, alwaysIncludeContainer: chest.Container).ToArray(); this.ManageChestOverlay = new ManageChestOverlay(chestMenu, chest, chests, this.Config, this.Helper.Translation); this.ManageChestOverlay.OnChestSelected += selected => { this.SelectedInventory = selected.Container.Inventory; Game1.activeClickableMenu = selected.OpenMenu(); }; } }
public RangeHandlerTests() { rangeHandler = new RangeHandler(60); }
/// <inheritdoc /> public MultirangeHandler(PostgresMultirangeType pgMultirangeType, RangeHandler <TSubtype> rangeHandler) : base(pgMultirangeType) => RangeHandler = rangeHandler;
/// <summary>Get all player chests.</summary> /// <param name="range">Determines whether given locations are in range of the player for remote chest access.</param> /// <param name="excludeHidden">Whether to exclude chests marked as hidden.</param> /// <param name="alwaysIncludeContainer">A container to include even if it would normally be hidden.</param> public IEnumerable <ManagedChest> GetChests(RangeHandler range, bool excludeHidden = false, IContainer alwaysIncludeContainer = null) { IEnumerable <ManagedChest> Search() { foreach (GameLocation location in CommonHelper.GetLocations()) { // chests in location { int namelessChests = 0; foreach (KeyValuePair <Vector2, Object> pair in location.Objects) { Vector2 tile = pair.Key; if (pair.Value is Chest chest && chest.playerChest) { yield return(new ManagedChest(new ChestContainer(chest), location, tile, this.Translations.Get("default-name.chest", new { number = ++namelessChests }))); } } } // farmhouse containers if (location is FarmHouse house && Game1.player.HouseUpgradeLevel > 0) { Chest fridge = house.fridge; if (fridge != null) { yield return(new ManagedChest(new ChestContainer(fridge), location, Vector2.Zero, this.Translations.Get("default-name.fridge"))); } } // buildings if (location is BuildableGameLocation buildableLocation) { int namelessHuts = 0; foreach (Building building in buildableLocation.buildings) { if (building is JunimoHut hut) { yield return(new ManagedChest(new JunimoHutContainer(hut), location, new Vector2(hut.tileX, hut.tileY), this.Translations.Get("default-name.junimo-hut", new { number = ++namelessHuts }))); } } } // shipping bin if (this.EnableShippingBin && location is Farm farm) { yield return(new ManagedChest(new ShippingBinContainer(farm, this.Reflection), farm, Vector2.Zero, this.Translations.Get("default-name.shipping-bin"))); } } } return( from chest in Search() orderby chest.Order ?? int.MaxValue, chest.Name where chest.Container.IsSameAs(alwaysIncludeContainer) || ( (!excludeHidden || !chest.IsIgnored) && range.IsInRange(chest.Location) ) select chest ); }
/// <inheritdoc /> public MultirangeHandler(PostgresMultirangeType pgMultirangeType, RangeHandler <TSubtype1, TSubtype2> rangeHandler) : base(pgMultirangeType, rangeHandler) { }