Modding Discussion Standardising content packs

Discussion in 'Mods' started by Pathoschild, Jan 17, 2018.

  1. Pathoschild

    Pathoschild Master Astronaut

    Here's a proposed standard for mod content packs; feedback welcome!

    Background:

    Several mods read content packs to extend the game (not related to mod packs). This is a way for modders to change the game without needing to write their own SMAPI mod or worry about the implementation. For example:
    In all three cases, the latter is just a collection of files that the actual mod can read (i.e. content pack), not a mod in itself.

    The problem:
    • Players often mistakenly install content packs as mods. SMAPI shows a 'no manifest.json' error, which is confusing.
    • Mod managers can't automatically know whether something is a content pack, or which mod it's for.
    • Mod managers need to support content packs for each mod individually. For example, Json Assets and Seasonal Immersion don't have mods in the same directory structure. This also means that when a new mod supports content packs, players can't use mod managers to install them.
    Proposed solution:
    All content packs would have a manifest.json file with the basic mod fields plus a ContentPack field:
    Code:
    {
       "Name": "Eemie's Bees",
       "Author": "Eemie",
       "Version": "1.0.0",
       "UniqueID": "Eemie.Bees",
       "UpdateKeys": [ "Nexus:1259" ],
       "ContentPack": {
          "ForModID": "spacechase0.CustomCritters",
          "Subfolder": "Critters/Eemie.Bees"
       }
    }
    
    Benefits:
    • Mod managers would know (a) this is a content pack for the Custom Critters mod, and (b) to unzip it into that mod's Critters subfolder. They could also use SMAPI's web API to get a download link for the mod it needs.
    • SMAPI would know it's a content pack, so it can show a more helpful error if it's installed as a mod (like "Fantasy Crops is a content pack for the Json Assets mod. See the mod's instructions for install steps.").
    • The parent mod could potentially use a SMAPI API to fetch available content packs and let SMAPI handle the edge cases:
      Code:
      IContentPack[] contentPacks = helper.Mod.GetContentPacks("Critters");
      
     
      Digus likes this.
    • Pathoschild

      Pathoschild Master Astronaut

    • Entoarox

      Entoarox Oxygen Tank

      I vote in favor of a standardised format at least insofar as a way for SMAPI & ModManager related information.

      But I also feel that a CP manifest should also be able to be convertable to a custom type easily, so that custom properties can type-safely exist for them.
       
      • Pathoschild

        Pathoschild Master Astronaut

        @Entoarox Longer term, we can add SMAPI APIs to encapsulate reading content packs that avoids needing to do that. For example:
        Code:
        IContentPack[] contentPacks = helper.Mod.GetContentPacks("Critters");
        foreach (IContentPack pack in contentPacks)
        {
            CritterData data = pack.ReadJsonFile<CritterData>("critter.json");
            Texture2D texture = pack.LoadContent<Texture2D>("critter.png");
        }
        
        The first step is to standardise content packs, but there are a lot of things we can do once that's done.
         
        • Entoarox

          Entoarox Oxygen Tank

          I like that idea, having a SMAPI provided mechanic for handling all this intuitively would be very much wanted! :D
           
          • Digus

            Digus Existential Complex

            What about a regular mod that want also have some content pack?
            Would it need to be two separate things?
            Since you are making SMAPI handle the content pack, couldn't it be done so any regular SMAPI mod could say which directory has content to each mod?
            This way people could make a custom tool that procure some items, but load this new items using Json Assets, all in one release.
             
            • Pathoschild

              Pathoschild Master Astronaut

              @Digus This would support any mod that accepts content packs. One mod can't directly add content packs for another mod (which would cause load order issues), but a mod is free to create an mod-provided API for other mods to use.
               
              • Digus

                Digus Existential Complex

                I think now I understood what you are proposing. I thought it was the other way around.
                I like the idea of parent mods loading content using SMAPI.
                What I was trying to ask, is with it would be possible for a mod to declare content packs and still function as a regular mod.
                It would not work if the parent mod does not load it thought SMAPI, but if it did, we could declare which subfolder has the content pack to be loaded. We could even declare more than one parent mod for different folders.
                 
                • Pathoschild

                  Pathoschild Master Astronaut

                  Yep: any mod could read content packs from specified subfolders, and it'd still be a regular mod. Content packs must be loaded from the mod's folder though (e.g. Custom Critters can read them from subfolders in Mods/CustomCritters).
                   
                  • Pathoschild

                    Pathoschild Master Astronaut

                    One issue is that SMAPI mods are dropped directly into Mods, but content packs work differently. So players often install content packs incorrectly and that'll be a perpetual source of confusion.

                    Since we've already agreed to standardise a manifest.json (with the EntryDLL field replaced with a ContentPack field), what if players could drop them directly into Mods and SMAPI would pick them up? Mods could call helper.Mod.GetContentPacks() to get all the content packs added for them, and SMAPI would show a friendly error if you install a content pack for a mod that's not installed.
                     
                    • Digus

                      Digus Existential Complex

                      That was more like what I was thinking. This way I could make a mod zip with 2 folders, one for my mod and the other one with a content pack data for a dependency. This way I could release all in one file without any other action required from the user.

                      Later, if possible, there could be a way to register both a mod and content packs for other mods using the same manifest. Since SMAPI would be loading the content pack, it shouldn't matter if its from its own folder or inside a mod. That was what I thought of proposing.
                       
                      • Pathoschild

                        Pathoschild Master Astronaut

                        Planned as SMAPI ticket #436; feel free to comment there if you want to suggest any changes before implementation. Otherwise this will be added in an upcoming SMAPI release. :)
                         

                        Share This Page