Jump to content

Null reference exception with a plugin I'm adapting.


Recommended Posts

I am trying to edit the BeamedPowerStandalone mod to take its managed resource from a config file.

I've got this code:

public class WirelessReceiver : PartModule
{
    static ConfigNode setting = ConfigNode.Load(KSPUtil.ApplicationRootPath + "GameData/BeamedPowerStandalone/Settings.cfg");
    private static string ManagedResource = setting.GetValue("BPManagedResource");
	OTHER STUFF HERE
	readonly int ResourceHash = PartResourceLibrary.Instance.GetDefinition(ManagedResource).id;
	OTHER STUFF HERE
	if (HighLogic.CurrentGame.Parameters.CustomParams<BPSettings>().BackgroundProcessing == false)
	{
    	this.part.RequestResource(ResourceHash, -(double)ReceivedPower * TimeWarp.fixedDeltaTime);
	}
	OTHER STUFF HERE
}

Also please ignore that weird indent from line 5 onwards; its not in the actual code.

So the idea is that the code reads that file, takes the value BPManagedResource, and then sets the ResourceHash to that value. ResourceHash is then used with the RequestResource method to add the appropriate amount of resources. 

 

This is the error I'm getting:

NullReferenceException: Object reference not set to an instance of an object
  at PartResourceDefinitionList.get_Item (System.String name) [0x00000] in <4b449f2841f84227adfaad3149c8fdba>:0 
  at PartResourceLibrary.GetDefinition (System.String name) [0x00000] in <4b449f2841f84227adfaad3149c8fdba>:0 
  at BeamedPowerStandalone.WirelessSource..ctor () [0x00057] in <d68e19269a5b46ef93c5c11353a0a255>:0 

 

What did I mess up this time? It looks like ResourceHash hasn't been set to anything for some reason?

Link to comment
Share on other sites

If I was debugging this, I would check whether the ManagedResource string is null. I can see a path for that to cause that exception, but not anything else so far.

BTW, the game will automatically load all config nodes from all .cfg files on startup. You can access them via GameDatabase.Instance.GetConfigNode/Nodes instead of calling ConfigNode.Load again yourself:

(And you can use ConfigNode.LoadObjectFromConfig to transfer the values from a node into the properties of an object for convenience. Here's an example of some code that does that:

Edited by HebaruSan
Link to comment
Share on other sites

6 hours ago, HebaruSan said:

If I was debugging this, I would check whether the ManagedResource string is null. I can see a path for that to cause that exception, but not anything else so far.

How would you check that? I don't see any errors in Visual Studio. I'll check the log to see if it's recorded anywhere.

 

6 hours ago, HebaruSan said:

BTW, the game will automatically load all config nodes from all .cfg files on startup. You can access them via GameDatabase.Instance.GetConfigNode/Nodes instead of calling ConfigNode.Load again yourself:

THANK YOU! Seriously, ConfigNode.load has been brutal to me. However, I didn't see BPManagedResource in the config cache, which suggests an error to me.

Link to comment
Share on other sites

11 minutes ago, KspNoobUsernameTaken said:

How would you check that? I don't see any errors in Visual Studio. I'll check the log to see if it's recorded anywhere.

Just a simple guard/check before using it:

if (ManagedResource != null)
{
    // Do the rest of the stuff
}
11 minutes ago, KspNoobUsernameTaken said:

THANK YOU! Seriously, ConfigNode.load has been brutal to me. However, I didn't see BPManagedResource in the config cache, which suggests an error to me.

Yeah, you'll want to get a reference to the parent config node, not a specific key-value pair. E.g. if the file says this:

BEAMEDPOWERSETTINGS
{
    BPManagedResource = whatever
}

Then you'd retrieve the "BEAMEDPOWERSETTINGS" node and check its child values.

If you only had the middle line in the file, that might explain why it was failing to load for you.

Edited by HebaruSan
Link to comment
Share on other sites

51 minutes ago, HebaruSan said:

Just a simple guard/check before using it:

if (ManagedResource != null)
{
    // Do the rest of the stuff
}

Yeah, you'll want to get a reference to the parent config node, not a specific key-value pair. E.g. if the file says this:

BEAMEDPOWERSETTINGS
{
    BPManagedResource = whatever
}

Then you'd retrieve the "BEAMEDPOWERSETTINGS" node and check its child values.

If you only had the middle line in the file, that might explain why it was failing to load for you.

So this is what I had:

BPSettings
{
    BPManagedResource = ThermalPower
}

Then I would do ManagedResource = settings.BPManagedResource.GetValue?

Link to comment
Share on other sites

2 minutes ago, KspNoobUsernameTaken said:

So this is what I had:

BPSettings
{
    BPManagedResource = ThermalPower
}

Then I would do ManagedResource = settings.BPManagedResource.GetValue?

I'd probably start with something like this:

var node = GameDatabase.Instance.GetConfigNode("BPSettings");
if (node.TryGetValue("BPManagedResource", out string ManagedResource)
       && !string.IsNullOrEmpty(ManagedResource))
{
    MonoBehaviour.print($"Got resource name: {ManagedResource}");
    // Use ManagedResource here
}
else
{
    MonoBehaviour.print($"Failed to get resource name");
}

That way you can confirm whether it's actually being loaded as expected.

Link to comment
Share on other sites

Posted (edited)
18 minutes ago, HebaruSan said:
var node = GameDatabase.Instance.GetConfigNode("BPSettings");
if (node.TryGetValue("BPManagedResource", out string ManagedResource)
       && !string.IsNullOrEmpty(ManagedResource))
{
    MonoBehaviour.print($"Got resource name: {ManagedResource}");
    // Use ManagedResource here
}
else
{
    MonoBehaviour.print($"Failed to get resource name");
}

So I tried adding this to a new Testing.cs file and got about 3 dozen errors;

for reference, this is the entire file:

using System;
using UnityEngine;
namespace BeamedPowerStandalone
{
    public class Testing : MonoBehaviour
	{
        ConfigNode node = GameDatabase.Instance.GetConfigNode("BPSettings");
        static string ManagedResource;
        if (node.TryGetValue("BPManagedResource", out string ManagedResource) && !string.IsNullOrEmpty(ManagedResource))
        {
            MonoBehaviour.print($"Got resource name: {ManagedResource}");
    // Use ManagedResource here
        }
        else
        {
            MonoBehaviour.print($"Failed to get resource name");
        }
	}
}

I clearly did not understand what you meant, so could you clarify?

 

Ok so I think I messed up the .csproj file... I'll come back to this later after fixing  that.

Edited by KspNoobUsernameTaken
Link to comment
Share on other sites

1 minute ago, HebaruSan said:

Don't put ordinary procedural code directly in a class body. It needs to be inside a method (member function). I assumed you already had that in your "OTHER STUFF HERE" lines.

Ohhh... ok, understood. I'll correct that when trying again. I didn't realise that you need to put stuff in functions for it to run. Thanks. 

Link to comment
Share on other sites

So fairly sure its not, in fact, getting the resource name, but weirder still it isn't printing to the log at all.

Code attached below, this is in a file called "Testing.cs"

using System;
using UnityEngine;
namespace BeamedPowerStandalone
{
    [KSPAddon(KSPAddon.Startup.AllGameScenes, false)]
    public class Testing : MonoBehaviour
    {
        string ManagedResource = "";
        public void Start()
        {

            var node = GameDatabase.Instance.GetConfigNode("BPSettings");
            if (!node.TryGetValue("BPManagedResource", value: ref ManagedResource) || string.IsNullOrEmpty(ManagedResource))
            {
                MonoBehaviour.print($"Failed to get resource name");
            }
            else

            {
                MonoBehaviour.print($"Got resource name: {ManagedResource}");
            }
        }
    }
}

 

Link to comment
Share on other sites

32 minutes ago, KspNoobUsernameTaken said:

@HebaruSan

It looks like Monobehaviour.print just isn't working? This seems like a difference issue entirely.

At some level, you must realize that it's extremely unlikely that a core Unity function just randomly stopped working.

A much more likely possibility is that your code isn't running.

Link to comment
Share on other sites

Just now, HebaruSan said:

At some level, you must realize that it's extremely unlikely that a core Unity function just randomly stopped working.

A much more likely possibility is that your code isn't running.

I get that. I'm just not sure why it isn't running? I'll take a look at some other mod and fix it. I didn't mean to imply the function itself isn't working, but rather that the code it was in was not working.  

Link to comment
Share on other sites

Apply standard debugging techniques. Retrace your steps since the last time it was working. Find the most recent thing that did work, then update it incrementally and confirm it's working at each step. Quadruple check your build/install so you're not running an old DLL. Etc.

Link to comment
Share on other sites

Finally, some 'progress'. This code produces NREs as soon as I reach KSC. So at least it is running for sure:

using System;
using UnityEngine;
namespace BeamedPowerStandalone
{
    [KSPAddon(KSPAddon.Startup.FlightEditorAndKSC, false)]
    public class Testing : MonoBehaviour
    {
        string ManagedResource = "";
        public void Update()
        {

            var node = GameDatabase.Instance.GetConfigNode("BPSettings");
            node.TryGetValue("BPManagedResource", ref ManagedResource);
            if (string.IsNullOrEmpty(ManagedResource) || !node.TryGetValue("BPManagedResource", ref ManagedResource))
            {
                Debug.Log($"Failed to get resource name");
            }
            else
            {
                Debug.Log($"Got resource name: {ManagedResource}");
            }
        }
    }
}

 

Link to comment
Share on other sites

Now this is interesting: I added this line just before the Debug.log($Got resource name):

Debug.Log("ManagedResouceNameAcquired");

I would expect this to cause log entries like so:

Null reference execption

ManagedResouceNameAcquired

Null reference exception

... continued forever.

 

Instead, only the NREs show up, suggesting they are related to something different.

 

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