Jump to content

KSPField questions


Recommended Posts

Is it possible to have an array or list of information stored as a persistent field in the game file?  I know I can do strings, ints, etc.  I'd like to avoid having to convert an array of ints to a string and then decode it back when the game loads.

 

Link to comment
Share on other sites

There's no built in way to parse and save lists, but you can do it manually with not that much code.  Something like:

public class MyModule : PartModule
{
    public List<int> theList = new List<int>();
    
    public override void OnLoad(ConfigNode node)
    {
        base.OnLoad(node);
        
        foreach (string value in node.GetValues("nameInNode"))
        {
            theList.Add(int.Parse(value));
        }
    }
    
    public override void OnSave(ConfigNode node)
    {
        base.OnSave(node);
        
        foreach (int value in theList)
        {
            node.AddValue("nameInNode", value);
        }
    }
}

This is pretty quick and dirty and you'd probably want to have at least a bit of error handling in there, but hopefully you get the idea.

Edited by blowfish
Link to comment
Share on other sites

32 minutes ago, blowfish said:

There's no built in way to parse and save lists, but you can do it manually with not that much code.  Something like:


public class MyModule : PartModule
{
    public List<int> theList = new List<int>();
    
    public override void OnLoad(ConfigNode node)
    {
        base.OnLoad(node);
        
        foreach (string value in node.GetValues("nameInNode"))
        {
            theList.Add(int.Parse(value));
        }
    }
    
    public override void OnSave(ConfigNode node)
    {
        base.OnSave(node);
        
        foreach (int value in theList)
        {
            node.AddValue("nameInNode", value);
        }
    }
}

This is pretty quick and dirty and you'd probably want to have at least a bit of error handling in there, but hopefully you get the idea.

That works for parts and part modules, but I want to do this for a game;  I've used the following successfully in other mods:

 

	[KSPScenario (ScenarioCreationOptions.AddToAllGames, new GameScenes[] {
		GameScenes.SPACECENTER,
		GameScenes.EDITOR,
		GameScenes.FLIGHT,
		GameScenes.TRACKSTATION,
		GameScenes.SPACECENTER
	})]
	public class PDPNPersistent : ScenarioModule
	{
		public static bool inited = false;

		[KSPField (isPersistant = true)]
		public int c1 = 0;
    

Will your method work for this as well?

Link to comment
Share on other sites

[Persistent] supports Lists and arrays. Simple example:

    class PersistentPartModuleExample : PartModule
    {
        [Persistent] private string[] _testArray = { "Apple", "Pear" };
        [Persistent] private List<string> _testList = new List<string> { "Cucumber", "Carrot" };

        public override void OnSave(ConfigNode node)
        {
            node.AddNode(ConfigNode.CreateConfigFromObject(this));
        }

        public override void OnLoad(ConfigNode node)
        {
            ConfigNode.LoadObjectFromConfig(this, node.GetNode(GetType().FullName));
        }
    }

It also executes methods before and after serializing the object if the object implements IPersistenceSave and IPersistenceLoad. You can easily save a dictionary (or resolve a reference, set a field, etc) this way:

    class PersistentPartModuleExample : PartModule, IPersistenceSave, IPersistenceLoad
    {
        // can't be serialized
        private Dictionary<string, string> _myDictionary = new Dictionary<string, string>();

        [Persistent] private List<string> _dictionaryKeys = new List<string>();
        [Persistent] private List<string> _dictionaryValues = new List<string>(); 

        public override void OnSave(ConfigNode node)
        {
            node.AddNode(ConfigNode.CreateConfigFromObject(this));
        }

        public override void OnLoad(ConfigNode node)
        {
            ConfigNode.LoadObjectFromConfig(this, node.GetNode(GetType().FullName));
        }

        // just before serializing
        public void PersistenceSave()
        {
            _dictionaryKeys = _myDictionary.Keys.ToList();
            _dictionaryValues = _myDictionary.Values.ToList();
        }

        // just after deserializing
        public void PersistenceLoad()
        {
            _myDictionary = Enumerable.Range(0, _dictionaryKeys.Count)
                .ToDictionary(idx => _dictionaryKeys[idx], idx => _dictionaryValues[idx]);
        }
    }

You can also serialize somewhat complex types with it. Maybe you have a class defining some information you want to persist. This particular one would be somewhat unpleasant to serialize manually (note its recursive nature):

class PersistentPartModuleExample : PartModule
{
    class ImportantDataToPersist
    {
        [Persistent] public string ImportantThing = string.Empty;
        [Persistent] public double ImportantNumber; // note how it's a double? handled!
        [Persistent] public List<ImportantDataToPersist> Children = new List<ImportantDataToPersist>();
    }

    [Persistent] private ImportantDataToPersist _importantStuff = new ImportantDataToPersist();


    public override void OnLoad(ConfigNode node)
    {
        ConfigNode.LoadObjectFromConfig(this, node.GetNode(GetType().FullName));
    }

    public override void OnSave(ConfigNode node)
    {
        node.AddNode(ConfigNode.CreateConfigFromObject(this));
    }
}

 

Link to comment
Share on other sites

7 minutes ago, linuxgurugamer said:

That works for parts and part modules, but I want to do this for a game;  I've used the following successfully in other mods:

*snip*

Will your method work for this as well?

There's nothing really PartModule specific in the code I gave, it was just a convenient example.  ScenarioModule has the same method names OnSave and OnLoad, so yes, it will work.

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