Jump to content

[1.12.x] PatchManager


Recommended Posts

PatchManager is a simple mod which will allow mod and patch authors to package various optional patches with their mods, or as stand-alone patch sets.

By creating a simple config file for each patch, PatchManager makes it possible to install and remove patches from inside the game.  Gone are the days where you would have to copy patches into the game.

An additional benefit is that all active patches are stored in a single location,  making it easy to save, package up and redistribute to your friends.

This mod will do nothing by itself.  It requires a mod to include patches in a specific format.

When the window is open, lines with text in red are patches which are not enabled, lines in green are patches which are enabled.

 

Note that the changes aren't done until until you click the "Apply All" button.

Mods which use this:

Pics:

Toolbar button:

rQLAog0.png

 

Main PatchManager window:

 

oGnJ54a.png

0enCVTF.png

5URR36P.png

 

 

 

Patch Manager Confirmation window:

Fu9jqbH.png

Settings screen:

kZhC6M3.png

===================================================================================
Instructions for Mod authors

I'll be referring to the KWRocketry Rebalanced mod, so if you have any questions, I suggest you first download that and look at it as a working example.


PatchManager looks for config nodes which have the following format:

    PatchManager
    {
        // Required settings.  
        // srcPath should use forward slashes, and include the full file name.  srcPath should be in a directory 
        // called ".../PatchManager/PluginData"
		modname = KW Rocketry
        patchName = GraduatedPowerResponse
        srcPath = KWRocketry/PatchManager/PluginData/GraduatedPowerResponse.cfg
        shortDescr = Graduated Power Response

        // Optional, but recommended
        longDescr = Makes the engines take time to spool up and down


        //// Optional entries here

        // dependencies, only show this patch if these specified mods are available
        // List either the directory of the mod (as show by ModuleManager), or the 
        // mod DLL (as show by ModuleManager)
        //dependencies = 

		// exclusions, this patch is exclusive with these, in other words, don't install this
		// if a patch listed in the exclusion is installed
		// exclusions = 

        // Path to icon, if desired.  Can be a flag, but will be shrunken down to a 38x38 image
        icon = KWRocketry/Flags/KWFlag04

		// Is this patch active on mod installation?  If this is true, then this
		// is describing a patch which is initially active.
		installedWithMod = false

        // Author's name, if desired
        author = Linuxgurugamer 
    }


patchName            This is the name of the patch.  It should be short but descriptive
srcPath              Where the patch file is located, relative to the GameData directory.  
                     You MUST include the full file name as well.  The filename MUST match
                     the patchName

shortDescr           A short description of the patch.
longDescr            A longer description of the patch
dependencies         What mods this patch is dependent on.  If these aren't installed, 
                     the patch won't be shown.  This is a comma separated list of mods
exclusions           Specify a comma separated list of other patches which should prevent
                     this patch from being installed.  Note that this does not work in
                     reverse
installedWithMod     If true, then this mod is active when the mod is installed

icon                 An icon to show, if desired
Author               Author of the patch

The directory structure is intentionally rigid.  This is done to make sure that patches are found properly, that patches aren't accidently made active, etc.

PatchManager configs should be in a directory in the mod folder called PatchManager. The patches themselves should be in a directoryy called PluginData, inside the Patchmanager directory.  See the following tree diagram for an example of how it's set up in KW Rocketry Rebalanced.  Note that while I did use different names for the PatchManager file and the  actual patch file, and recommend that you do so, it isn't absolutely necessary:

    KWRocketry
       |
       |->Flags/
       |->KWCommunityFixes/
       |->Parts/
       |
       |->PatchManager/
       |       |
       |       |->PluginData/
       |       |      |
       |       |      |-_GraduatedPowerResponse.cfg                // This is the actual patch file
       |       |
       |       |->PM_GraduatedPowerResponse.cfg                    // This is the PatchManager file
       |
       |->SoundBank/
       |
       |->KWRocketryRedux.version
       |->MiniAVC.dll


Now, as I was developing this, I was working with another mod author, who had a lot of difficulty understanding what I was trying to explain.  The problem was we each were thinking of a "mod" in different manners.  So, to be clear, I'll define here what I'm referring to when I talk about a mod:

Mod Definition:

  •     KW is a mod, it has it's own set of patches
  •     CommunityPatches is a mod, it has it's own set of patches.
  •     JoesKWPatches is a  mod. it has it's own set of patches

Special Instructions regarding the "installedWithMod" option
============================================================
Some mods may wish to have patches which are installed and active when the mod is installed.
This requires special handling:

The patch goes into a different directory called ActiveMMPatches in the initial Patchmanager folder.   Internally, the operations are somewhat reversed.  Instead of the patch being copied to the main PatchManager directory, when deactivated the patch will be moved to the local PluginData directory, and back again if reactivated.  The "srcPath" should still point to the PluginData directory, even though the patch will be in the ActiveMMPatches directory.  In this case, "srcPath" is telling the mod where to move the patch to in order to disable it.  The name of the file will be obtained from this entry.

srcPath = KWRocketry/PatchManager/PluginData/GraduatedPowerResponse.cfg

Using the same diagram as earlier, the new directory layout is:

    KWRocketry
       |
       |->Flags/
       |->KWCommunityFixes/
       |->Parts/
       |
       \->PatchManager/
               |
               |->ActiveMMPatches/
               |      |
               |      |->InitialActivePatch.cfg                    // This is the actual patch file
               |
               |->PluginData/
               |      |
               |      |->GraduatedPowerResponse.cfg                // This is the actual patch file
               |
               |->PM_InitialActivePatch.cfg                        // This is the PatchManager file
               |->PM_GraduatedPowerResponse.cfg                    // This is the PatchManager file


        
Some final notes:

  • If there aren't any mod patches available to be installed, the toolbar button will not be displayed
  • You can disable the toolbar button in the standard game settings page.
  • There is an override which will force the toolbar button to be always shown, regardless of dependencies
  • If you install some patches, and then remove a dependency that one or more of those patches depend on, the patch WILL NOT be removed

Available

Source Code:  https://github.com/linuxgurugamer/PatchManager

Download:  https://github.com/linuxgurugamer/PatchManager/releases

License:  CC-BY-NC-SA-4.0

 

Edited by linuxgurugamer
Link to comment
Share on other sites

Liking the idea.  One thought, however:  Am I correct in thinking that in the absence of PatchManager all patches will default to 'Not Applied'?  If so, could there be consideration given to having a path setup that would allow the patch to default to 'Applied'?

 

I'm thinking I want to submit PR's to a couple of mods to support this system - but I don't want to change current functionality if possible, and the patches that interest me on it are 'default applied - remove to unapply' patches.

Link to comment
Share on other sites

5 hours ago, DStaal said:

Liking the idea.  One thought, however:  Am I correct in thinking that in the absence of PatchManager all patches will default to 'Not Applied'?  If so, could there be consideration given to having a path setup that would allow the patch to default to 'Applied'?

 

I'm thinking I want to submit PR's to a couple of mods to support this system - but I don't want to change current functionality if possible, and the patches that interest me on it are 'default applied - remove to unapply' patches.

I don't particularly like the idea, but can you give me a specific example, please?

Link to comment
Share on other sites

1 minute ago, linuxgurugamer said:

I don't particularly like the idea, but can you give me a specific example, please?

The two I was thinking of are:

NFE has a patch to integrate USI's reactors to NFE production mechanics.  I always remove the patch - I was going to suggest using this mod to help manage it.

MKS has a patch to integrate with EL - I was going to split it into two (one for the resources, one for the parts) and set them up as optional via this mod.

Another that immediately comes to mind is that WBI's Pathfinder has an integration patch with KPBS.  Again, it'd be nice to make it easier to make optional.  Or OPM's increase of the stock antenna's power.  I could probably go on for a while, as I think of them.  :wink:

In most of these if Patchmanager had existed since they were created I can see them as would likely to have been using it from the start - but Patchmanager didn't, and adding it as a dependency to make the mod work as it has in the past will be more likely to cause issues to users.

 

While I was typing this up, another thing occurred to me that might be nice (though is likely complicated...): The ability for patches to declare themselves mutually exclusive with another patch.  (My MKStoKPBS set is incompatible with Pathfinder's integration, for example.)  But I can see that getting really complicated to implement, and is definitely an edge case.  :wink:  The 'default active' I'd consider a more normal case - it means a mod can support this mod without requiring it.

Link to comment
Share on other sites

1 minute ago, DStaal said:

The two I was thinking of are:

NFE has a patch to integrate USI's reactors to NFE production mechanics.  I always remove the patch - I was going to suggest using this mod to help manage it.

MKS has a patch to integrate with EL - I was going to split it into two (one for the resources, one for the parts) and set them up as optional via this mod.

Another that immediately comes to mind is that WBI's Pathfinder has an integration patch with KPBS.  Again, it'd be nice to make it easier to make optional.  Or OPM's increase of the stock antenna's power.  I could probably go on for a while, as I think of them.  :wink:

In most of these if Patchmanager had existed since they were created I can see them as would likely to have been using it from the start - but Patchmanager didn't, and adding it as a dependency to make the mod work as it has in the past will be more likely to cause issues to users.

 

While I was typing this up, another thing occurred to me that might be nice (though is likely complicated...): The ability for patches to declare themselves mutually exclusive with another patch.  (My MKStoKPBS set is incompatible with Pathfinder's integration, for example.)  But I can see that getting really complicated to implement, and is definitely an edge case.  :wink:  The 'default active' I'd consider a more normal case - it means a mod can support this mod without requiring it.

Ok, there is already the ability to define a dependency, adding an exclusion wouldn't be too difficult. It would be referring to the Mod name + patch name, with all spaces replaced with underscores.

I need to think about patches which default to being installed

Link to comment
Share on other sites

26 minutes ago, linuxgurugamer said:

New release, 0.0.3:

  • Updated active file names to avoid name collisions
  • Added code to rename existing files, if any
  • Added ability to have exclusions of other patch files

Still thinking about patches which default to being installed

Nice.  Thanks.  :wink:

(Though I don't actually see a download for it on GitHub - there's source code bundles, but not a release bundle.)

Link to comment
Share on other sites

Just now, linuxgurugamer said:

Oops!

It's there now:

https://github.com/linuxgurugamer/PatchManager/releases/tag/0.0.3

 

Also, you are going to get your wish.  I've figured out how to do the patches which default to being installed.  It's a bit more difficult, so it may be a day or so before I get it out.

 

Yay!  Thanks.  :wink:

(Then I'll get on making PRs for mods to make some of these little things optional...)

Link to comment
Share on other sites

I just tried this out using the Steam release of KSP on Linux, and got exceptions in my log when trying to activate a patch:

[EXC 21:53:03.703] DirectoryNotFoundException: Destination directory not found: /home/wyzard/.steam/steam/SteamApps/common/Kerbal_Space_Program/KSP_Data/../GameData/PatchManager/ActiveMMPatches
	System.IO.File.Copy (System.String sourceFileName, System.String destFileName, Boolean overwrite)
	System.IO.File.Copy (System.String sourceFileName, System.String destFileName)
	PatchManager.PatchManagerClass.ApplyAllChanges ()
	PatchManager.PatchManagerClass.drawWindow (Int32 windowid)
	UnityEngine.GUILayout+LayoutedWindow.DoWindow (Int32 windowID)
	UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style)

The problem is that my KSP installation directory is named "Kerbal Space Program" (with spaces), not "Kerbal_Space_Program".  (The "KSP_Data" folder, however, does have the underscore.)  Other than that, the path is correct.

As an aside, I'm a bit concerned that the patch is being copied into the PatchManager directory — when I install a new version of a mod, I always delete the old version's folder first, to avoid leaving cruft if the new version has removed files that were in the old version.  (Many mods specifically recommend doing this.)  It looks like upgrading PatchManager will require some additional care to avoid deleting all the active patches.

Link to comment
Share on other sites

On 7/11/2017 at 10:04 PM, Wyzard said:

I just tried this out using the Steam release of KSP on Linux, and got exceptions in my log when trying to activate a patch:


[EXC 21:53:03.703] DirectoryNotFoundException: Destination directory not found: /home/wyzard/.steam/steam/SteamApps/common/Kerbal_Space_Program/KSP_Data/../GameData/PatchManager/ActiveMMPatches
	System.IO.File.Copy (System.String sourceFileName, System.String destFileName, Boolean overwrite)
	System.IO.File.Copy (System.String sourceFileName, System.String destFileName)
	PatchManager.PatchManagerClass.ApplyAllChanges ()
	PatchManager.PatchManagerClass.drawWindow (Int32 windowid)
	UnityEngine.GUILayout+LayoutedWindow.DoWindow (Int32 windowID)
	UnityEngine.GUI.CallWindowDelegate (UnityEngine.WindowFunction func, Int32 id, UnityEngine.GUISkin _skin, Int32 forceRect, Single width, Single height, UnityEngine.GUIStyle style)

The problem is that my KSP installation directory is named "Kerbal Space Program" (with spaces), not "Kerbal_Space_Program".  (The "KSP_Data" folder, however, does have the underscore.)  Other than that, the path is correct.

Thank you for the report, I'll work on fixing it.

On 7/11/2017 at 10:04 PM, Wyzard said:

As an aside, I'm a bit concerned that the patch is being copied into the PatchManager directory — when I install a new version of a mod, I always delete the old version's folder first, to avoid leaving cruft if the new version has removed files that were in the old version.  (Many mods specifically recommend doing this.)  It looks like upgrading PatchManager will require some additional care to avoid deleting all the active patches.

When upgrading PatchManager manually, you do NOT remove the old directory for this reason specifically.  PatchManager does not leave any old files, it's a single DLL and a .version file.  I'll update the instructions to emphasize this.

Link to comment
Share on other sites

@Wyzard After reflection, I believe that a use case can be made for both methods: Storing active patches in the PatchManager folder, and alternatively storing patches in the parent mod folder.

So I'm adding a configurable option to store patches in the parent mod folder.  

 

Link to comment
Share on other sites

I was thinking about the issue of where to copy the patches to, as well as the challenge of enabled-by-default patches that was discussed earlier, and it occurred to me that it might be useful to add patch enable/disable functionality into ModuleManager itself.  If ModuleManager could read a config file that tells it to ignore certain patches, or to process certain patches that'd otherwise be ignored (due to being in a PluginData folder), PatchManager could act as a front-end for editing that config file, and there'd be no need to copy patch files at all.

I know that'd be a big change in direction for this mod, and a bunch of work on a different mod to support it, so it's understandable if you'd rather not go in that direction.  But there are benefits in being able to enable/disable MM patches without having to copy them to different paths, so I'm suggesting it as a possible future enhancement.  In particular, if an upgraded version of a mod brings an upgraded version of a patch, a copy previously made by PatchManager will still be the old version, and some extra steps are needed to replace it with a copy of the new version.  If the patch is instead enabled in-place via MM config, the new version takes effect immediately.

Hypothetically, imagine PatchManager creating or editing a file like this:

ModuleManagerConfig
{
    // From ExampleMod/PatchManager/PM_DisabledByDefaultPatch.cfg
    use = ExampleMod/Patches/PluginData/DisabledByDefaultPatch.cfg

    // From ExampleMod/PatchManager/PM_EnabledByDefaultPatch.cfg
    ignore = ExampleMod/Patches/EnabledByDefaultPatch.cfg
}
Link to comment
Share on other sites

Not really a good idea.  MM works well, if you start changing it's functionality, you can cause major problem.  

Anyway, got it done, new release, 0.0.4:

  • Fixed bug where path to KSP directory has spaces
  • Changed first button on line where icon is show to non-functional field, removed button graphics
  • Added new option:  installedWithMod  for patches which need to be initially active
  • Added new settings option to allow active patches to be stored in the parent mod directory
  • Added code to move active patches to the correct directory at load time and if it is changed 
  • Replaced settings page with new setting window, because these options are global to all games, not specific saves
Link to comment
Share on other sites

Well, in principle it'd just be a small adjustment after MM has finished scanning for patch files, before it starts actually processing them.  Just add some more files to the set that's about to be processed, and remove some others.  I'm pretty sure filesystem scanning and patch application are already decoupled, since MM has to filter the patches based on :NEEDS conditions, and rearrange the list to satisfy :AFTER constraints.  This would just be an added step before that one.  (But I don't know how the MM code is structured, so I don't know whether it'd be easy to add or if it'd require a lot of refactoring.)

Actually, the existing MM preprocessing brings another idea to mind: optional patches can be controlled by a :NEEDS condition for a patch-specific name (e.g. :NEEDS[ExampleModRealismModeEnabled]), and to enable the patch, PM could just create a dummy .cfg with a corresponding :FOR clause which defines that name.  Default-enabled patches would use :NEEDS[!ExampleModRealismModeDisabled] instead.  This would avoid the need to hide patches in a PluginData folder and copy them out to activate them, and it doesn't require any changes to MM.  It also has the advantage that :NEEDS conditions can be applied to arbitrary things within a patch file, rather than being limited to enabling or disabling the entire file.

(And actually, the above can be accomplished already if the mod author ships the dummy :FOR patch to be enabled by PatchManager using the current copying mechanism.  But it'd be useful if PM could directly create the :FOR patch using a name defined in the PatchManager metadata file.)

Anyway, that's enough brainstorming from me for now.  :wink:  I'll try out v0.0.4 later tonight.

Link to comment
Share on other sites

21 minutes ago, Wyzard said:

Well, in principle it'd just be a small adjustment after MM has finished scanning for patch files, before it starts actually processing them.  Just add some more files to the set that's about to be processed, and remove some others.  I'm pretty sure filesystem scanning and patch application are already decoupled, since MM has to filter the patches based on :NEEDS conditions, and rearrange the list to satisfy :AFTER constraints.  This would just be an added step before that one.  (But I don't know how the MM code is structured, so I don't know whether it'd be easy to add or if it'd require a lot of refactoring.)

Actually, the existing MM preprocessing brings another idea to mind: optional patches can be controlled by a :NEEDS condition for a patch-specific name (e.g. :NEEDS[ExampleModRealismModeEnabled]), and to enable the patch, PM could just create a dummy .cfg with a corresponding :FOR clause which defines that name.  Default-enabled patches would use :NEEDS[!ExampleModRealismModeDisabled] instead.  This would avoid the need to hide patches in a PluginData folder and copy them out to activate them, and it doesn't require any changes to MM.  It also has the advantage that :NEEDS conditions can be applied to arbitrary things within a patch file, rather than being limited to enabling or disabling the entire file.

(And actually, the above can be accomplished already if the mod author ships the dummy :FOR patch to be enabled by PatchManager using the current copying mechanism.  But it'd be useful if PM could directly create the :FOR patch using a name defined in the PatchManager metadata file.)

Anyway, that's enough brainstorming from me for now.  :wink:  I'll try out v0.0.4 later tonight.

You're in the wrong thread - those would require changes to MM, and this is the PatchManager thread.  :wink:  (Well, the :FOR idea wouldn't, but I can see arguments either way.  I think the current way you can save KSP from actually trying to load things in the first place, and save some RAM therefore, but I'm not sure.)

Link to comment
Share on other sites

8 hours ago, DStaal said:

You're in the wrong thread - those would require changes to MM, and this is the PatchManager thread.  :wink:  (Well, the :FOR idea wouldn't, but I can see arguments either way.  I think the current way you can save KSP from actually trying to load things in the first place, and save some RAM therefore, but I'm not sure.)

Yeah, I thought about that.  I figured it'd be appropriate to suggest it here since PatchManager would be the main user of the feature, and linuxgurugamer might therefore might want to make the MM changes.  I may suggest it over in the MM thread as well, but actually I kinda like the :NEEDS/:FOR approach better — it's simpler to implement and provides more flexibility.

I'd expect that patch definitions can be garbage-collected after MM has applied its changes to the game's real configuration, so memory usage of disabled patches shouldn't be an issue.  They do still need to be parsed, but people probably aren't going to have large numbers of optional patches in their installation so I doubt that's a significant issue either.

Link to comment
Share on other sites

I tried out v0.0.4 and I'm able to install patches now, so it looks like the path issue I had earlier is fixed.  Thanks for the quick response!

A few observations:

  • The OP shows a screenshot of the settings in the Game Difficulty window, but they're actually in a separate window that's accessed via a button in the main PatchManager window.  I think it's better that way, though; PatchManager's settings aren't related to difficulty, and changing them shouldn't force the game's difficulty level to "custom".
  • The description above the "store active patches in the PatchManager folder" checkbox says that changing it won't move patches that are already installed, but the patches actually do move to the new location when I click OK to close the Settings window.
  • If I change a mod's original version of a patch (as can happen when upgrading a mod), the installed copy in ActiveMMPatches doesn't change, even if I open the PatchManager window and click the "Apply All" button.  Looks like the only way to activate the updated version of the patch is to disable the patch, apply all, then re-enable and apply all again.  It may be a good idea to make the "Apply All" button reinstall patches that are already active, to pick up any changes that may have been made to the original version.  (It'd also be helpful if PatchManager could notice the discrepancy and warn the user.)

Other than those issues, things are working well.  I'm hoping that PatchManager gains traction and becomes widely-used, because optional patches are something that aren't really well-handled in KSP right now.  (I can only think of a few mods that provide them, each in its own ad-hoc way.  I'd love to see that change.)

Link to comment
Share on other sites

2 hours ago, DStaal said:

BTW: It might be nice to be able to add stuff to the wiki on GitHub.  It doesn't seem to be enabled for this project.  :wink:

Wiki created, go for it

On 7/14/2017 at 10:40 PM, Wyzard said:

I tried out v0.0.4 and I'm able to install patches now, so it looks like the path issue I had earlier is fixed.  Thanks for the quick response!

A few observations:

  • The OP shows a screenshot of the settings in the Game Difficulty window, but they're actually in a separate window that's accessed via a button in the main PatchManager window.  I think it's better that way, though; PatchManager's settings aren't related to difficulty, and changing them shouldn't force the game's difficulty level to "custom".
  • The description above the "store active patches in the PatchManager folder" checkbox says that changing it won't move patches that are already installed, but the patches actually do move to the new location when I click OK to close the Settings window.
  • If I change a mod's original version of a patch (as can happen when upgrading a mod), the installed copy in ActiveMMPatches doesn't change, even if I open the PatchManager window and click the "Apply All" button.  Looks like the only way to activate the updated version of the patch is to disable the patch, apply all, then re-enable and apply all again.  It may be a good idea to make the "Apply All" button reinstall patches that are already active, to pick up any changes that may have been made to the original version.  (It'd also be helpful if PatchManager could notice the discrepancy and warn the user.)

Other than those issues, things are working well.  I'm hoping that PatchManager gains traction and becomes widely-used, because optional patches are something that aren't really well-handled in KSP right now.  (I can only think of a few mods that provide them, each in its own ad-hoc way.  I'd love to see that change.)

Answering your observations in order:

  • Working on a new screenshot.  It was moved because this mod applies the changes to ALL games.
  • The code to move was a late addition, I'll get the text updated.
  • I'll think about updatig what the "Apply All" button does, but that raises some other issues; it's not going to happen right away
Link to comment
Share on other sites

I just uninstalled them, but get this package

and look for it yourself, you can only see 3 or 4 patches at one time, because the window is pretty small. My proposal would be to group all patches comming from one mod, and make it expandable or such. Or just show the titles of each patch, not the whole description. Show the description as a tooltip, or if its clicked on.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...