RELEASED Content Patcher *

Loads content packs that change the game's images and data without replacing XNB files.

Thread Status:
Not open for further replies.
  1. coldazrael

    coldazrael Existential Complex

    Could you explain more of this 'certain way'? Or perhaps a sample mod of it?
     
    • Pathoschild

      Pathoschild Tiy's Beard

      @coldazrael Normally you can't intercept mod assets, except when a mod uses IAssetLoader to load an asset (which doesn't necessarily exist) from the game's content folder. In that case you can use "Action: EditImage" to change the image after it's loaded. For example, the tractor sprite is loaded directly from the mod folder (with asset key SMAPI/pathoschild.tractormod/tractor.png), and can't be changed using Content Patcher. The garage sprite is loaded by the game (with asset key Buildings/TractorGarage), so you can change that using Content Patcher.

      That depends on implementation details in the way SMAPI's content pipeline works, and isn't guaranteed to work in future versions. I'm considering adding an explicit feature to support this in a future version though.
       
      • coldazrael

        coldazrael Existential Complex

        @Pathoschild
        So if I were to make a CP conversion of a mod that replaces the garage, the target field is "Buildings/TractorGarage" ?
        To be frank I don't mean to doubt your answer. I used the mod yet I didn't see the TractorGarage.xnb in Content/Buildings folder, so how's that supposed to work? :unsure:

        And how about if the case were about a CP mod instead of SMAPI mod (which is the tractor mod is one of em). Let's say your own conversion here, and I wanted to replace the farmhouse with a CP mod that patches your conversion. For the present situation I do know it's not going to work since the target field is locked in content folder only. But perhaps in the future, could it be possible if you were give the access to the Mods folder as well?
         
        • Pathoschild

          Pathoschild Tiy's Beard

          @coldazrael
          • SMAPI changes how the game loads content, so a mod can say "when the game asks for Buildings/TractorGarage, use my file instead". That means the file doesn't even need to exist in the Content folder.
          • You can't change the internal file loaded by another content pack, but you can patch the same asset it does. In this case, you'd just use Action: EditImage to apply your own patch to the farmhouse after Hobbit Hole does.
          • SMAPI and Content Patcher deliberately don't allow changing another mod's internal assets, since that would make mods more fragile and harder to troubleshoot. Instead you can apply your own patch on top of theirs. There's a possible future feature that would let you provide the asset file for another mod, but only for assets that mod explicitly allows.
           
          • coldazrael

            coldazrael Existential Complex

            Bold : Well this good, I always thought content patcher always replaces the files that only exists in content folder, thanks alot for this :D

            I ran a test for the hobbit hole to patch the farmhouse while there is another mod that changes the farmhouse as well.. and yeah it works. But there is another case for a two conflicting mods, Recolors to match Eemie's Collor Pallet by Allayna ( https://www.nexusmods.com/stardewvalley/mods/1554 ) and the CP version of Eemie's Map Recolor by minervamaga ( https://www.nexusmods.com/stardewvalley/mods/2050 ). The expected change is the whole shipping bin, and yet this happens ( https://prnt.sc/h8xzlu ), probably just on me but I don't know if anyone had the same problem. I did a random guess by adding a dependency field and putting the CP version of Eemie's Map Recolor UniqueID in the manifest file of Allayna's Recolor, oddly it works. This opens up another questions :
            -What sort of criteria that makes a certain CP mod could replace another sprite while there is another CP mod(s) that patches the same sprite?
            -As for the case above, did I really do the right thing to fix the problem? (It might be wrong to ask you but it seems the author of both mods seems to be busy, really busy that can't even respond the question, so I have no choice but to ask the author of the CP itself)

            This explicitly allows thing, perhaps a SMAPI mod 'explicitly allowed assets' can be determined like the tractor mod but what about CP mod that only replaces a cow sprite for example? If the feature is possible though, in what version that the feature is going to be implemented, is it the upcoming one?
             
              Last edited: Aug 31, 2018
            • Pathoschild

              Pathoschild Tiy's Beard

              @coldazrael You can always edit the game's assets (everything in Content), no matter which other mods edit them. If you need one content pack to apply after another one, dependencies is the correct way to do it. See how multiple patches interact in the readme for more info.
               
              • coldazrael

                coldazrael Existential Complex

                Well I guess this wrap the things up, sorry if I wasted a lot of your time by asking a question that's already had an obvious answer. o_O
                 
                • igoutta

                  igoutta Void-Bound Voyager

                  Hi, how is it the progress with conditional maps, I trully want to use that feature to make the the Mountain map escalable. I felt offf when I saw I cannot use hasflag with the load action cause I wanna use to make the map change after the guild acceptance.
                   
                  • Pathoschild

                    Pathoschild Tiy's Beard

                    @igoutta Unfortunately not yet. I'm mainly focusing on SMAPI and helping update mods to Stardew Valley 1.3 currently, and there are some other Content Patcher improvements I want to focus on first.
                     
                    • Pathoschild

                      Pathoschild Tiy's Beard

                      Notice for Content Patcher modders:
                      Content Patcher 1.5 will make important changes to give you more flexibility, but there's a tradeoff.
                      • Bad: Content Patcher will no longer warn you ahead of time about potential issues like FromFile matching a file that doesn't exist, or two Action: Load patches conflicting. Instead you'll only see an error when the patch is applied (and the conflict occurs or missing file is noticed).
                      • Good: most restrictions on the use of conditions and tokens will be lifted. For example, any single-value token will be usable in fields like FromFile and Target (even if the values aren't predetermined), you'll be able to use any conditions with Action: Load patches, and the upcoming custom tokens will be usable in those fields too. This also simplifies a number of other improvements I have planned, like allowing multiple Target values.
                      This will make content packs much more flexible, but also make testing more difficult since it won't detect potential issues for you in advance. Are there any objections to that tradeoff?

                      (Note: the actual format isn't changing, and forward compatibility for all existing content packs is guaranteed.)
                       
                        hatmouse and Tanpoponoko like this.
                      • coldazrael

                        coldazrael Existential Complex

                        I'd like to hear these new upcoming custom tokens :)
                        Could you please elaborate them?
                         
                        • Pathoschild

                          Pathoschild Tiy's Beard

                          @coldazrael That's a feature proposed for Content Patcher 1.5 that lets you create your own dynamic tokens. For example, you could create a {{SpriteVariant}} token whose value depends on the season and weather:
                          Code:
                          "CustomTokens": [
                              {
                                  "Name": "SpriteVariant",
                                  "Value": "default"
                              },
                              {
                                  "Name": "SpriteVariant",
                                  "Value": "Spring_Rainy",
                                  "When": {
                                      "Season": "spring, summer",
                                      "Weather": "rain, storm"
                                  }
                              },
                              {
                                  "Name": "SpriteVariant",
                                  "Value": "{{season}}_Indoor",
                                  "When": {
                                      "Season": "spring, summer",
                                      "Weather": "sun, snow"
                                  }
                              }
                          ]
                          
                          Then instead of many repeated patches for every NPC like this:
                          Code:
                          {
                              "LogName": "Emily Spring/Summer - Rain",
                              "Action": "Load",
                              "Target": "Characters/Emily",
                              "FromFile": "Characters/Emily/Emily_Spring_Rain.png",
                              "When": {
                                  "Season": "spring, summer",
                                  "Weather": "rain, storm"
                              }
                          },
                          {
                              "LogName": "Emily Spring/Summer - Indoor",
                              "Action": "Load",
                              "Target": "Characters/Emily",
                              "FromFile": "Characters/Emily/Emily_{{season}}_Indoor.png",
                              "When": {
                                  "Season": "spring, summer",
                                  "Weather": "sun, snow"
                              }
                          },
                          ...
                          
                          You could do this instead:
                          Code:
                          {
                              "LogName": "Emily Sprite",
                              "Action": "Load",
                              "Target": "Characters/Emily",
                              "FromFile": "Characters/Emily/Emily_{{SpriteVariant}}.png"
                          }
                          
                          Note that custom tokens are only proposed. There's no guarantee they'll be implemented, or that they'll work exactly as shown here.
                           
                            igoutta likes this.
                          • igoutta

                            igoutta Void-Bound Voyager

                            I'm newby, looks good the new way, but I prefer the safer path, even when I know that restrict me for my plans.
                             
                            • igoutta

                              igoutta Void-Bound Voyager

                              Hello again.
                              I have a question now, what it's the point of the atribute "AllowMultiple" if almost no one can use it.
                              I don't even know where it's valuable to use.
                              This can be silly or could be an idea that was discarded long time ago, but instead of having multiples options to enable each sprite from a long list of them, can a list load or edit multiples files of the same adress. I know it sound close to custom tokens, but it's not the same as well.

                              Better I show an example:
                              Code:
                              "ConfigSchema": {
                                "Active": {
                                  "AllowValues": "Blue Chicken, Brown Chicken, Void Chicken, White Chicken, Duck, Brown Cow, White Cow, Pig",
                                  "AllowMultiple" : "True",
                                  "AllowBlank": "True"
                                },
                              },
                              "Changes": [
                                {
                                  "Action": "EditImage",
                                  "Target": "Animals/{{Active}}",
                                  "FromFile": "assets/{{Active}}.png"
                                },
                              ]
                              The condition to use "AllowMultiple" must be have the exact same token as much as in Target as in FromFile, and of course, obviously check if all the files exist.
                              Pd: Teorically, this could make crazy options alongside custom tokens.
                               
                                Last edited: Sep 8, 2018
                              • Pathoschild

                                Pathoschild Tiy's Beard

                                @igoutta I think implicitly using tokens as foreach logic would be confusing. If I add foreach support in the future, it'd probably be a more explicit option.

                                Options with 'allow multiple' are meant for conditions like this:
                                Code:
                                "ConfigSchema": {
                                   "PatchVillagers": "Abigail, Emily, Pierre",
                                   "AllowMultiple" : "True"
                                },
                                "Changes": [
                                   {
                                      "Action": "EditImage",
                                      "Target": "Characters/Abigail",
                                      "FromFile": "assets/abigail.png",
                                      "When": {
                                         "PatchVillagers": "Abigail" // PatchVillagers includes Abigail
                                      }
                                   }
                                ]
                                
                                In future versions of Content Patcher, you may also be able to do this:
                                Code:
                                "ConfigSchema": {
                                   "PatchSeasons": "spring, summer, fall",
                                   "AllowMultiple" : "True"
                                },
                                "Changes": [
                                   {
                                      "Action": "EditImage",
                                      "Target": "Characters/Abigail",
                                      "FromFile": "assets/abigail_{{season}}.png",
                                      "When": {
                                         "Season": "{{PatchSeasons}}" // season is any of the PatchSeasons values
                                      }
                                   }
                                ]
                                
                                 
                                • coldazrael

                                  coldazrael Existential Complex

                                  Hey there, so I received some reports from paradigmnomad that the old tokens became unusable in 1.5. And for example, like if I wanted to change the colour of melon sprite :
                                  Code:
                                  "ConfigSchema": {
                                     "Melon": {
                                        "AllowValues" : "Red, Blue, Green, None",
                                        "Default" : "Red"
                                     },
                                  },
                                  "Changes": [
                                     {
                                        "Action": "EditImage",
                                        "Target": "Maps/springobjects",
                                        "FromFile": "assets/{{Melon}}.png", // This is what I mean about old token, it becomes invalid in 1.5
                                        "When": {
                                           "Melon": "Red, Blue, Green"
                                        },
                                     },
                                  ]
                                  
                                  And it must be fixed with defining the whole dynamic tokens.. sorta like this to get the mod working :
                                  Code:
                                  "DynamicTokens": [
                                     {
                                        "Name": "Colour",
                                        "Value": "Red",
                                        "When": {
                                           "Melon": "Red"
                                        },
                                     },
                                     {
                                        "Name": "Colour",
                                        "Value": "Blue",
                                        "When": {
                                           "Melon": "Blue"
                                        },
                                     },
                                     {
                                        "Name": "Colour",
                                        "Value": "Green",
                                        "When": {
                                            "Melon": "Green"
                                        },
                                     },
                                  ],
                                  "ConfigSchema": {
                                     "Melon": {
                                        "AllowValues" : "Red, Blue, Green, None",
                                        "Default" : "Red"
                                     },
                                  },
                                  "Changes": [
                                     {
                                        "Action": "EditImage",
                                        "Target": "Maps/springobjects",
                                        "FromFile": "assets/{{Colour}}.png", // Changed with Dynamic Token to get the mod working
                                        "When": {
                                           "Melon": "Red, Blue, Green"
                                        },
                                     },
                                  ]
                                  
                                  So the question, could it be possible make the old tokens working alongside with the dynamic tokens?
                                   
                                  • Pathoschild

                                    Pathoschild Tiy's Beard

                                    @coldazrael Content Patcher 1.5 is backwards compatible and all previous content packs should work fine. You definitely don't need to use dynamic tokens that way. Content Patcher 1.5 is still in early beta testing, so it's possible ParadigmNomad was referring to a bug in the beta; I'll follow up with them to make sure it's fixed before release.
                                     
                                    • coldazrael

                                      coldazrael Existential Complex

                                      Thank god, I was worried about the mods from migration thread will be unusable :rofl:
                                      And thanks for the information :DD
                                       
                                      • Pathoschild

                                        Pathoschild Tiy's Beard

                                        Content Patcher 1.5 is now available! (For Stardew Valley 1.3.29 beta only.)

                                        Release notes:
                                        • Added support for dynamic tokens defined by the modder.
                                        • Added new tokens:
                                          • FarmCave (the current farm cave type);
                                          • FarmhouseLevel (the upgrade level for the main farmhouse);
                                          • FarmName (the farm name);
                                          • FarmType (the farm type like Standard or Wilderness);
                                          • HasFile (whether a given file path exists in the content pack);
                                          • HasProfession (whether the player has a given profession);
                                          • PlayerGender (the player's gender);
                                          • PlayerName (the player's name);
                                          • PreferredPet (whether the player is a cat or dog person);
                                          • Year (the year number).
                                        • Added subkey form for all tokens, which can be used to enable AND logic and condition negation (see readme).
                                        • Added: you can now use any condition with Action: Load patches.
                                        • Added: you can now use tokens in EditData entries and fields.
                                        • Added: you can now list multiple values in the Target field.
                                        • Added config tokens to patch summary.
                                        • Added warning when a config field has AllowValues but a patch checks for an unlisted value.
                                        • Removed some early warnings for issues like patch conflicts. That validation required a number of restrictions on how conditions and tokens could be used. Based on discussion with content pack modders, lifting those restrictions was more valuable than the early validation.
                                        • Removed image preloading, which is no longer needed with SMAPI 2.8+.
                                        • Fixed patch summary showing tokens that aren't valid in the current context.
                                         
                                          igoutta, hatmouse, coldazrael and 3 others like this.
                                        • MasterYoba

                                          MasterYoba Void-Bound Voyager

                                          Hi I've returned to Stardew and modding now seems more complex. How do I install content patcher? I downloaded and unzipped it in my SDV folder - along with SMAPI. I put a seasonal outfits in the mod folder to test - and SMAPI knows it's there but tells me it can't load due to my lack of content patcher. Help?
                                           
                                          Thread Status:
                                          Not open for further replies.

                                          Share This Page