Beale

[1.4] Project Manager - Group and Autonumber Your Launches [09/03/2018]

Recommended Posts

On 5/7/2018 at 4:19 AM, Wyzard said:

BTW, I've submitted a pull request that fixes the revert issue by bringing the launch counts into the .sfs file.  I've been using the modified version for a few weeks and it seems to work well; I haven't encountered any problems.

Hmm, I have updated to work with the scenario module and nodes, though it is for sure a lot easier than external save files, the revert still does not seem to work for me?


This is a new re-write which is much more compact - actually it does not appear to save at all!

namespace ProjectManager
{
    [KSPScenario(ScenarioCreationOptions.AddToAllGames, GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
    class ScenarioProjectManager : ScenarioModule
    {
        // Constants.
        private const string LOG_PREFIX = "[Project Manager]";
        private const string NODE_PROJECT = "PROJECTS";
        private const string VALNAME_LAUNCHCOUNT = "launchCount";

        // Variables.
        private static bool isSubscribed = false;
        private ConfigNode rootNode;

        // Functions.
        private Func<string, string> GetSeriesNodeName = 
            (string seriesName) => Regex.Replace(seriesName, "[^a-zA-Z0-9_.]+", "");

        private Func<string, ConfigNode, bool> GetIsSeriesNodeCreated = 
            (string seriesNodeName, ConfigNode rootNode) => (rootNode.GetNode(seriesNodeName) != null);

        private Func<ConfigNode, bool> GetIsSeriesLaunchCountCreated = 
            (ConfigNode seriesNode) => (seriesNode.GetValue(VALNAME_LAUNCHCOUNT) != null);

        public override void OnAwake()
        {
            base.OnAwake();

            if (!isSubscribed)
            {
                isSubscribed = true;

                // Subscribe to launch event.
                GameEvents.OnVesselRollout.Add(OnVesselRollout);
                Debug.LogFormat("{0}{1}", LOG_PREFIX, "Subscribed to launch event.");
            }
        }

        public override void OnLoad(ConfigNode node)
        {
            base.OnLoad(node);
            rootNode = node.GetNode(NODE_PROJECT);

            if(rootNode == null)
            {
                rootNode = new ConfigNode(NODE_PROJECT);
            }
        }

        public override void OnSave(ConfigNode node)
        {
            node.AddNode(rootNode);
            base.OnSave(node);
        }

        private void OnVesselRollout(ShipConstruct shipConstruct)
        {
            var vessel = FlightGlobals.ActiveVessel;
            string vesselName = vessel.vesselName;

            string seriesName = GetSeriesName(vesselName);

            if (seriesName == null)
                return;

            string seriesNodeName = GetSeriesNodeName(seriesName);

            bool isSeriesNodeCreated = GetIsSeriesNodeCreated(seriesNodeName, rootNode);

            if(!isSeriesNodeCreated)
            {
                CreateSeriesNode(rootNode, seriesNodeName);
            }

            var seriesNode = rootNode.GetNode(seriesNodeName);

            bool isSeriesLaunchCountCreated = GetIsSeriesLaunchCountCreated(seriesNode);

            if(!isSeriesLaunchCountCreated)
            {
                CreateSeriesLaunchCount(seriesNode);
            }

            // Get the current launch count.
            string seriesLaunchCountString = seriesNode.GetValue(VALNAME_LAUNCHCOUNT);
            int seriesLaunchCount = Convert.ToInt32(seriesLaunchCountString);

            // Rename the vessel using new launch count.
            int newLaunchCount = seriesLaunchCount + 1;
            vessel.vesselName = string.Format("{0} {1}", seriesName, newLaunchCount);

            // Write the new launch count to series node.
            seriesNode.SetValue(VALNAME_LAUNCHCOUNT, newLaunchCount);
        }

        private string GetSeriesName(string vesselName)
        {
            var seriesPattern = @"\[(.*?)\]";
            var seriesMatch = Regex.Match(vesselName, seriesPattern);

            if (string.IsNullOrEmpty(seriesMatch.Value))
                return null;

            string seriesName = seriesMatch.Value;

            seriesName = seriesName.Replace("[","");
            seriesName = seriesName.Replace("]","");

            return seriesName;
        }

        private void CreateSeriesNode(ConfigNode rootNode, string seriesNodeName)
        {
            ConfigNode vesselNode = new ConfigNode(seriesNodeName);
            vesselNode.AddValue(VALNAME_LAUNCHCOUNT, 0);

            rootNode.AddNode(vesselNode);
        }

        private void CreateSeriesLaunchCount(ConfigNode seriesNode)
        {
            seriesNode.AddValue(VALNAME_LAUNCHCOUNT, 0);
        }
        
    }
}

 

Edited by Beale

Share this post


Link to post
Share on other sites
2 hours ago, Beale said:

Hmm, I have updated to work with the scenario module and nodes, though it is for sure a lot easier than external save files, the revert still does not seem to work for me?


This is a new re-write which is much more compact - actually it does not appear to save at all!


namespace ProjectManager
{
    [KSPScenario(ScenarioCreationOptions.AddToAllGames, GameScenes.FLIGHT, GameScenes.EDITOR, GameScenes.SPACECENTER)]
    class ScenarioProjectManager : ScenarioModule
    {
        // Constants.
        private const string LOG_PREFIX = "[Project Manager]";
        private const string NODE_PROJECT = "PROJECTS";
        private const string VALNAME_LAUNCHCOUNT = "launchCount";


        public override void OnLoad(ConfigNode node)
        {
            base.OnLoad(node);
            rootNode = node.GetNode(NODE_PROJECT);

            if(rootNode == null)
            {
                rootNode = new ConfigNode(NODE_PROJECT);
            }
        }

        public override void OnSave(ConfigNode node)
        {
            node.AddNode(rootNode);
            base.OnSave(node);
        }

     
}

 

In OnSave you have to save your vaiables and in Onload you have to  load them. KSP will not do this for you (I think in Partmodules this can be automated). Here you have to do all the dirty work by yourself. The base.OnSave() will not do anything usefull. 

Share this post


Link to post
Share on other sites
31 minutes ago, Ger_space said:

In OnSave you have to save your vaiables and in Onload you have to  load them. KSP will not do this for you (I think in Partmodules this can be automated). Here you have to do all the dirty work by yourself. The base.OnSave() will not do anything usefull. 

Ah is this note handled by node.AddNode? 

From the pinned example:

9) Save/Load data.

 

The simplest way to save/load data is to use the KSPField attribute as listed in the Common Properties/Objects section and let KSP do all the work for you. If you needs are more complex you can use the OnSave/OnLoad methods to save to the confignode, or you can directly save to a file on disk.

 

OnSave/OnLoad methods:

Public void OnSave(ConfigNode node)
{
	node.AddValue("myValue","Hello World!")
}

Public void OnLoad(ConfigNode node)
{
	string myValue2 = node.GetValue("myValue");
}

 

Share this post


Link to post
Share on other sites
1 minute ago, Beale said:

Ah is this note handled by node.AddNode? 

From the pinned example:


9) Save/Load data.

 

The simplest way to save/load data is to use the KSPField attribute as listed in the Common Properties/Objects section and let KSP do all the work for you. If you needs are more complex you can use the OnSave/OnLoad methods to save to the confignode, or you can directly save to a file on disk.

 

OnSave/OnLoad methods:

Public void OnSave(ConfigNode node)
{
	node.AddValue("myValue","Hello World!")
}

Public void OnLoad(ConfigNode node)
{
	string myValue2 = node.GetValue("myValue");
}

 

Hmm Are you sure the node you add contains the data you want? What is in the SaveGames after you launched a vessel?

Share this post


Link to post
Share on other sites
3 hours ago, Beale said:

Hmm, I have updated to work with the scenario module and nodes, though it is for sure a lot easier than external save files, the revert still does not seem to work for me?

Did the changes in my pull request not work for you?  That's strange.  I just did a test, in a new sandbox game using the DLL from my pull request and no other mods:

  • Open the VAB and place a part in the editor (doesn't matter what part, but I used the Mk1 Command Pod).
  • Change the name from "Untitled Space Craft" to "[Test] Dummy" and click the save button.
  • Click Launch and check the spacecraft's name on the launchpad.  It's called "Test 1".
  • Revert to vehicle assembly.
  • Click Launch again and check the spacecraft's name on the launchpad.  It's called "Test 1" again.

(If I make another new save and do these same steps using the DLL from the latest GitHub release, the spacecraft is named "Test 2" on the second launch.)

Share this post


Link to post
Share on other sites
25 minutes ago, Wyzard said:

Did the changes in my pull request not work for you?  That's strange.  I just did a test, in a new sandbox game using the DLL from my pull request and no other mods:

  • Open the VAB and place a part in the editor (doesn't matter what part, but I used the Mk1 Command Pod).
  • Change the name from "Untitled Space Craft" to "[Test] Dummy" and click the save button.
  • Click Launch and check the spacecraft's name on the launchpad.  It's called "Test 1".
  • Revert to vehicle assembly.
  • Click Launch again and check the spacecraft's name on the launchpad.  It's called "Test 1" again.

(If I make another new save and do these same steps using the DLL from the latest GitHub release, the spacecraft is named "Test 2" on the second launch.)

Ah I have re-written entirely instead of the pull request - however the code is quite similar on save and load. Confusing why it does not seem to work.

Share this post


Link to post
Share on other sites
57 minutes ago, Beale said:

Ah I have re-written entirely instead of the pull request - however the code is quite similar on save and load. Confusing why it does not seem to work.

I was just trying out your rewritten version, but the DLL fails to load at all for me:

[ERR 12:08:02.933] AssemblyLoader: Exception loading 'ProjectManager': System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
  at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
  at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0 
  at AssemblyLoader.LoadAssemblies () [0x00000] in <filename unknown>:0 

Additional information about this exception:

 System.TypeLoadException: Could not load type 'ProjectManager.ScenarioProjectManager' from assembly 'ProjectManager, Version=1.0.6798.21835, Culture=neutral, PublicKeyToken=null'.

 System.TypeLoadException: Could not load type '<>c' from assembly 'ProjectManager, Version=1.0.6798.21835, Culture=neutral, PublicKeyToken=null'.

I'm guessing that "<>c" type in the assembly might be related to your use of lambdas, though I don't actually know.

I don't think a full rewrite is really needed, though — your old code seemed fine to me — and the rewritten version drops backward compatibility with the ProjectManager.settings file, so people's launch counts will all revert to 1 when they upgrade.

Please give my pull request a try, and maybe use it as a starting point for refactoring.

Edited by Wyzard

Share this post


Link to post
Share on other sites
1 hour ago, Wyzard said:

I was just trying out your rewritten version, but the DLL fails to load at all for me:


[ERR 12:08:02.933] AssemblyLoader: Exception loading 'ProjectManager': System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
  at (wrapper managed-to-native) System.Reflection.Assembly:GetTypes (bool)
  at System.Reflection.Assembly.GetTypes () [0x00000] in <filename unknown>:0 
  at AssemblyLoader.LoadAssemblies () [0x00000] in <filename unknown>:0 

Additional information about this exception:

 System.TypeLoadException: Could not load type 'ProjectManager.ScenarioProjectManager' from assembly 'ProjectManager, Version=1.0.6798.21835, Culture=neutral, PublicKeyToken=null'.

 System.TypeLoadException: Could not load type '<>c' from assembly 'ProjectManager, Version=1.0.6798.21835, Culture=neutral, PublicKeyToken=null'.

I'm guessing that "<>c" type in the assembly might be related to your use of lambdas, though I don't actually know.

I don't think a full rewrite is really needed, though — your old code seemed fine to me — and the rewritten version drops backward compatibility with the ProjectManager.settings file, so people's launch counts will all revert to 1 when they upgrade.

Please give my pull request a try, and maybe use it as a starting point for refactoring.

It is written for 1.3.1 so that may be the case.

But, fair reason - I will try the pull request version. Thanks for your help.

Share this post


Link to post
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.