/// <summary>Get the human-readable farm type selected by the player.</summary> private string?GetFarmType() { // get farm type int farmType = Game1.whichFarm; if (this.IsLoadMenu) { XElement?saveData = this.RawSaveData?.Value; string? rawType = saveData?.Element("whichFarm")?.Value; farmType = rawType != null?int.Parse(rawType) : -1; } // get type name return(farmType switch { -1 => null, Farm.combat_layout => GameI18n.GetString("Strings\\UI:Character_FarmCombat").Replace("_", Environment.NewLine), Farm.default_layout => GameI18n.GetString("Strings\\UI:Character_FarmStandard").Replace("_", Environment.NewLine), Farm.forest_layout => GameI18n.GetString("Strings\\UI:Character_FarmForaging").Replace("_", Environment.NewLine), Farm.mountains_layout => GameI18n.GetString("Strings\\UI:Character_FarmMining").Replace("_", Environment.NewLine), Farm.riverlands_layout => GameI18n.GetString("Strings\\UI:Character_FarmFishing").Replace("_", Environment.NewLine), Farm.fourCorners_layout => GameI18n.GetString("Strings\\UI:Character_FarmFourCorners").Replace("_", Environment.NewLine), Farm.beach_layout => GameI18n.GetString("Strings\\UI:Character_FarmBeach").Replace("_", Environment.NewLine), _ => I18n.Player_FarmMap_Custom() });
/// <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) },
/********* ** Private methods *********/ /// <summary>Get whether the eat/drink confirmation is being shown.</summary> /// <param name="menu">The confirmation menu.</param> private bool IsConfirmationShown(out DialogueBox menu) { if (Game1.player.itemToEat != null && Game1.activeClickableMenu is DialogueBox dialogue) { string actualLine = this.Reflection.GetField <List <string> >(dialogue, "dialogues").GetValue().FirstOrDefault(); bool isConfirmation = actualLine == GameI18n.GetString("Strings\\StringsFromCSFiles:Game1.cs.3159", Game1.player.itemToEat.DisplayName) || // drink actualLine == GameI18n.GetString("Strings\\StringsFromCSFiles:Game1.cs.3160", Game1.player.itemToEat.DisplayName); // eat if (isConfirmation) { menu = dialogue; return(true); } } menu = null; return(false); }
/// <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 )); }
/// <summary>Register the config menu if available.</summary> public void Register() { // get config menu var menu = this.ConfigMenu; if (!menu.IsLoaded) { return; } menu.Register(); // main options menu .AddSectionTitle(I18n.Config_Title_MainOptions) .AddCheckbox( name: I18n.Config_Enabled_Name, tooltip: I18n.Config_Enabled_Desc, get: config => config.Enabled, set: (config, value) => config.Enabled = value ) .AddCheckbox( name: I18n.Config_JunimoHutsOutputGems_Name, tooltip: I18n.Config_JunimoHutsOutputGems_Desc, get: config => config.PullGemstonesFromJunimoHuts, set: (config, value) => config.PullGemstonesFromJunimoHuts = value ) .AddNumberField( name: I18n.Config_AutomationInterval_Name, tooltip: I18n.Config_AutomationInterval_Desc, get: config => config.AutomationInterval, set: (config, value) => config.AutomationInterval = value, min: 1, max: 600 ) .AddKeyBinding( name: I18n.Config_ToggleOverlayKey_Name, tooltip: I18n.Config_ToggleOverlayKey_Desc, get: config => config.Controls.ToggleOverlay, set: (config, value) => config.Controls.ToggleOverlay = value ); // mod compatibility menu .AddSectionTitle(I18n.Config_Title_ModCompatibility) .AddCheckbox( name: I18n.Config_BetterJunimos_Name, tooltip: I18n.Config_BetterJunimos_Desc, get: config => config.ModCompatibility.BetterJunimos, set: (config, value) => config.ModCompatibility.BetterJunimos = value ) .AddCheckbox( name: I18n.Config_WarnForMissingBridgeMod_Name, tooltip: I18n.Config_WarnForMissingBridgeMod_Desc, get: config => config.ModCompatibility.WarnForMissingBridgeMod, set: (config, value) => config.ModCompatibility.WarnForMissingBridgeMod = value ); // connectors menu.AddSectionTitle(I18n.Config_Title_Connectors); foreach (DataModelFloor entry in this.Data.FloorNames.Values) { int itemId = entry.ItemId; menu.AddCheckbox( name: () => GameI18n.GetObjectName(itemId), tooltip: () => I18n.Config_Connector_Desc(itemName: GameI18n.GetObjectName(itemId)), get: config => this.HasConnector(config, entry.Name), set: (config, value) => this.SetConnector(config, entry.Name, value) ); } menu.AddTextbox( name: I18n.Config_CustomConnectors_Name, tooltip: I18n.Config_CustomConnectors_Desc, get: config => string.Join(", ", config.ConnectorNames.Where(this.IsCustomConnector)), set: (config, value) => this.SetCustomConnectors(config, value.Split(',').Select(p => p.Trim())) ); // machine overrides menu.AddSectionTitle(I18n.Config_Title_MachineOverrides); foreach (var entry in this.Data.DefaultMachineOverrides) { menu.AddCheckbox( name: () => this.GetTranslatedMachineName(entry.Key), tooltip: () => I18n.Config_Override_Desc(machineName: this.GetTranslatedMachineName(entry.Key)), get: config => this.IsMachineEnabled(config, entry.Key), set: (config, value) => this.SetCustomOverride(config, entry.Key, value) ); } menu.AddParagraph(I18n.Config_CustomOverridesNote); }
/// <summary>Get the custom fields for a crop.</summary> /// <param name="dirt">The dirt the crop is planted in, if applicable.</param> /// <param name="crop">The crop to represent.</param> /// <param name="isSeed">Whether the crop being displayed is for an unplanted seed.</param> private IEnumerable <ICustomField> GetCropFields(HoeDirt dirt, Crop crop, bool isSeed) { if (crop == null) { yield break; } var data = new CropDataParser(crop, isPlanted: !isSeed); bool isForage = crop.whichForageCrop.Value > 0 && crop.fullyGrown.Value; // show crop fields for growing mixed seeds // add next-harvest field if (!isSeed) { // get next harvest SDate nextHarvest = data.GetNextHarvest(); // generate field string summary; if (data.CanHarvestNow) { summary = I18n.Generic_Now(); } else if (!Game1.currentLocation.SeedsIgnoreSeasonsHere() && !data.Seasons.Contains(nextHarvest.Season)) { summary = I18n.Crop_Harvest_TooLate(date: this.Stringify(nextHarvest)); } else { summary = $"{this.Stringify(nextHarvest)} ({this.GetRelativeDateStr(nextHarvest)})"; } yield return(new GenericField(I18n.Crop_Harvest(), summary)); } // crop summary if (!isForage) { List <string> summary = new List <string>(); // harvest if (!crop.forageCrop.Value) { summary.Add(data.HasMultipleHarvests ? I18n.Crop_Summary_HarvestOnce(daysToFirstHarvest: data.DaysToFirstHarvest) : I18n.Crop_Summary_HarvestMulti(daysToFirstHarvest: data.DaysToFirstHarvest, daysToNextHarvests: data.DaysToSubsequentHarvest) ); } // seasons summary.Add(I18n.Crop_Summary_Seasons(seasons: string.Join(", ", I18n.GetSeasonNames(data.Seasons)))); // drops if (crop.minHarvest != crop.maxHarvest && crop.chanceForExtraCrops.Value > 0) { summary.Add(I18n.Crop_Summary_DropsXToY(min: crop.minHarvest.Value, max: crop.maxHarvest.Value, percent: (int)Math.Round(crop.chanceForExtraCrops.Value * 100, 2))); } else if (crop.minHarvest.Value > 1) { summary.Add(I18n.Crop_Summary_DropsX(count: crop.minHarvest.Value)); } // crop sale price Item drop = data.GetSampleDrop(); summary.Add(I18n.Crop_Summary_SellsFor(price: GenericField.GetSaleValueString(this.GetSaleValue(drop, false), 1))); // generate field yield return(new GenericField(I18n.Crop_Summary(), "-" + string.Join($"{Environment.NewLine}-", summary))); } // dirt water/fertilizer state if (dirt != null && !isForage) { // watered yield return(new GenericField(I18n.Crop_Watered(), this.Stringify(dirt.state.Value == HoeDirt.watered))); // fertilizer yield return(new GenericField(I18n.Crop_Fertilized(), dirt.fertilizer.Value switch { HoeDirt.noFertilizer => this.Stringify(false), HoeDirt.speedGro => GameI18n.GetObjectName(465), // Speed-Gro HoeDirt.superSpeedGro => GameI18n.GetObjectName(466), // Deluxe Speed-Gro HoeDirt.hyperSpeedGro => GameI18n.GetObjectName(918), // Hyper Speed-Gro HoeDirt.fertilizerLowQuality => GameI18n.GetObjectName(368), // Basic Fertilizer HoeDirt.fertilizerHighQuality => GameI18n.GetObjectName(369), // Quality Fertilizer HoeDirt.fertilizerDeluxeQuality => GameI18n.GetObjectName(919), // Deluxe Fertilizer HoeDirt.waterRetentionSoil => GameI18n.GetObjectName(370), // Basic Retaining Soil HoeDirt.waterRetentionSoilQuality => GameI18n.GetObjectName(371), // Quality Retaining Soil HoeDirt.waterRetentionSoilDeluxe => GameI18n.GetObjectName(920), // Deluxe Retaining Soil _ => I18n.Generic_Unknown() }));
/********* ** Public methods *********/ /// <summary>Get the config UI fields to show in the cheats menu.</summary> /// <param name="context">The cheat context.</param> public override IEnumerable <OptionsElement> GetFields(CheatContext context) { return(this.SortFields( new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(10), value: context.Config.FastBeeHouse, setValue: value => context.Config.FastBeeHouse = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(90), value: context.Config.FastBoneMill, setValue: value => context.Config.FastBoneMill = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(163), value: context.Config.FastCask, setValue: value => context.Config.FastCask = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(114), value: context.Config.FastCharcoalKiln, setValue: value => context.Config.FastCharcoalKiln = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(16), value: context.Config.FastCheesePress, setValue: value => context.Config.FastCheesePress = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(246), value: context.Config.FastCoffeeMaker, setValue: value => context.Config.FastCoffeeMaker = value ), new CheatsOptionsCheckbox( label: GameI18n.GetObjectName(710), value: context.Config.FastCrabPot, setValue: value => context.Config.FastCrabPot = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(21), value: context.Config.FastCrystalarium, setValue: value => context.Config.FastCrystalarium = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(265), value: context.Config.FastDeconstructor, setValue: value => context.Config.FastDeconstructor = value ), new CheatsOptionsCheckbox( label: I18n.FastMachines_FruitTrees(), value: context.Config.FastFruitTree, setValue: value => context.Config.FastFruitTree = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(13), value: context.Config.FastFurnace, setValue: value => context.Config.FastFurnace = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(182), value: context.Config.FastGeodeCrusher, setValue: value => context.Config.FastGeodeCrusher = value ), new CheatsOptionsCheckbox( label: I18n.FastMachines_ReadyInTheMorning(machineName: GameI18n.GetBigCraftableName(101)), value: context.Config.FastIncubator, setValue: value => context.Config.FastIncubator = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(12), value: context.Config.FastKeg, setValue: value => context.Config.FastKeg = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(9), value: context.Config.FastLightningRod, setValue: value => context.Config.FastLightningRod = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(17), value: context.Config.FastLoom, setValue: value => context.Config.FastLoom = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(24), value: context.Config.FastMayonnaiseMachine, setValue: value => context.Config.FastMayonnaiseMachine = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(128), value: context.Config.FastMushroomBox, setValue: value => context.Config.FastMushroomBox = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(19), value: context.Config.FastOilMaker, setValue: value => context.Config.FastOilMaker = value ), new CheatsOptionsCheckbox( label: I18n.FastMachines_ReadyInTheMorning(GameI18n.GetBigCraftableName(254)), value: context.Config.FastOstrichIncubator, setValue: value => context.Config.FastOstrichIncubator = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(15), value: context.Config.FastPreservesJar, setValue: value => context.Config.FastPreservesJar = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(20), value: context.Config.FastRecyclingMachine, setValue: value => context.Config.FastRecyclingMachine = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(25), value: context.Config.FastSeedMaker, setValue: value => context.Config.FastSeedMaker = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(158), value: context.Config.FastSlimeEggPress, setValue: value => context.Config.FastSlimeEggPress = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(156), value: context.Config.FastSlimeIncubator, setValue: value => context.Config.FastSlimeIncubator = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(117), value: context.Config.FastSodaMachine, setValue: value => context.Config.FastSodaMachine = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(231), value: context.Config.FastSolarPanel, setValue: value => context.Config.FastSolarPanel = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(127), value: context.Config.FastStatueOfEndlessFortune, setValue: value => context.Config.FastStatueOfEndlessFortune = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(160), value: context.Config.FastStatueOfPerfection, setValue: value => context.Config.FastStatueOfPerfection = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(280), value: context.Config.FastStatueOfTruePerfection, setValue: value => context.Config.FastStatueOfTruePerfection = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(105), value: context.Config.FastTapper, setValue: value => context.Config.FastTapper = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(211), value: context.Config.FastWoodChipper, setValue: value => context.Config.FastWoodChipper = value ), new CheatsOptionsCheckbox( label: GameI18n.GetBigCraftableName(154), value: context.Config.FastWormBin, setValue: value => context.Config.FastWormBin = value ) )); }