Jump to content

How to read custom config in a PartModule?


Recommended Posts

Apologies if this seems like a silly question, but I've been going around in circles and haven't been able to find any documentation that answers my question:

Details below, but what it boils down to is "I'm implementing a new PartModule, which needs to load custom config data at OnLoad time, and needs to access that data at OnStart time.  How do I access the data?"

 

What I'm trying to do

I'm writing my own PartModule, and it needs to have a data structure in it that's complex enough that the usual [KSPField] stuff won't do.  What I really need is to have some custom config in it, i.e. the config would look like like this:

MODULE {
    name = MySuperCoolPartModule
    
    SOME_CUSTOM_CONFIG {
        key1 = value1
        key2 = value2
    }
    
    // maybe some more SOME_CUSTOM_CONFIG blocks
}

 

How I've been trying to do it

Well, I see that PartModule has a handy overrideable OnLoad() method that receives a ConfigNode as input, so that seems to fit the bill!  I want to have code that will read the SOME_CUSTOM_CONFIG nodes (and their nested structure therein) and store that to some data member on the PartModule.  Seems pretty straightforward:  I override OnLoad, then take the ConfigNode that's passed in and call rootNode.nodes.GetNodes("SOME_CUSTOM_CONFIG") on  it to get those config nodes, then write whatever code I need to set things.

 

What's working

I see that my OnLoad code is getting called during KSP startup, i.e. before I actually load a game and go into the VAB and start placing parts.  I've added some log lines to my OnLoad processing, and I can see that it's doing everything that I want, exactly the way I want it to work.  Since it's being called on KSP startup, I assume that the place that my constructed data structures are going are onto some prefab version of the part where the PartModule lives.

 

What's not working

However... when I'm in the VAB and I actually create an instance of the part... OnStart gets called on the PartModule that's on the newly created instance of the part.  But the data members that get set at OnLoad time... aren't there.  It's as if OnLoad never happened.  (Certainly OnLoad doesn't get called when the player instantiates a part in the vehicle editor.)

class MySuperCoolPartModule : PartModule {

    private SomeSpecialDataStructure stuff = null;
  
    public override void OnLoad(ConfigNode node) {
        // Code here that initializes stuff based on the contents
        // of node. Upon completion, stuff is no longer null.
    }
  
    public override void OnStart(StartState state) {
        // I find that stuff is null.  Now what?
    }
}

I find that OnLoad is called once at KSP startup time, I assume on the part prefab.  And OnStart is called at part instantiation time, on the particular instance of the part.

But if that's the case... what do I do?  How do I get at the data at OnStart time, which is when I need it so that I can do stuff with it?

(I've implemented plenty of mods before, and usually just use [KSPField] for the data on my parts that I need to read from config, and that works great-- the field values get copied across to the instance of the PartModule, just the way I'd expect.  So really what I'm trying to figure out is how to accomplish the same thing when the data is coming from custom config nodes instead of by using [KSPField].)

Link to comment
Share on other sites

On phone, so I can't be too detailed. But you are right that OnLoad does not get called when you spawn a part in the editor. It will be called when a vessel is loaded in flight (and I think when a vessel is rolled out to the launchpad), and also when you load a vessel in the editor. And I think OnStart does not get called when a vessel is loaded in the editor, but I'm not sure about that.

I know, it's very irritating. 

You are right about the data being loaded into the prefab during startup, OnLoad is also called there.

You might be able to process all of the data that you need at that point, so that it is stored in the part prefab and carried over to newly instatiated copies of the part.

Link to comment
Share on other sites

14 hours ago, DMagic said:

You might be able to process all of the data that you need at that point, so that it is stored in the part prefab and carried over to newly instatiated copies of the part.

Thanks!

My problem is that it doesn't seem to be making the leap from the part prefab to the instantiated copies.  Not sure what the "right" answer is, but I've found a (somewhat clunky) workaround that works well enough.  I just have a static Dictionary<string, MyCustomDataStructure> that maps from part name to the thing I want.  That way, instantiated copies of the module can get at the data since my part module knows what part it's on. 

Link to comment
Share on other sites

You could also populate a list/dictionary in the prefab, then read from that list when a part's OnStart is called through the part's partInfo.partPrefab, or whatever the AvailablePart reference is called.

You should be able to propagate data from the prefab to the instantiated copy, as long as the data is serializable, and you would have to make sure the data collection is either public or marked with the SerializeField attribute. But that kind of thing can be tricky sometimes.

Link to comment
Share on other sites

Sorry I didn't see this earlier. You've probably already got something working.

What I do is fetch the ConfigNode for the PartModule:

ConfigNode myNode = Utility.GetPartModuleConfigNode(part, typeof(MASFlightComputer).Name, 0);

with GetPartModuleConfigNode defined over here: https://github.com/MOARdV/AvionicsSystems/blob/6a6d41612236451078eaa1109426bae24ff4a962/Source/Utility.cs#L551-L575

Then it's a case of reading through a ConfigNode.

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