Jump to content

[0.11.1] Patch Manager


cheese3660

Recommended Posts

Patch Manager

A mod for all your generic patching needs!

Spacedock: https://spacedock.info/mod/3482/Patch Manager

Github: https://github.com/KSP2Community/PatchManager

Author: KSP2 Community

PatchManager

Description

Patch Manager is a mod for KSP2 that functions as a sort of spiritual successor to Module Manager for KSP1, its purpose is to allow for the patching of existing JSON definitions for anything that exists in the KSP2 Addressables files (this includes Parts/Galaxies/Planets/Tech/Resources/Etc...), along with the creation thereof.

It does this by allowing the user to write patches and patch libraries in a custom syntax derived loosely off of SCSS, a lot of the functioning of which is documented in the reference for the language.

How to Make Patches

The best place to learn how to make patches is by asking people in the: KSP2 Modding Society Discord Server
Other places to learn are the aforementioned reference (which will be being updated to add more information)

Or by looking at how it is used in other mods (all examples are licensed under MIT):

Dependencies

Edited by cheese3660
bump version
Link to comment
Share on other sites

Patch Manager 0.7.0
## What's Changed
- Unquoted Strings
- List Subtraction
- Standalone patches (hopefully)
## Breaking changes
- Prefix expressions have been removed and replaced with mutating definitions, instead of `: +[` do ` +: [`

**Full Changelog**: https://github.com/KSP2Community/PatchManager/compare/v0.6.1...v0.7.0

Link to comment
Share on other sites

Hey, thank you for the mod! I've been working on my own .patch files and learning the syntax based on the wiki. I can make the part changes I'd like pretty easily, however I'm trying to convert a .konfig file over to a .patch file since I was told Konfig was being/already is deprecated. Could I get some help translating the Mun Rotation (and preferably a Custom Skybox) .konfig scripts over to .patch files? I honestly don't know where to start since I've only just started getting use to this language, but I can't quite wrap my mind around how to make it work. The black skybox and .konfig show that they should work on 0.2, but nothing loads (and I only get on kpatcher line in my log files, and it's a ton of errors). If anyone could help, the .konfig codes are:

Mun Rotation Konfig:

[Target(Mun)]
[Module(CelestialBodyComponent)]
[Data(CelestialBodyProperties)]
Data.rotationPeriod = 800;
Data.rotates = true;
Data.isTidallyLocked = false;
Module.SetDefinition(Data);

Custom Skybox Konfig:

[Target(Black)]
[Module(Skybox)]
[Data(int)]
Data = 1024;

Thanks for the hard work on this mod. I'll continue to attempt to create the .patch files for the above in the meantime. If I come across  a solution I'll update as needed.

Link to comment
Share on other sites

3 hours ago, shoe7ess said:

Hey, thank you for the mod! I've been working on my own .patch files and learning the syntax based on the wiki. I can make the part changes I'd like pretty easily, however I'm trying to convert a .konfig file over to a .patch file since I was told Konfig was being/already is deprecated. Could I get some help translating the Mun Rotation (and preferably a Custom Skybox) .konfig scripts over to .patch files? I honestly don't know where to start since I've only just started getting use to this language, but I can't quite wrap my mind around how to make it work. The black skybox and .konfig show that they should work on 0.2, but nothing loads (and I only get on kpatcher line in my log files, and it's a ton of errors). If anyone could help, the .konfig codes are:

Mun Rotation Konfig:

[Target(Mun)]
[Module(CelestialBodyComponent)]
[Data(CelestialBodyProperties)]
Data.rotationPeriod = 800;
Data.rotates = true;
Data.isTidallyLocked = false;
Module.SetDefinition(Data);

Custom Skybox Konfig:

[Target(Black)]
[Module(Skybox)]
[Data(int)]
Data = 1024;

Thanks for the hard work on this mod. I'll continue to attempt to create the .patch files for the above in the meantime. If I come across  a solution I'll update as needed.

For the first one, it should be something like this:

@patch celestial_bodies;

:json celestial_bodies > data {
    @if $$bodyName == "Mun" {
        rotationPeriod: 800;
        isTidallyLocked: false;
    }
}

I tested only briefly, but it seems to work.

For the second one, there's no direct replacement, since Patch Manager can only edit or create JSON files (which the games uses for the definitions of parts, planets, science, and things like that), but the skybox is just a texture, and Konfig seems to have included a lot of custom code to get that to work, so the next best thing would be to take the C# code from Konfig's source and use it to put together your own mod that replaces the skybox textures similarly to how it did.

Edited by munix
Link to comment
Share on other sites

Spoiler

For the first one, it should be something like this:

@patch celestial_bodies;

:json celestial_bodies > data {
    @if $$bodyName == "Mun" {
        rotationPeriod: 800;
        isTidallyLocked: false;
    }
}

I tested only briefly, but it seems to work.

For the second one, there's no directly replacement, since Patch Manager can only edit or create JSON files (which the games for the definitions of parts, planets, science, and things like that), but the skybox is just a texture, and Konfig seems to have included a lot of custom code to get that to work, so the next best thing would be to take the C# code from Konfig's source and use it to put together your own mod that replaces the skybox textures similarly to how it did.

You are awesome. I was actually on the right (well, I thought maybe it had to be editing .json data), but thank you for saving me the time on that! I may make that my first C# project (never programmed with that language before and, although the stock one is quite beautiful, the one I made from Space Engine would be gorgeous).

However, I've worked on a part patch for about 3 hours of troubleshooting and is just not taking. I'm attempting to increase the ejection impulse of the radial decouplers in the game. Originally I wanted to just multiply the values by 10 but was running into too many errors I didn't understand in the log so I eventually just landed on a flat "5000" kN for each part. However, no matter how hard I try, I can't get it working. I have tried the following different methods:

Spoiler
:parts #decoupler_1v_radial {
	> Module_Decoupler {
		ejectionForce: 5000
		EjectionImpulse: 5000
    }
}

:parts #decoupler_1v_radial {
	@merge {
    ejectionForce: 5000
	EjectionImpulse: 5000
	};
}

:parts #decoupler_1v_radial {
    ejectionForce: 5000
	EjectionImpulse: 5000
}

 

I have attempted with and without the "EjectionImpulse" line and receive no errors in the log, but they still have default impulse values...

Edited by shoe7ess
Link to comment
Share on other sites

58 minutes ago, shoe7ess said:

You are awesome. I was actually on the right (well, I thought maybe it had to be editing .json data), but thank you for saving me the time on that! I may make that my first C# project (never programmed with that language before and, although the stock one is quite beautiful, the one I made from Space Engine would be gorgeous).

However, I've worked on a part patch for about 3 hours of troubleshooting and is just not taking. I'm attempting to increase the ejection impulse of the radial decouplers in the game. Originally I wanted to just multiply the values by 10 but was running into too many errors I didn't understand in the log so I eventually just landed on a flat "5000" kN for each part. However, no matter how hard I try, I can't get it working. I have tried the following different methods:

  Hide contents
:parts #decoupler_1v_radial {
	> Module_Decoupler {
		ejectionForce: 5000
		EjectionImpulse: 5000
    }
}

:parts #decoupler_1v_radial {
	@merge {
    ejectionForce: 5000
	EjectionImpulse: 5000
	};
}

:parts #decoupler_1v_radial {
    ejectionForce: 5000
	EjectionImpulse: 5000
}

 

I have attempted with and without the "EjectionImpulse" line and receive no errors in the log, but they still have default impulse values...

 

You got pretty close, the main differences are that you need semicolons after the assignments, and it's actually Module_Decouple without the "r" at the end. To access the data inside a module, you need to go a level deeper into Data_Decouple. Also, I don't think the impulse needs to be patched here. Here it is:

Spoiler
:parts #decoupler_1v_radial {
    * > Module_Decouple > Data_Decouple {
        ejectionForce *: 10;
    }
}

And if you wanted to do it for all radial decouplers at once (also showing the shorter version of the selector):

:parts #decoupler_??_radial > Module_Decoupler > Data_Decouple {
    ejectionForce *: 10;
}

 

Edited by munix
Link to comment
Share on other sites

1 hour ago, munix said:

You got pretty close, the main differences are that you need semicolons after the assignments, and it's actually Module_Decouple without the "r" at the end. To access the data inside a module, you need to go a level deeper into Data_Decouple. Also, I don't think the impulse needs to be patched here. Here it is:

  Hide contents
:parts #decoupler_1v_radial {
    * > Module_Decouple > Data_Decouple {
        ejectionForce *: 10;
    }
}

And if you wanted to do it for all radial decouplers at once (also showing the shorter version of the selector):

:parts #decoupler_??_radial > Module_Decoupler > Data_Decouple {
    ejectionForce *: 10;
}

 

Man, you are awesome. Thanks for the info, I'm glad I wasn't too far off. I could plow MM like a boss back in the day and I can't wait to reach the same point with PM :)

Link to comment
Share on other sites

2 hours ago, munix said:

To access the data inside a module, you need to go a level deeper into Data_Decouple.

The reason I didnt shorten this for reference, is that there are modules (usually ones derived from others) that can have multiple data types

Link to comment
Share on other sites

Happy new year and I am thrilled to have a way of patching KSP2 thanks to your mod and also apologize, if my questions sound a bit simple, this due to me being exactly that.
Used to create simple patches in KSP1 using Modul Manager, but I am stuck a bit with Patch Manager on KSP2 now.

#1 Looking for a reference on what fields exist for parts/resources, e.g. your patch "rover_0v_wheel" in the wiki uses field "mass".
How would I know that the field "mass" exists at all? (Though got a slight suspicion these fields are still the same as they where in KSP1, right?)

#2 Especially trying to increase ElectricCharge for batteries and don't seem to get the hang of how to patch resources.


Thanks again for your work and I am in no hurry please!

Link to comment
Share on other sites

16 minutes ago, Cave_Lupum said:

Happy new year and I am thrilled to have a way of patching KSP2 thanks to your mod and also apologize, if my questions sound a bit simple, this due to me being exactly that.
Used to create simple patches in KSP1 using Modul Manager, but I am stuck a bit with Patch Manager on KSP2 now.

#1 Looking for a reference on what fields exist for parts/resources, e.g. your patch "rover_0v_wheel" in the wiki uses field "mass".
How would I know that the field "mass" exists at all? (Though got a slight suspicion these fields are still the same as they where in KSP1, right?)

#2 Especially trying to increase ElectricCharge for batteries and don't seem to get the hang of how to patch resources.


Thanks again for your work and I am in no hurry please!

Definitely not bad questions! To see the stock parts and their fields, you can use the small TextAssetDumper plugin (it's also on CKAN), which adds a "DUMP" button to the main menu, and after clicking that, in the plugin's folder you'll find dump/text_assets/parts_data, and inside it you'll see the JSON definition files for all parts.

For the second question, it should look like this, it's a bit different from what the wiki tells you, it needs to be updated:

:parts #storage_??_battery* {
    * > resourceContainers {
        * > .ElectricCharge {
            capacityUnits *: 100;
            initialUnits *: 100;
        }
    }
}

 

Link to comment
Share on other sites

1 hour ago, munix said:

Definitely not bad questions! To see the stock parts and their fields, you can use the small TextAssetDumper plugin (it's also on CKAN), which adds a "DUMP" button to the main menu, and after clicking that, in the plugin's folder you'll find dump/text_assets/parts_data, and inside it you'll see the JSON definition files for all parts.

For the second question, it should look like this, it's a bit different from what the wiki tells you, it needs to be updated:

:parts #storage_??_battery* {
    * > resourceContainers {
        * > .ElectricCharge {
            capacityUnits *: 100;
            initialUnits *: 100;
        }
    }
}

 

Thanks so much for your quick reply, much appreciated! Already managed to pull the mentioned dump and I am comforted a bit, that it was no wonder I wasn't able to deduct the correct use of the :resource RuleSet :wink:.

Link to comment
Share on other sites

Patch Manager v0.8.0

This update adds support for string interpolation, done via `#{...}` inside of a quoted string.
It also adds support for `@each`/`@for`/`@while` loops inside of selection blocks.

6 hours ago, munix said:

For the second question, it should look like this, it's a bit different from what the wiki tells you, it needs to be updated:

Wiki has been updated

Link to comment
Share on other sites

I've not been able to find references for editing things that aren't parts or resources. I see there's a generic "json" option but no one seems to have used it yet so I can't just steal copy and modify their code for my own use.

I'm trying to affect the axial tilt of planets and moons. I used the Text Asset Dumper mod (which is fantastic) and with it, I have the file for - say - Mun. In there is this code (extra stuff stripped):

{
    "version": "0.3",
    "useExternal": false,
    "data": {
        "bodyName": "Mun",
        ...
        "axialTilt": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0
        },
        ...
    }
}

I've tried everything I can think of, basically at random because I have no idea what I'm doing. The most recent patch file that failed is:

:json #mun > data {
    @set {
        axialTilt: {
            x: 30.0,
            y: 0.0,
            z: 0.0
        }
    };
}

I've tried with quotes around those strings. I've tried putting "data" as a section below "@set" containing "axialTilt" (with and without quotes around the strings), without that semicolon, and with the semicolon elsewhere...

I'm trying to mimic what I see people doing with parts, but it's just not working out for me.

Could someone tell me the 8-10 things I'm doing wrong, and how to do them correctly so I can finally get to creating my "Kerbolar System As I See It" patch?

Edited by Superfluous J
Link to comment
Share on other sites

15 minutes ago, Superfluous J said:

 

I've tried everything I can think of, basically at random because I have no idea what I'm doing. The most recent patch file that failed is:

:json #mun > data {
    @set {
        axialTilt: {
            x: 30.0,
            y: 0.0,
            z: 0.0
        }
    };
}

I've tried with quotes around those strings. I've tried putting "data" as a section below "@set" containing "axialTilt" (with and without quotes around the strings), without that semicolon, and with the semicolon elsewhere...

I'm trying to mimic what I see people doing with parts, but it's just not working out for me.

Could someone tell me the 8-10 things I'm doing wrong, and how to do them correctly so I can finally get to creating my "Kerbolar System As I See It" patch?

You can use the patch in this post as inspiration: 

The most important part is to first use the @patch directive. It's needed when using the generic json ruleset, so that we don't have to try to patch every single label that exists in the game. And the other thing is that you can only really use the #name syntax with the specialized rulesets, because the generic json one doesn't know where to find the name of a general JSON asset, so you have to get around it by using a condition. I think those two changes should be enough to get your patch working.

Edit: Oh and you shouldn't need to use @set for this, since that would replace the contents of the whole file with just the axial tilt.

Edited by munix
Link to comment
Share on other sites

Again, thank you. I am getting all a'tilty over here.

However I've hit another snag. SOME world properties are stored in their own json files, but orbital parameters (most importantly for me right now is inclination) are stored in the file GalaxyDefinition_Default which is a json file but was not given the extension json (or any extension) by the Text Asset Dumper.

In it for - say - Minmus we have this:

{
    "Name": "Default",
    "Version": "0.0.1",
    "CelestialBodies": [
        ...
        {
            "GUID": "Minmus",
            "PrefabKey": "Celestial.Minmus.Simulation",
            "OrbitProperties": 
            {
                "referenceBodyGuid":  "Kerbin",
                "inclination": "6",
                "eccentricity":  "0",
                "semiMajorAxis": "47000000",
                "longitudeOfAscendingNode":  "78",
                "argumentOfPeriapsis": "38",
                "meanAnomalyAtEpoch":  "0.9",
                "epoch": "0"
            },
            ...
        },
    ]
}

...and I'm not sure how to define that in my file.

I tried a couple things before giving up. The one I felt the most confident of was just adding it to the main

:json celestial_bodies > data {
    ...
    @if $$bodyName == "Minmus" {
        axialTilt: {
            x: -23.0,
            y: 0.0,
            z: 0.0
        };
        inclination: -23;
    }
    @if $$GUID == "Minmus" {
        inclination: -23;
    }
    ...
}

I get why it doesn't work (or at least I think I do). There is no "data" in the GalaxyDefinition_Default file. I don't know how to fix it, though, in my file to reference that one.

I tried to reverse engineer what I already have, but the first line ":json celestial_bodies > data {", I don't know how I'd have found out "celestial_bodies" on my own, so don't know how to figure out what I'd need to use to locate Minmus' inclination in the GalaxyDefinition_Default file.

Link to comment
Share on other sites

As for the GalaxyDefinition_Default stuff, this is what a WIP mod I'm working on, Shoemaker, is meant to address, but thats a bit out from release, as I have to figure out some stuff about scaling planets still.

 

Shoemaker will be an addon for PM meant specifically for planet modding.

Link to comment
Share on other sites

8 hours ago, Superfluous J said:

Again, thank you. I am getting all a'tilty over here.

However I've hit another snag. SOME world properties are stored in their own json files, but orbital parameters (most importantly for me right now is inclination) are stored in the file GalaxyDefinition_Default which is a json file but was not given the extension json (or any extension) by the Text Asset Dumper.

The way the addressables system works is that assets are assigned labels, a single asset can have multiple labels (for example, parts have a label of their own name, but all of them also have "parts_data", that way the game can load all parts at once, included ones from mods - they just have to be labeled with "parts_data"). What TextAssetDumper does is that inside TextAssetDumper/dump/text_assets, it creates a folder for every addressable label that contains text assets (which are usually JSON files, even if without an extension). So, if you want to find all the celestial bodies, you can look inside the "celestial_bodies" folder, since that's the common label for them, and that's also what the Patch Manager patch needs to target. Similarly, you can find a folder called GalaxyDefinition_Default in there, which contains the definition of the galaxy, and the orbital parameters of all the celestial bodies in it. So, you'll need to write a patch that specifically targets that label. And to do that, you need to use a @patch statement to tell Patch Manager to include that label:

@patch GalaxyDefiniton_Default;

Now Patch Manager will include this this label when patching assets.

This specific patch is a bit more complicated, because all variables/fields are considered immutable, so you can't just edit some nested value, instead you have to redefine them with a new object.

The best way to "edit" an array like CelestialBodies is to use the "map" function from the "builtin:list" library, which is called on all the elements of the array and then returns a new modified version of the array. You can define a closure to pass to the "map" function, like I do with $inclineMinmus in the example below. There we check if the current element has the GUID of Minmus, and if it does, we use another function, "set" from "builtin:dictionary", to replace the values of the object. The inner "set" creates a copy of the OrbitProperties object with the "inclination" field's value set to 45. Then, that copied and modified object is used to create a copy of the "$body" variable, now with its OrbitProperties field set to the previously created object. Passing $inclineMinmus to $value:map(...) will return the CelestialBodies array with Minmus's inclination modified to 45. And last, we use @set to replace the entire value of CelestialBodies with the result of the "map" function.

@use 'builtin:list';
@use 'builtin:dictionary';

@patch 'GalaxyDefinition_Default';

$inclineMinmus: @function($body) {
    @if $body['GUID'] == 'Minmus' {
        $body: $body:set(
            'OrbitProperties', $body['OrbitProperties']:set(
                'inclination', 45.0
            )
        );
    }

    @return $body;
};

:json GalaxyDefinition_Default {
    * > CelestialBodies {
        @set $value:map($inclineMinmus);
    }
}

But yeah, as Cheese said, this is just a temporary solution, she is working on a better one.

Edited by munix
Link to comment
Share on other sites

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...