Jump to content

Proper loading of ConfigNodes in a PartModule


Recommended Posts

I've looked around a bunch and haven't really been able to find any documentation on this.

Essentially I have a new PartModule that I would like to contain a few new blocks similar to PROPELLANT blocks. The goal would be something like this:

		MODULE
{
name = VariableISPEngine
EnergyUsage = 180

UseDirectThrottle = false

VARIABLEMODE
{
name = ArgonMode
ThrustCurve
{
key = 0 6
key = 1 22
}
IspCurve
{
key = 0 12000
key = 1 3200
}
}
VARIABLEMODE
{
name = HydrogenMode
ThrustCurve
{
key = 0 1.9
key = 1 6
}
IspCurve
{
key = 0 26500
key = 1 5250
}
}


}

Now, I've got that working about halfway, then I got stuck. Based on the documentation I've collected, I can successfully load the above data by reading it into an implementation of ConfigNode.

public class VariableEngineMode : IConfigNode
{
[Persistent]
public string name = "";
[Persistent]
public string fuelType = "";
[Persistent]
public FloatCurve thrustCurve = new FloatCurve();
[Persistent]
public FloatCurve ispCurve = new FloatCurve();

public VariableEngineMode()
{
}
public VariableEngineMode(ConfigNode node)
{
Load(node);
}
public void Load(ConfigNode node)
{

if (node.name.Equals("VARIABLEMODE"))
{
ConfigNode.LoadObjectFromConfig(this, node);
if (node.HasValue("name"))
name = node.GetValue("name");
if (node.HasValue("fuelType"))
fuelType = node.GetValue("fuelType");
if (node.HasNode("ThrustCurve"))
{
thrustCurve = new FloatCurve();
thrustCurve.Load(node.GetNode("ThrustCurve"));

}
if (node.HasNode("IspCurve"))
{
ispCurve = new FloatCurve();
ispCurve.Load(node.GetNode("IspCurve"));
}
}

}

public void Save(ConfigNode node)
{
ConfigNode.CreateConfigFromObject(this, node);
}

}

Then load it via my PartModule's OnLoad() section. This code performs fine at load time - that is, I can read out the members of engineModes and they are correctly populated during the KSP loading scene.

public override void OnLoad(ConfigNode node)
{
base.OnLoad(node);

ConfigNode[] nodes = node.GetNodes("VARIABLEMODE");
engineModes = new List<VariableEngineMode>();
foreach (ConfigNode n in nodes)
{
VariableEngineMode mode = new VariableEngineMode(n);
engineModes.Add(mode);
}
this.moduleName = "Variable ISP Engine";
}

The issue - Once ingame and the part's OnStart() runs, engineModes is back to an uninitialized, empty List. I've also tried doing in with a builtin array with no luck.

So, what am I missing? I feel like there could be some step between OnLoad and OnStart that I need to specify, but I can't find info.

Link to comment
Share on other sites

I've looked around a bunch and haven't really been able to find any documentation on this.

Essentially I have a new PartModule that I would like to contain a few new blocks similar to PROPELLANT blocks. The goal would be something like this:

		MODULE
{
name = VariableISPEngine
EnergyUsage = 180

UseDirectThrottle = false

VARIABLEMODE
{
name = ArgonMode
ThrustCurve
{
key = 0 6
key = 1 22
}
IspCurve
{
key = 0 12000
key = 1 3200
}
}
VARIABLEMODE
{
name = HydrogenMode
ThrustCurve
{
key = 0 1.9
key = 1 6
}
IspCurve
{
key = 0 26500
key = 1 5250
}
}


}

Now, I've got that working about halfway, then I got stuck. Based on the documentation I've collected, I can successfully load the above data by reading it into an implementation of ConfigNode.

public class VariableEngineMode : IConfigNode
{
[Persistent]
public string name = "";
[Persistent]
public string fuelType = "";
[Persistent]
public FloatCurve thrustCurve = new FloatCurve();
[Persistent]
public FloatCurve ispCurve = new FloatCurve();

public VariableEngineMode()
{
}
public VariableEngineMode(ConfigNode node)
{
Load(node);
}
public void Load(ConfigNode node)
{

if (node.name.Equals("VARIABLEMODE"))
{
ConfigNode.LoadObjectFromConfig(this, node);
if (node.HasValue("name"))
name = node.GetValue("name");
if (node.HasValue("fuelType"))
fuelType = node.GetValue("fuelType");
if (node.HasNode("ThrustCurve"))
{
thrustCurve = new FloatCurve();
thrustCurve.Load(node.GetNode("ThrustCurve"));

}
if (node.HasNode("IspCurve"))
{
ispCurve = new FloatCurve();
ispCurve.Load(node.GetNode("IspCurve"));
}
}

}

public void Save(ConfigNode node)
{
ConfigNode.CreateConfigFromObject(this, node);
}

}

Then load it via my PartModule's OnLoad() section. This code performs fine at load time - that is, I can read out the members of engineModes and they are correctly populated during the KSP loading scene.

public override void OnLoad(ConfigNode node)
{
base.OnLoad(node);

ConfigNode[] nodes = node.GetNodes("VARIABLEMODE");
engineModes = new List<VariableEngineMode>();
foreach (ConfigNode n in nodes)
{
VariableEngineMode mode = new VariableEngineMode(n);
engineModes.Add(mode);
}
this.moduleName = "Variable ISP Engine";
}

The issue - Once ingame and the part's OnStart() runs, engineModes is back to an uninitialized, empty List. I've also tried doing in with a builtin array with no luck.

So, what am I missing? I feel like there could be some step between OnLoad and OnStart that I need to specify, but I can't find info.

That's because OnLoad is called during the loading sequence and before flight, not in the editor. So whatever you get in the loading sequence is then unloaded before you get to the editor. A solution I came with is to save the ConfigNode of the Module in a public variable, since it's serializable it won't be unloaded. You can just reload mmanually in OnStart with the node.

Link to comment
Share on other sites

Ah, awesome. I'll do that.

- edit: Ok, so I tried this... and yes, that worked. Stuff loaded in the VAB. However, of course, changing the scene to Flight cleared everything again. So reload in flight? Nope, now my saved ConfigNode is empty!

So in summary:

- Loaded data in OnLoad(), saved the whole module's ConfigNode to a public variable

- Data reloads manually just fine in the VAB/SPH

- Data does *not* reload in flight because the ConfigNode is empty.

So I'm just generally scratching my head on how all this works now.

Edited by Nertea
Link to comment
Share on other sites

I ended up putting the data in static variables to store them.

Check the source here:

https://github.com/snjo/Firespitter/blob/master/Firespitter/tools/FSnodeLoader.cs

https://github.com/snjo/Firespitter/blob/master/Firespitter/FSnodeLoaderTest.cs (not usre if that test is compatible with the above class anymore)

https://github.com/snjo/Firespitter/blob/master/Firespitter/customization/FStextureSwitch.cs - but it is used in this one

These examples are very custom to a particular use, but you can see the system of static lists in the FStextureSwitch. This isn't the best system ever, but it works. I've since abandoned nodes for parsed strings in FStextureSwitch2. They are much easier to work with since you don't need to restart the game each time you change the part.cfg.

edit: and then i parse floatCurves using this parser

Edited by Snjo
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...