1. I'm working on an extension that will require hooks to players and server, but also do stuff that plugins can't do. I'm also using namespaces and assemblies that aren't whitelisted so making a standalon plugin is out the question.
    I was wondering if there is a way to either get hooks in my extension in some class like i would in a plugin, or load a plugin soley for that specific extension and communicate between the two?
    How can i do this? do is use LoadPluginWatchers() method and if so how?

    Kind regards,
    Sililia
     
  2. You need use HookMethodAttribute("HookName") on method in plugin class.
     
  3. I don't think i understand what you mean, could you give a simple example of how i would do that?
     
  4. Wulf

    Wulf Community Admin

    The RustCore.cs is a plugin in the Oxide.Rust extension, this would be an example of what you want to do.
     
  5. upload_2018-5-14_19-29-34.png

    This is a test class I've made. Only problem is that it doesn't put any of the messages in the console. Do i inherit CovalencePlugin or CSPlugin as is in the RustCore.cs.
    What's the difference?
     
  6. Wulf

    Wulf Community Admin

    All plugins in extensions are CSPlugin, they do not have any concept of Covalence or other plugins types. RustCore.cs would be an example of what you should follow, don't try to make it like a normal plugin. Your namespace should also match your extension's namespace, do not use Oxide.Plugins.
     
  7. So i have gotten hooks to work on the plugin inside the extension. Is there a way to accept commands from players ingame? '[Command("test")]' doesn't seem to work.
     
  8. Wulf

    Wulf Community Admin

    You'd have to manually register the command using the command API; attributes are game-specific and only available in those types of plugins.
     
  9. Any good examples to look at to get the gist of command API; thanks for all the help BTW incredibly useful
     
  10. Wulf

    Wulf Community Admin

    Not on hand, but look for AddChatCommand and AddConsoleCommand. For an extension, you'd need to get the Commands library as well as it isn't already available like in RustPlugin and such.
     
  11. So I've been looking how the command system is implemented on the rust extension.From this i have a few questions, I've noticed classes such as the RustConsolePlayer, RustCommandSystem, Command, IPlayer are all in the extension rather than Oxide itself. You mentioned that "All plugins in extensions are CSPlugin, they do not have any concept of Covalence or other plugins types." which I take means that my extension will not know of the existence of the rust extension correct? If so, will that mean that i will have to implement these classes myself?
     
  12. Wulf

    Wulf Community Admin

    Unless you manually reference any of the game or Covalence libraries, your extension will not have access to those. You'd need to get the library for the ones you want in order to use them.
     
  13. I've added the Oxide.Rust as a reference to my project which gives me access to some of the classes. I've made a function which iterates through a given plugin class and looks for console and chat command attributes (code below).
    PlayerManager is an instance of a plugin, whenever the function finds a command it will try registering it with the core, the only problem is that it seems that there is an object that the Command class tries to use that's null. My hunch is that it's inside the CanOverrideCommand() but i cant check this since i can't debug the core. Any idea what i may be doing wrong?

    Exception
    Object reference not set to an instance of an object
    Failed to load extension Oxide.Ext.Manager (NullReferenceException: Object reference not set to an instance of an object)
    at Oxide.Ext.Manager.VmeCommands.RegisterPluginCommands () [0x00000] in <filename unknown>:0
    at Oxide.Ext.Manager.VmeCommands..ctor () [0x00000] in <filename unknown>:0
    at Oxide.Ext.Manager.VipManager.Load () [0x00000] in <filename unknown>:0

    Code:
                // Iterate through each method from PlayerManager
                foreach (MethodInfo method in typeof(PlayerManager).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
                {
                    // Get all methods with the "Command" attribute
                    var attributes = method.GetCustomAttributes(typeof(ConsoleCommandAttribute), true);                // Go to next if there are no attributes
                    if (attributes.Length > 0)
                    {                    if (attributes[0] is ConsoleCommandAttribute consoleAttr)
                        {
                ExtManager.Logger.Write(Core.Logging.LogType.Info, $"VME: Console command found!");
                            Cmd.AddConsoleCommand(consoleAttr.Command, PlayerManagerPlugin, method.Name);
                            ExtManager.Logger.Write(Core.Logging.LogType.Info, $"VME: Console command '{consoleAttr.Command}' has been bound");
                        }
                    }                attributes = method.GetCustomAttributes(typeof(ChatCommandAttribute), true);
                    if (attributes.Length <= 0) continue;
                    
                    if (attributes[0] is ChatCommandAttribute attribute)
                    {
                        ExtManager.Logger.Write(Core.Logging.LogType.Info, $"VME: Chat command found!");
                        Cmd.AddChatCommand(attribute.Command, PlayerManagerPlugin, method.Name);
                        ExtManager.Logger.Write(Core.Logging.LogType.Info, $"VME: Chat command '{attribute.Command}' has been bound");
                    }
                }
     
  14. I don't understand why, but inheriting CSPlugin and calling its constructor fixed this. Perhaps explain explain that it initialises that's required to register a command?
     
  15. Wulf

    Wulf Community Admin

    CSPlugin is what extensions should be using.