Null Reference with Config.ReadObject (I'm officially insane)Solved
_config = Config.ReadObject<Configuration>();

 

The line above, which seems to be a standard in everyone's plugin, is breaking my plugin and sanity. 
_config is always null if I have a config file already in the oxide/config directory.  If not, my plugin works perfectly using config defaults.

I have to assume that my config file isn't being read, likely due to formatting possibly, but I can't find any documentation on formatting standards. Compared to other languages, C# seems border-line impossible to trouble-shoot.. error messages are the furthest thing from clear or helpful (my error response is below). 
15:59 [Info] GroupWatch was compiled successfully in 302ms
15:59 [Error] Could not initialize plugin 'GroupWatch v0.0.8' (NullReferenceException: Object reference not set to an instance of an object)
  at Oxide.Plugins.GroupWatch.LoadConfig () [0x00029] in <a9d7b4c1f6a94bba801764eca8477443>:0 
  at Oxide.Core.Plugins.Plugin.HandleAddedToManager (Oxide.Core.Plugins.PluginManager manager) [0x0000f] in <99d545163fdd4d57a562df7989f2ca0a>:0 
  at Oxide.Core.Plugins.CSPlugin.HandleAddedToManager (Oxide.Core.Plugins.PluginManager manager) [0x00000] in <99d545163fdd4d57a562df7989f2ca0a>:0 
  at Oxide.Plugins.CSharpPlugin.HandleAddedToManager (Oxide.Core.Plugins.PluginManager manager) [0x00000] in <cc99cb05b42e4ea494cdf294badea406>:0 
  at Oxide.Plugins.CovalencePlugin.HandleAddedToManager (Oxide.Core.Plugins.PluginManager manager) [0x000b3] in <cc99cb05b42e4ea494cdf294badea406>:0 
  at Oxide.Core.Plugins.PluginManager.AddPlugin (Oxide.Core.Plugins.Plugin plugin) [0x00027] in <99d545163fdd4d57a562df7989f2ca0a>:0 
  at Oxide.Core.OxideMod.PluginLoaded (Oxide.Core.Plugins.Plugin plugin) [0x00035] in <99d545163fdd4d57a562df7989f2ca0a>:0 
15:59 [Info] Rolling back plugin to last good version: GroupWatch
15:59 [Info] Loaded plugin Group Watch v0.0.8 by Rustonauts​

My config file looks ok (below).

{
  "exists": true,
  "WatchGroups": [
    {
      "groupName": "example-group",
      "enabled": true,
      "responseCmd": null,
      "responseKit": "example-kit"
    },
    {
      "groupName": "example-group-6",
      "enabled": false,
      "responseCmd": "Puts('hello')",
      "responseKit": "example-kit2"
    }
  ]
}​

My entire plugin is below,

using Newtonsoft.Json;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;


namespace Oxide.Plugins
{
    [Info("Group Watch", "Rustonauts", "0.0.8")]
    [Description("Allows server owners to execute commands once a player is added to specific groups.")]
    class GroupWatch : CovalencePlugin
    {
        
        private Configuration _config;
        

        private void Init()
        {
            Puts("Initializing...");
        }


        protected override void LoadConfig()
        {
            base.LoadConfig();

            try
            {
                _config = Config.ReadObject<Configuration>();
                 if (_config == null) throw new Exception();
                 Puts("Config loaded");
            }
            catch
            {
                Puts("config error, create defaults");
                LoadDefaultConfig();
            }
        }



        protected override void LoadDefaultConfig()
        {
            _config = new Configuration();
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(_config, true);
        }



        private class WatchGroupSettings
        {
            public string groupName;
            public bool enabled;
            public string responseCmd;
            public string responseKit;
        }


        private class WatchGroup
        {
            public string groupName;
            public bool enabled;
            public string responseCmd;
            public string responseKit;


            public WatchGroup(WatchGroupSettings settings)
            {
                groupName = settings.groupName;
                enabled = settings.enabled;
                responseCmd = settings.responseCmd;
                responseKit = settings.responseKit;
            }    
        }

 
        private class Configuration
        {
            public bool exists { get; set; } = true;

            public IEnumerable<WatchGroup> WatchGroups { get; set; } = new[]
            {
                new WatchGroup(new WatchGroupSettings()
                {
                    groupName = "example-group",
                    enabled = true,
                    responseCmd = null,
                    responseKit = "example-kit"
                }),

                new WatchGroup(new WatchGroupSettings()
                {
                    groupName = "example-group-6",
                    enabled = false,
                    responseCmd = "Puts('hello')",
                    responseKit = "example-kit2"
                })

            };

        }




        void OnUserGroupAdded(string id, string groupName)
        {
            Puts($"Player added to group");

            foreach (var group in _config.WatchGroups)
            {
                //Puts($"watched: \"{group.groupName}\".");
            }
        }

       
    }
}


Any suggestions would be greatly appreciated.   Thank you in advance!

What does your config file have in it?

{
  "exists": true,
  "WatchGroups": [
    {
      "groupName": "example-group",
      "enabled": true,
      "responseCmd": null,
      "responseKit": "example-kit"
    },
    {
      "groupName": "example-group-6",
      "enabled": false,
      "responseCmd": "Puts('hello')",
      "responseKit": "example-kit2"
    }
  ]
}

nothing eh?  Feels like the config file looks fine.

Hey, I meant to tell you that I'm not having any issues when using it.

GroupWatch was compiled successfully in 1581ms
Unloaded plugin Group Watch v0.0.8 by Rustonauts
[Group Watch] Config error, loaded defaults
Loaded plugin Group Watch v0.0.8 by Rustonauts

Do you have any other plugins loaded?

I appreciate the time you're taking here.  When you have no config file, no errors.  It's only when trying to read an existing config file does the error occur.  I'm now doing a try/catch in my LoadConfig method to prevent the exception, but you'll see in the console "config error, create defaults".

I tried without a config and loading existing, no issues.

OgAlNbWQxxw2zGk.png Wulf

I tried without a config and loading existing, no issues.

hm.. you should see in the console Initializiging.... and then saying that there was an error, creating defaults.  

In any case, I've removed the try/catch so that it actually throws an error.  Code updated below.  It says somethign about instantiating null reference.



using Newtonsoft.Json;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;


namespace Oxide.Plugins
{
    [Info("Group Watch", "Rustonauts", "0.0.8")]
    [Description("Allows server owners to execute commands once a player is added to specific groups.")]
    class GroupWatch : CovalencePlugin
    {
       

        private Configuration _config;
        

        private void Init()
        {
            Puts("Initializing...");
        }


        protected override void LoadConfig()
        {
            base.LoadConfig();

            _config = Config.ReadObject<Configuration>();
            Puts("Config loaded");
        }



        protected override void LoadDefaultConfig()
        {
            _config = new Configuration();
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(_config, true);
        }



        private class Kit
        {
            public string name;

        }



        private class WatchGroupSettings
        {
            public string groupName;
            public bool enabled;
            public string responseCmd;
            public string responseKit;
        }


        private class WatchGroup
        {
            public string groupName;
            public bool enabled;
            public string responseCmd;
            public string responseKit;


            public WatchGroup(WatchGroupSettings settings)
            {
                groupName = settings.groupName;
                enabled = settings.enabled;
                responseCmd = settings.responseCmd;
                responseKit = settings.responseKit;
            }    
        }

 
        private class Configuration
        {
            public bool exists { get; set; } = true;

            public IEnumerable<WatchGroup> WatchGroups { get; set; } = new[]
            {
                new WatchGroup(new WatchGroupSettings()
                {
                    groupName = "vip1",
                    enabled = true,
                    responseCmd = null,
                    responseKit = "example-kit"
                }),

                new WatchGroup(new WatchGroupSettings()
                {
                    groupName = "discord-member",
                    enabled = true,
                    responseCmd = "Puts('hello')",
                    responseKit = "example-kit2"
                })

            };


            // public IEnumerable<string> ActionKits { get; set; } = new[]
            // {
            //     {
            //         name = "DiscordMember",
            //     }
            // };

        }


        // void OnEntityEnter(TriggerBase trigger, BaseEntity entity)
        // {
        //     if(entity.name == "assets/prefabs/player/player.prefab")
        //     {
        //         Puts("Entity entered");
        //         Puts(trigger.trigger);
        //         Puts(entity.name);
        //     }
            
        // }

        // void OnUserGroupAdded(string id, string groupName)
        // {
        //     Puts($"Player added to group");

        //     //iterating through the watch groups in the config file
        //     foreach (var group in _config.WatchGroups)
        //     {
        //         //qualifying group name from config: enabled and matched
        //         if(group.enabled && group.groupName == groupName)
        //         {
        //             //iterate through commands to execute


        //             //iterate through kits to give
        //             if(Kits)
        //             {
        //                 var pluginKits = new Kits;
        //                 var theKit;

        //                 foreach(actionKitName in _config.ActionKits)
        //                 {
        //                     //give player kit
        //                     theKitdfs = pluginKits.GetKitInfo(actionKitName)
        //                 }
        //             }
                    

        //             Puts($"match with {groupName}");
        //         }
                
        //     }
        // }

       
    }
}
Failed to initialize plugin 'MonumentLock v1.1.5' (NullReferenceException: Object reference not set to an instance of an object)
  at Oxide.Core.Plugins.CSPlugin.OnCallHook (System.String name, System.Object[] args) [0x000fb] in <bae5f1223fce49c493b01571c99dce02>:0 
  at Oxide.Core.Plugins.CSPlugin.HandleAddedToManager (Oxide.Core.Plugins.PluginManager manager) [0x00043] in <bae5f1223fce49c493b01571c99dce02>:0 

This is the error message I receive when trying to my plugin.  The line that throws this error is

_config = Config.ReadObject<Configuration>();

My class looks like 

private class Configuration
        {
            [JsonProperty(PropertyName = "Does this monument exist?")]
            public bool exists { get; set; } = true;

            [JsonProperty(PropertyName = "How many non-looting seconds do we want to keep a monument locked for (600 = 10 min)?")]
            public int lock_timer { get; set; } = 600;

            [JsonProperty(PropertyName = "Will there be a max timer (regardless of how active player is)?")]
            public bool enable_max_timer { get; set; } = false;

            [JsonProperty(PropertyName = "How many seconds is max timer (1200 = 20 min)?")]
            public int max_timer { get; set; } = 1200;

            [JsonProperty(PropertyName = "When a player enters a locked monument, do we lock their looting abilities?")]
            public bool lock_looting { get; set; } = true;

            [JsonProperty(PropertyName = "When a player enters a locked monument, do we lock their card swiping abilities?")]
            public bool cancel_cards { get; set; } = true;

            [JsonProperty(PropertyName = "Do we want this plugin to broadcast to the server when a monument is locked?")]
            public bool enable_broadcasting { get; set; } = true;


            public List<Monument> Monuments = new List<Monument>{};
        }


change WatchGroupSettings to a struct instead of class

        private struct WatchGroupSettings
        {
            public string groupName;
            public bool enabled;
            public string responseCmd;
            public string responseKit;
        }​

oh
my
god

thank you!!

Locked automatically