Example #1
0
        /// <summary>
        /// Stops the upgrade objects from being placable on the ground.
        /// </summary>
        /// <param name="__instance"></param>
        /// <returns></returns>
        public static void isPlaceable_Postfix(SObject __instance, ref bool __result)
        {
            MPMSettings upgradeSettings = ModEntry.GetSettingsFromItem(__instance.name);

            if (upgradeSettings != null)
            {
                __result = false;
            }
        }
Example #2
0
        /// <summary>
        /// Sets up the mod.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void OnSaveLoaded(object sender, SaveLoadedEventArgs args)
        {
            //Clear out old data if any exists
            MPMSettings.Clear();
            MPMDefinitionSet.Clear();
            if (MPMManager != null)
            {
                MPMManager.Clear();
            }

            //Load content packs
            Monitor.Log("Loading content packs...", LogLevel.Info);
            string filepath = "upgrades.json";

            foreach (IContentPack contentPack in Helper.ContentPacks.GetOwned())
            {
                if (contentPack.HasFile(filepath))
                {
                    List <MPMSettings> loaded = contentPack.ReadJsonFile <List <MPMSettings> >(filepath);

                    foreach (MPMSettings setting in loaded)
                    {
                        if (MPMSettings.ContainsKey(setting.Key))
                        {
                            Monitor.Log($"Content pack {contentPack.Manifest.Name} {contentPack.Manifest.Version} tried to add upgrade settings for existing key '{setting.Key}'! " +
                                        "Settings left unchanged.", LogLevel.Warn);
                        }
                        else
                        {
                            MPMSettings.Add(setting.Key, setting);
                        }
                    }

                    Monitor.Log($"Loaded content pack {contentPack.Manifest.Name} {contentPack.Manifest.Version} by {contentPack.Manifest.Author}.",
                                LogLevel.Info);
                }
                else
                {
                    Monitor.Log($"Failed reading content pack {contentPack.Manifest.Name} {contentPack.Manifest.Version}: missing file {filepath}.", LogLevel.Warn);
                }
            }

            //Create mail to send recipes
            MailManager.SetupMail();

            //Set up machines to work with PFM
            Monitor.Log("Defining machines...", LogLevel.Info);
            MPMDefinitionSet = MassProductionMachineDefinition.Setup(MPMSettings);
            SeedMakerOverride.Initialize();

            //Start manager, loading saved data
            MPMManager = new MPMManager();

            Helper.Events.GameLoop.Saving += OnSave;
        }
Example #3
0
        /// <summary>
        /// Makes the machine produce an appropriate output.
        /// Adapted from https://github.com/Digus/StardewValleyMods/blob/master/ProducerFrameworkMod/OutputConfigController.cs
        /// </summary>
        /// <param name="producerRule"></param>
        /// <param name="settings"></param>
        /// <param name="producer"></param>
        /// <param name="fuelSearch"></param>
        /// <param name="who"></param>
        /// <param name="location"></param>
        /// <param name="producerConfig"></param>
        /// <param name="input"></param>
        /// <param name="probe"></param>
        /// <param name="noSoundAndAnimation"></param>
        /// <returns>Base output config - no values altered for mass production machine</returns>
        public static OutputConfig ProduceOutput(ProducerRule producerRule, MPMSettings settings, SObject producer, Func <int, int, bool> fuelSearch, Farmer who, GameLocation location,
                                                 ProducerConfig producerConfig = null, SObject input = null, int inputQuantity = 0, bool probe = false, bool noSoundAndAnimation = false,
                                                 List <InputInfo> inputInfo    = null)
        {
            if (who == null)
            {
                who = Game1.getFarmer((long)producer.owner);
            }

            if (inputInfo == null)
            {
                inputInfo = new List <InputInfo>();
            }

            Vector2      tileLocation = producer.TileLocation;
            Random       random       = ProducerRuleController.GetRandomForProducing(tileLocation);
            OutputConfig outputConfig = OutputConfigController.ChooseOutput(producerRule.OutputConfigs, random, fuelSearch, location, input);

            if (outputConfig != null)
            {
                SObject output = producerRule.LookForInputWhenReady == null?OutputConfigController.CreateOutput(outputConfig, input, random) : new SObject(outputConfig.OutputIndex, 1);

                output.Stack = settings.CalculateOutputProduced(output.Stack, inputInfo.ToArray());

                if (settings.Quality.HasValue)
                {
                    if (settings.Quality == QualitySetting.KeepInput)
                    {
                        output.Quality = input.Quality;
                    }
                    else
                    {
                        output.Quality = settings.GetOutputQuality();
                    }
                }

                producer.heldObject.Value = output;

                if (!probe)
                {
                    if (producerRule.LookForInputWhenReady == null)
                    {
                        OutputConfigController.LoadOutputName(outputConfig, producer.heldObject.Value, input, who);
                    }

                    //if (!noSoundAndAnimation)
                    //{
                    //    SoundUtil.PlaySound(producerRule.Sounds, location);
                    //    SoundUtil.PlayDelayedSound(producerRule.DelayedSounds, location);
                    //}

                    int minutesUntilReadyBase = outputConfig.MinutesUntilReady ?? producerRule.MinutesUntilReady;
                    int minutesUntilReady     = settings.CalculateTimeRequired(minutesUntilReadyBase, inputInfo.ToArray());

                    producer.minutesUntilReady.Value = minutesUntilReady;
                    if (producerRule.SubtractTimeOfDay)
                    {
                        producer.minutesUntilReady.Value = Math.Max(producer.minutesUntilReady.Value - Game1.timeOfDay, 1);
                    }

                    if (producerConfig != null)
                    {
                        producer.showNextIndex.Value = producerConfig.AlternateFrameProducing;
                    }

                    //if (producerRule.PlacingAnimation.HasValue && !noSoundAndAnimation)
                    //{
                    //    AnimationController.DisplayAnimation(producerRule.PlacingAnimation.Value,
                    //        producerRule.PlacingAnimationColor, location, tileLocation,
                    //        new Vector2(producerRule.PlacingAnimationOffsetX, producerRule.PlacingAnimationOffsetY));
                    //}

                    if (location.hasLightSource(LightSourceConfigController.GenerateIdentifier(tileLocation)))
                    {
                        location.removeLightSource(LightSourceConfigController.GenerateIdentifier(tileLocation));
                    }
                    producer.initializeLightSource(tileLocation, false);

                    int statsIncrement = inputQuantity;
                    producerRule.IncrementStatsOnInput.ForEach(s => StatsController.IncrementStardewStats(s, statsIncrement));
                }
            }
            return(outputConfig);
        }
Example #4
0
        /// <summary>
        /// Check if the input and fuels are of the required quantities for the producer rule and machine settings.
        /// Adapted from https://github.com/Digus/StardewValleyMods/blob/master/ProducerFrameworkMod/ProducerRuleController.cs
        /// </summary>
        /// <param name="producerRule">the producer rule to check.</param>
        /// <param name="settings">Mass production machine settings to check.</param>
        /// <param name="inputs">The inputs to check.</param>
        /// <param name="who">The farmer placing an item in the machine.</param>
        public static void ValidateIfInputsLessThanRequired(ProducerRule producerRule, MPMSettings settings, List <InputInfo> inputs, Farmer who)
        {
            foreach (InputInfo input in inputs)
            {
                int quantityRequired = settings.CalculateInputRequired(input);

                if ((!input.IsFuel && who.ActiveObject.Stack < quantityRequired) ||
                    (input.IsFuel && !who.hasItemInInventory(input.ID, quantityRequired)))
                {
                    throw new RestrictionException(string.Format("{1}x{0} required", quantityRequired, input.Name));
                }
            }
        }
Example #5
0
        [HarmonyPriority(801)] //Just before ProducerFrameworkMod. Can't use HarmonyBefore attribute, that wasn't working for some reason
        internal static bool PerformObjectDropInAction(SObject __instance, Item dropInItem, bool probe, Farmer who, ref bool __result)
        {
            if (__instance.isTemporarilyInvisible || !(dropInItem is SObject))
            {
                return(false);
            }

            SObject input = dropInItem as SObject;
            bool    failLocationCondition = false;
            bool    failSeasonCondition   = false;

            MPMSettings upgradeSettings = ModEntry.GetSettingsFromItem(input.name);

            if (upgradeSettings != null)
            {
                if (!probe)
                {
                    //Change the machine's mass producer settings
                    MassProductionMachineDefinition mpm = ModEntry.GetMPMMachine(__instance.name, upgradeSettings.Key);

                    if (mpm == null)
                    {
                        Game1.showRedMessage("This cannot take that upgrade.");
                    }
                    else
                    {
                        string oldProducerKey = __instance.GetMassProducerKey();

                        if (!string.IsNullOrEmpty(oldProducerKey))
                        {
                            string         upgradeItemName = ModEntry.MPMSettings[oldProducerKey].UpgradeObject;
                            JsonAssets.Api jsonAssets      = ModEntry.Instance.Helper.ModRegistry.GetApi("spacechase0.JsonAssets") as JsonAssets.Api;
                            int            upgradeItemId   = jsonAssets.GetObjectId(upgradeItemName);

                            Game1.createItemDebris(new SObject(upgradeItemId, 1), __instance.TileLocation * Game1.tileSize, 0, who.currentLocation);
                        }

                        __instance.SetMassProducerKey(upgradeSettings.Key);
                        input.Stack -= 1;
                        __result     = input.Stack <= 0;

                        return(false);
                    }
                }
            }
            else
            {
                //Check if this is a valid input for the machine's use
                if (string.IsNullOrEmpty(__instance.GetMassProducerKey()))
                {
                    return(true);
                }

                if (__instance.heldObject.Value != null && !__instance.name.Equals("Crystalarium") || input.bigCraftable.Value)
                {
                    return(true);
                }

                MassProductionMachineDefinition mpm = ModEntry.GetMPMMachine(__instance.name, __instance.GetMassProducerKey());

                if (mpm == null)
                {
                    return(true);
                }

                if (StaticValues.SUPPORTED_VANILLA_MACHINES.ContainsKey(__instance.name))
                {
                    IVanillaOverride vanillaOverride = VanillaOverrideList.GetFor(__instance.name);

                    if (vanillaOverride != null)
                    {
                        bool overrideResult = vanillaOverride.Manual_PerformObjectDropInAction(__instance, input, probe, who, mpm);

                        //End early if a result has been found
                        if (overrideResult)
                        {
                            __result = input.Stack <= 0;
                            return(true);
                        }
                    }
                }

                ProducerConfig baseConfig = mpm.GetBaseProducerConfig();
                GameLocation   location   = who.currentLocation;

                if (baseConfig != null)
                {
                    //TOREVIEW: maybe have machines that can break these conditions?
                    if (!baseConfig.CheckLocationCondition(location))
                    {
                        failLocationCondition = true;
                    }
                    if (!baseConfig.CheckSeasonCondition())
                    {
                        failSeasonCondition = true;
                    }
                    if (baseConfig.NoInputStartMode != null)
                    {
                        return(true);
                    }
                }

                if (ProducerController.GetProducerItem(__instance.name, input) is ProducerRule producerRule)
                {
                    if (PFMCompatability.IsInputExcluded(producerRule, mpm, input))
                    {
                        return(true);
                    }

                    if (__instance.bigCraftable.Value && !probe && __instance.heldObject.Value == null)
                    {
                        __instance.scale.X = 5f;
                    }

                    try
                    {
                        if (failLocationCondition)
                        {
                            throw new RestrictionException("Machine can't be used in this location.");
                        }
                        if (failSeasonCondition)
                        {
                            throw new RestrictionException("Machine can't be used in this season.");
                        }

                        List <InputInfo> inputAndFuelInfo = InputInfo.ConvertPFMInputs(producerRule, input);
                        PFMCompatability.ValidateIfInputsLessThanRequired(producerRule, mpm.Settings, inputAndFuelInfo, who);

                        Dictionary <int, int> fuelQuantities = new Dictionary <int, int>();

                        foreach (InputInfo inputInfo in inputAndFuelInfo)
                        {
                            if (inputInfo.IsFuel)
                            {
                                fuelQuantities.Add(inputInfo.ID, mpm.Settings.CalculateInputRequired(inputInfo));
                            }
                        }

                        Func <int, int, bool> fuelSearch   = (i, q) => who.hasItemInInventory(i, fuelQuantities[i]);
                        OutputConfig          outputConfig = PFMCompatability.ProduceOutput(producerRule, mpm.Settings, __instance,
                                                                                            fuelSearch, who, location, baseConfig, input, mpm.Settings.CalculateInputRequired(inputAndFuelInfo.First()), probe,
                                                                                            inputInfo: inputAndFuelInfo);

                        if (outputConfig != null)
                        {
                            if (!probe)
                            {
                                foreach (InputInfo inputInfo in inputAndFuelInfo)
                                {
                                    if (inputInfo.IsFuel)
                                    {
                                        RemoveItemsFromInventory(who, inputInfo.ID, mpm.Settings.CalculateInputRequired(inputInfo));
                                    }
                                }

                                List <InputInfo> outputConfigFuels = InputInfo.ConvertPFMInputs(outputConfig);

                                foreach (InputInfo fuel in outputConfigFuels)
                                {
                                    RemoveItemsFromInventory(who, fuel.ID, mpm.Settings.CalculateInputRequired(fuel));
                                }

                                input.Stack -= mpm.Settings.CalculateInputRequired(inputAndFuelInfo.First());
                                __result     = input.Stack <= 0;
                            }
                            else
                            {
                                __result = true;
                            }
                        }
                    }
                    catch (RestrictionException e)
                    {
                        __result = false;
                        if (e.Message != null && !probe && who.IsLocalPlayer)
                        {
                            Game1.showRedMessage(e.Message);
                        }
                    }
                    return(false);
                }
            }

            return(!failLocationCondition && !failSeasonCondition);
        }
Example #6
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="baseProducerName">Name of the base production machine as used by PFM or the base game.</param>
 /// <param name="settings">How the machine affects inputs and outputs.</param>
 protected MassProductionMachineDefinition(string baseProducerName, MPMSettings settings)
 {
     BaseProducerName     = baseProducerName;
     Settings             = settings;
     BlacklistedInputKeys = new List <object>();
 }