UsersManual.Caveats - KSP-ModularManagement/ModuleManager GitHub Wiki
One very nasty misconception about MM is that it "thinks" logically. It doesn't - to tell you the true, it doesn't thinks at all.
Module Manager is essentially a Finite State Machine those tokens have some resemblance with our logical constructions, but that's all.
So Module Manager is not free of idiosyncrasies itself and this chapter will discuss them. Essentially, this chapter is a manual about how not to use MM.
One of the worst errors a developer can make is to add :NEEDS[]
to a :FOR[]
thinking that a failed needs would fully suppress the :FOR[]
.
Unfortunately, it would suppress it only partially. The :FOR[]
argument is always registered on the taglist
structure, where the names of the installed add'ons are kept.
So, the following patch:
@PART[*]:FOR[foo]:NEEDS[bar]
{
@title = I created "foo" besides "bar" not being installed!
}
Will not patch the part
's title
if bar
doesn't exists, but will create inconditionally the add'on foo
in the taglist
and from that point everybody using :NEEDS[foo]
, :AFTER[foo]
, :BEFORE[foo]
et all will be applied!
A receipt for the disaster on the long run.
Multiple :NEEDS[]
are not evaluated separately. In truth, only the first one is evaluated and the remaining ones bluntly ignored.
So, the following patch:
@PART[*]:NEEDS[Squad]::NEEDS[SquadExpansion]
{
@title = I was applied when "Squad" exists, no matter "SquadExpansion" exists or not!
}
will not apply the patch only when Squad
and also SquadExpansion
exists! Instead, a message like the following will be logged on MMPatch.log
:
[WRN 02:42:48.796] more than one :NEEDS tag detected, ignoring all but the first: net.lisias.ksp/multipleneeds/+PART[*]:FINAL:NEEDS[Squad]:NEEDS[SquadExpansion]
and, exactly as it's said on the log, only the first :NEEDS
is evaluated, rendering the patch working like this one:
@PART[*]:NEEDS[Squad]
{
@title = I was applied when "Squad" exists, no matter "SquadExpansion" exists or not!
}
The proper way to code this patch is, so:
@PART[*]:NEEDS[Squad,SquadExpansion]
{
@title = I was applied when both "Squad" and "SquadExpansion" exists.
}
Replacing :NEEDS[Squad,SquadExpansion]
with :NEEDS[Squad&SquadExpansion]
is being pushed on Forum as the recommended way, but I think it's harder to read and since there're years of patches being written with ,
instead of &
I just don't care about.
Exactly the same problem as :NEEDS
. Only the first one is evaluated, and the remaining ones ignored. The same solution should be applied.
The patching order on MM appears to be straightforward, but sometimes it's not!
For example, take the following example:
+PART[foo]:FINAL
{
@name = bar
@title = #$title$ SCREWED
-MODULE[foobar]{}
MODULE
{
name = foobar
// yada yada yada
}
}
apparently will copy the current foo
configpart
into a new bar
one, then replace the older foobar
with a new one, right?
Wrong! At this stage of the patching all reads are made on the source node, while the writes will be made on the new node. So the attempt to remove the older node will fail with a stack dump on the Log, and the patching will be aborted for this node.
(Thanks Kraken, as alternatively it would delete the
MODULE
on the source node!!)
This is how you should do the replacement:
+PART[foo]:FINAL
{
@name = bar
@title = #$title$ SUCESSFULY HACKED
}
@PART[bar]:FINAL
{
-MODULE[foobar]{}
MODULE
{
name = foobar
// yada yada yada
}
}
First you copy the node, optionally editing simple values on the root node. Then you do the heavy editing in the recently created node, where reads and writes happen on node you expect them to happen!
Also note that the order of the MODULE
nodes will not be the same (i,e, new ModuleEnginesFX
will be created at the end of the parent's node).