Jump to content

[1.8.x-1.12.x] Module Manager 4.2.3 (July 03th 2023) - Fireworks season


sarbian

Recommended Posts

@sarbian, Just curious, would it help to make the game load faster if Module Manager could distinguish its patches from other cfg-s by extension, e.g. ".mm" or ".patch", so it wouldn't be necessary  to scan and cache hundreds of configs of modded parts and props?

Link to comment
Share on other sites

4 hours ago, Ser said:

@sarbian, Just curious, would it help to make the game load faster if Module Manager could distinguish its patches from other cfg-s by extension, e.g. ".mm" or ".patch", so it wouldn't be necessary  to scan and cache hundreds of configs of modded parts and props?

The sha generation is already pretty fast.  MM only needs to look at the individual files to generate the sha for caching.  Once it's actually applying patches, everything is already loaded by KSP.  Also, creation nodes may have NEEDS and patches applied internally.

Link to comment
Share on other sites

Besides, the current setup allows many mods to have what are essentially combined files: A part (or other) config file, with MM patches after the main config, or even mixed in.  Making MM use a different extension would be a major breaking change for *lots* of mods.

Link to comment
Share on other sites

Which one is the correct syntax? 

@MODULE[ModuleScienceExperiment]:HAS[#experimentID[mysteryGoo]|#experimentID[mobileMaterialsLab]|#experimentID[surfaceSample]],*

or

@MODULE[ModuleScienceExperiment]:HAS[#experimentID[mysteryGoo|mobileMaterialsLab|surfaceSample]],*

 

Link to comment
Share on other sites

Hey I'm wondering, can I "select" all nodes, that have a subnode which have a specific key-value pair, IE I want to select this:
 

MODULE
{
    name = foo
    INPUT_RESOURCE
    {
        ResourceName = bar
    }
}

But not:

MODULE
{
    name = foo
    INPUT_RESOURCE
    {
        ResourceName= blah
    }
}

and for those modules I wish to "add" an extra input_resource. (Thus not changing the bar one), I tried:

@MODULE[foo]:HAS[INPUT_RESOURCE:HAS[#ResourceName[bar]]
{
}
@MODULE[foo]:HAS[#INPUT_RESOURCE/ResourceName[bar]]
{
}
	

 

But both methods don't work. - I wish to stres that the internal code (omitted above) does work, as if I don't put a selector there and just edit all "foo modules" it works (though that's not what I want).

Edited by paul23
Link to comment
Share on other sites

13 minutes ago, paul23 said:

Hey I'm wondering, can I "select" all nodes, that have a subnode which have a specific key-value pair, IE I want to select this:
 


MODULE
{
    name = foo
    INPUT_RESOURCE
    {
        ResourceName = bar
    }
}

But not:


MODULE
{
    name = foo
    INPUT_RESOURCE
    {
        ResourceName= blah
    }
}

and for those modules I wish to "add" an extra input_resource. (Thus not changing the bar one), I tried:


@MODULE[foo]:HAS[INPUT_RESOURCE:HAS[#ResourceName[bar]]
{
}
@MODULE[foo]:HAS[#INPUT_RESOURCE/ResourceName[bar]]
{
}
	

 

But both methods don't work. - I wish to stres that the internal code (omitted above) does work, as if I don't put a selector there and just edit all "foo modules" it works (though that's not what I want).

nodes and variables have  different syntax


:HAS[@MODULE] > has a  MODULE
:HAS[!MODULE] > has no MODULE

:HAS[#resource[*]] > has a resource
:HAS[~resource[*]] > has no resource

so you need 

@MODULE[foo]:HAS[@INPUT_RESOURCE:HAS[#ResourceName[bar]]]
{
}

 

Link to comment
Share on other sites

Thanks that solved it and explained it as well!

 

Now I've got two more questions:

- Can I "select by mod" - ie select all parts from a mod (with an extra HAS etc).?

 

- And can I make "optionals"? IE I wish to give "foo" variable the value of "bar" if it exists, and if it doesn't exist it gets the value of "blah"?

 

my guess is:

@module[myModule]
{
  %foo = #$blah$
  %foo = #$bar$
}

This works - however it has the side effect to introduce an error during the loading of the patch - for each "myModule" at which bar is not existing.

Edited by paul23
Link to comment
Share on other sites

26 minutes ago, paul23 said:

- Can I "select by mod" - ie select all parts from a mod (with an extra HAS etc).?

Not directly.  There might be other ways to identify these parts though, for instance if the part names all use the same prefix or if they all have the same author.

27 minutes ago, paul23 said:

- And can I make "optionals"? IE I wish to give "foo" variable the value of "bar" if it exists, and if it doesn't exist it gets the value of "blah"?

my guess is:


@module[myModule]
{
  %foo = #$blah$
  %foo = #$bar$
}

This works - however it has the side effect to introduce an error during the loading of the patch - for each "myModule" at which bar is not existing.

You need a condition on the patch

@module[myModule]:HAS[#bar]
{
  %foo = #$bar$
}

 

Link to comment
Share on other sites

30 minutes ago, paul23 said:

- And can I make "optionals"? IE I wish to give "foo" variable the value of "bar" if it exists, and if it doesn't exist it gets the value of "blah"?

This works - however it has the side effect to introduce an error during the loading of the patch - for each "myModule" at which bar is not existing.

you'll need to use :HAS checks to make sure you don't try to copy something that doesn't exist

 

ninja'd by @blowfish

 

Edited by Sigma88
Link to comment
Share on other sites

On 11/18/2016 at 11:45 AM, paul23 said:

Thanks for all the help; I guess there is no way to select "parts from a specific mod"? Would be nice if we could do this though.

Agreed, this would be quite useful.

Say I want to patch only the LFO fuel tanks from "Mod X", WITHOUT patching "every LFO fuel tank in the game".

Problem is, "Mod X" is a mod that adds a LOT of LFO fuel tanks (20+). I'm talking about a big mod with lots of parts like B9, etc.

Without a way to patch "only parts from "Mod X"" or "only parts found in directory "/ModX"", I'm forced to write a separate patch for each LFO fuel tank that is added by "Mod X", which is a tedious process because it requires me to look up the part name of each and every LFO fuel tank in "Mod X".
There must be a better way to describe this to Module Manager, as the way I know is tedious and repetitive (but it works).

Basically, right now we have ways to select "any part" (@PART[*]), "parts matching these characteristics" (@PART[*]:HAS[blah]), and "this specific part" (@PART[PartName]).
What we're missing is a short-hand way to select "any part in this folder". This would take care of the "stuff from this mod"

Something like this would be nice:
"@PART[*]:IN[FilePath]" (FilePath is assumed to start with "GameData/")
This would make the patch search for matches ONLY within the specified directory (or any subdirectories).

This would be especially nice if it can be extended to something like this:
"@PART[*]:IN[SpaceY-Lifters/Parts/FuelTanks | Engines]" (spaces added for clarity)
This would only search for matches in the "SpaceY-Lifters/Parts/Fueltanks" and "SpaceY-Lifters/Parts/Engines" directories (or any of their subdirectories).

The specific thing I'm trying to avoid is having to specify part names if I'm trying to apply a patch to
"any part in (ModName) with (ListOfCharacteristics)".


As a side note, Module Manager seems like it takes a lot of cues from Regular Expressions. That's a good thing, as regex is a really powerful tool, even if it can be confusing at times.
 

Spoiler

 

That being said, stuff like this is missing from the wiki:
"@description ^= :$:" will add stuff on the end of a part's description.
"?" is a single-character wildcard.
In-patch Variable use (not just "multiply this by 2", but "create variable X and then use it to control how the patch works, then delete it at the end").

To be honest, sometimes reading the MM wiki doesn't answer my question, or it does (and I realize it does) but not in a form I can parse.

 

 

Link to comment
Share on other sites

True, I can and have used prefixes to sort out multiple parts from more than one mod by the same author in the past.
Ex: "NBprobe*" matches NBprobe3m, NBprobe5m, and NBprobe7m so I can add MechJeb to all 3 of them with one patch.

Here's an example of where the ability to limit a patch by directory would be the only thing that makes it possible to write a patch without having to apply it to each individual part (meaning "@PART[part1]{PatchStuff}, @PART[part2]{PatchStuff}, @PART[part3]{PatchStuff}, etc.") :

Say there's a single mod that adds 7 spaceplane cockpits, 3 spaceplane probe cores, 8 space capsules, and 4 "regular" probe cores (similar form-factor to stock RC-L01 and RC-001S probe cores).

  • None of the spaceplane cockpits or drone cores have lifting surfaces.
  • 3 of the spaceplane cockpits and 5 of the space capsules can operate unmanned and/or crewed.
  • The spaceplane cockpits and drone cors are all under "ModName/Parts/Spaceplanes/Command"
  • The space capsules and "regular" probe cores are all under "ModName/Parts/Rockets/Command"

The intent of the patch is to add MechJeb to all the drone cores, and the spaceplane cockpits, but not the space capsules.

Here's the patch header that would select the spaceplane cockpits without selecting the space capsules.
It works without needing to find part names, but it would only work if I can limit the patch to a certain directory:

 @PART[ModPrefix*]:IN[ModName/Parts/Spaceplanes/Command]:HAS[@MODULE[ModuleCommand],!MODULE[MechJebCore],#CrewCapacity[*],#CrewCapacity[!=0]]:NEEDS[ModName] 

Translation (in case I have syntax errors in the above aside from using "IN" which is the search-in-specified-directory-only operator):

  • Any part starting with "ModPrefix"
  • Only search for matches in the directory "ModName/Parts/Spaceplanes/Command" (this is the new functionality that I'm talking about)
  • HAS a module called "ModuleCommand"
  • HAS no modules called "MechJebCore"
  • HAS a defined value for the key "CrewCapacity"
  • HAS the value for the key "CrewCapacity" is not zero

The double-checking on the last part is to make sure it doesn't trigger on parts that don't even have a "CrewCapacity" line in their config.

The patch that selects the drone cores of this mod still uses directory limits to make sure it doesn't operate on any probe cores from the same author's OTHER mods, and it basically inverts the "check for crew capacity" logic:

 @PART[ModPrefix*]:IN[ModName/Parts/]:HAS[@MODULE[ModuleCommand],!MODULE[MechJebCore],~CrewCapacity[*]|#CrewCapacity[0]]:NEEDS[ModName] 

Translation:

  • Any part starting with "ModPrefix"
  • Only search for matches in the directory "ModName/Parts/"
  • HAS a module called "ModuleCommand"
  • HAS no modules called "MechJebCore"
  • HAS no defined value for the key "CrewCapacity" OR the defined value for the key "CrewCapacity" is zero.

Again, the double checking is to make sure the patch DOES run on a part that has "CrewCapacity = 0" in it (zero or undefined either one works).

 

I went for the contrived example where this is the only solution aside from "manually patch for each part name" purely for demonstration purposes.
I have no reason to expect anything like this has actually happened in existing KSP part configs, but a less contrived example would result in the reply "Why don't you just list out the part names and patch them individually", which is EXACTLY the thing I want to eliminate whenever possible.

Link to comment
Share on other sites

On 11/19/2016 at 9:27 PM, blowfish said:

@SciMan I can't speak for other mods, but B9 uses prefixed part names which make them easier to identify.  Splitting out the HX parts complicated things somewhat, but you can still identify the correct parts relatively easily.  Example: B9 MFT/RF patch

 

Many mods don't do this: for example the USI system doesn't use prefixes at all.

 

EDIT: I feel I"m running into a bug. Or I am greatly misunderstanding something. module manager keeps crashing on a simple patch file:

	
//containers
@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]
{
 
    @cost = 1000
} 
//containers
@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[@RESOURCE[Supplies]]
{
    @cost = 1
}
	//containers
@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[!RESOURCE[Supplies]]
{
 
    @cost = 100
} 

The first runs cleanly, but the second and third don't run at all (yet at least 1 of those should always run? Either a part has a resource named Supplies or doesn't). Actually they crash with an exception.

PART
{
	name = Ranger_AgModule22
	module = Part
	author = RoverDude

	MODEL
	{
		model = UmbraSpaceIndustries/MKS/Assets/Ranger_AgModule
	}

	scale = 1
	rescaleFactor = 1

	node_stack_pod = 0.0, 0.0, 0.0, 0, 0, 1

	TechRequired = advConstruction
	entryCost = 5200

	cost = 16320
	category = none
	subcategory = 0
	title = MKS 'Ranger' Agricultural Module
	manufacturer = USI - Kolonization Division
	description = An expandable greenhouse that can be configured as an algae-based farm and biological filter using either recycled waste (yuck!) or local resources (either substrate or dirt, plus water).  Requires fertilzer, and can be used to supplement larger greenhouse-type modules.  Ensure an experienced scientist is on board for optimal efficiency.

	tags = USI MKS Ranger base colony agriculture farm agroponics greenhouse resource convert cultivate bio recyc KIS swap cargo weight logistics MKS ScienceContainter LifeSupport Kerbal algae expand Inflatable Recycle ReplacementParts LifeSupport Substrate MaterialKits Supplies Ore Recyclables SpecializedParts Fertilizer Dirt Organics Water Mulch ElectricCharge e/c 

	attachRules = 1,0,0,0,0
	mass = 1.251
	dragModelType = default
	maximum_drag = 0.3
	minimum_drag = 0.2
	angularDrag = 1
	crashTolerance = 8
	maxTemp = 2000 
	bulkheadProfiles = size1
	breakingForce = 250
	breakingTorque = 250
	CrewCapacity = 0
	tags = cck-lifesupport
	RESOURCE
	{
		name = Supplies
		amount = 0
		maxAmount = 250
		isTweakable = True
	}
}

This is the file I try to edit (from USI)

[ModuleManager] Exception while processing node : supersettings/usi_tac/@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[@RESOURCE[Supplies]]
System.ArgumentOutOfRangeException: Cannot be negative.
Parameter name: length
  at System.String.Substring (Int32 startIndex, Int32 length) [0x00000] in <filename unknown>:0 
  at ModuleManager.MMPatchLoader+<ApplyPatch>d__63.MoveNext () [0x00000] in <filename unknown>:0 
 
(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

[ModuleManager] Processed node was
@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[@RESOURCE[Supplies]][@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[@RESOURCE[Supplies]]]
  @PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[@RESOURCE[Supplies]]
  {
    @cost = 1
  }


 
(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

[ModuleManager] Exception while processing node : supersettings/usi_tac/@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[!RESOURCE[Supplies]]
System.ArgumentOutOfRangeException: Cannot be negative.
Parameter name: length
  at System.String.Substring (Int32 startIndex, Int32 length) [0x00000] in <filename unknown>:0 
  at ModuleManager.MMPatchLoader+<ApplyPatch>d__63.MoveNext () [0x00000] in <filename unknown>:0 
 
(Filename: C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineDebugBindings.gen.cpp Line: 42)

[ModuleManager] Processed node was
@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[!RESOURCE[Supplies]][@PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[!RESOURCE[Supplies]]]
  @PART[Ranger_AgModule22*]:AFTER[UmbraSpaceIndustries]:HAS[!RESOURCE[Supplies]]
  {
    @cost = 100
  }

And these exceptions were thrown while loading.

Edited by paul23
Link to comment
Share on other sites

I'm sure this basic question will have been asked before but I've searched and can't find it...

I believe that MM will try to parse any .cfg file in and below the GameData folder. I have several mods that use .cfg files for other things, like saved settings for the mod. Does MM try to parse these files?

Link to comment
Share on other sites

1 hour ago, Foxster said:

I'm sure this basic question will have been asked before but I've searched and can't find it...

I believe that MM will try to parse any .cfg file in and below the GameData folder. I have several mods that use .cfg files for other things, like saved settings for the mod. Does MM try to parse these files?

yes, and everytime you save something you force MM to reload the cache. which for some ppl can take a lot of time.

IIRC you can avoid this by putting your cfgs inside a folder called PluginData

Link to comment
Share on other sites

7 hours ago, Foxster said:

I'm sure this basic question will have been asked before but I've searched and can't find it...

I believe that MM will try to parse any .cfg file in and below the GameData folder. I have several mods that use .cfg files for other things, like saved settings for the mod. Does MM try to parse these files?

As Sigma88 said, anything in a PluginData folder will be ignored.  If there are mods that store settings in a cfg outside of a PluginData folder you should tell the author that this will break MM's caching clarification: writing to a .cfg file outside of a PluginData folder will cause ModuleManager's cache to be invalidated, causing it to re-apply all patches rather than simply reading from the cache.  This is undesirable because it makes the user wait significantly longer than necessary for KSP to load.

Edited by blowfish
Link to comment
Share on other sites

2 hours ago, blowfish said:

As Sigma88 said, anything in a PluginData folder will be ignored.  If there are mods that store settings in a cfg outside of a PluginData folder you should tell the author that this will break MM's caching.

That's not quite true. The contents of the .cfg would have to be malformed in a way that MM tries to parse and is unsuccessful in doing so or results in an illegal MM operation. If the contents of the file contain a valid node then it will not break MM caching.

Please be careful in disseminating information that can result in players coming to me about non-issues :wink:

(DeadlyReentry stores its settings in an ordinary config node and it is absolutely not a problem to do so)

Link to comment
Share on other sites

6 minutes ago, Starwaster said:

That's not quite true. The contents of the .cfg would have to be malformed in a way that MM tries to parse and is unsuccessful in doing so or results in an illegal MM operation. If the contents of the file contain a valid node then it will not break MM caching.

Please be careful in disseminating information that can result in players coming to me about non-issues :wink:

(DeadlyReentry stores its settings in an ordinary config node and it is absolutely not a problem to do so)

If it's in a .cfg file, and the contents change, then ModuleManager will re-apply every patch rather than using the cache.  If you're saving settings to a config file, it should be in a PluginData folder (and thus will be ignored by the game database and MM's caching)

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