AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Coding MM:S Plugins & SM Extensions (https://forums.alliedmods.net/forumdisplay.php?f=75)
-   -   Custom MMS Interfaces (https://forums.alliedmods.net/showthread.php?t=143412)

CrimsonGT 11-19-2010 11:51

Custom MMS Interfaces
 
I've used the normal HL2SDK Interfaces for years, but never contemplated making my own before. Since I am constantly reusing the same code in each MMS plugin I do, I figured creating some Interfaces for handling/managing Menus/UserMessages/GameEvents/etc. wouldn't be a bad idea.

I am however a little confused on what the exact setup of Interfaces is. Just from looking around, it looks like you can use

g_SMAPI->MetaFactory(INTERFACE_NAME, NULL, NULL);

to get the interface pointer on the iface you create in another plugin, but I am not sure what else I need (such as the version defines, version names, and anything else such as how to expose it to other MMS plugins once its loaded and running). I didn't see anything on the Wiki regarding this (could have sworn I did a while back) so I would like any information on doing this.

API 11-19-2010 13:30

Re: Custom MMS Interfaces
 
I am pretty sure that the interface system requires implementation of QueryInterface(). Creating a pointer to the interface is created within your plugin, then your QueryInterface() should return the pointer you create. I believe it is a simple string comparison. Let me know if you need more help, I know my explanation was kind of quick.

Keeper 11-19-2010 13:36

Re: Custom MMS Interfaces
 
Are you looking to use one binary between all of your MMS plugins so you don't have to have that code in each one? Or are you looking for your own library that you can link into each plugin so you don't have to have rehash the same code over and over again?

CrimsonGT 11-19-2010 13:54

Re: Custom MMS Interfaces
 
I am looking to create a binary file, and expose specific customs functions via interfaces that I create. I actually never thought about doing this until I saw Voogru's hat extension/MMS plugin that does this, and I realized how nice that would be.

API 11-19-2010 15:42

Re: Custom MMS Interfaces
 
An interface isn't anything fancy. Check this out, this is the file you would distribute:

IMyInterface.h
Code:

#define MYINTERFACE_VERSION "MYINTERFACE001" // Increment the version number any time you a) add a function or b) remove a function. If you neglect to do this, the virtual table will not match.

class IMyInterface
{
    public:
        // I forget if you need constructor/destructor, consider this my warning that you might need this:
        // virtual ~IMyInterface() = 0;
        virtual void FunctionA() = 0; // The "= 0" means the function is purely virtual. It MUST be overriden. Don't worry, this is shown later.
        virtual int FunctionB(int Param1, int Param2) = 0;
        virtual bool FunctionC() = 0;
};

Now in your plugin, you have to define the interface's true functionality.

MyInterface.h
Code:

class CMyInterface : public IMyInterface
{
    public:
        CInterface() {}
        ~CInterface() {}
        void FunctionA()
        {
            // Do something fancy.
        }
        int FunctionB(int P1, int P2)
        {
            return P1 + P2; // Just an example to show return value.
        }
        bool FunctionC()
        {
            // Do something fancy.
            return true; // or false, :P
        }
};

extern CMyInterface g_MyInterface;

You're also going to need to put this in a CPP file:
Code:

CMyInteface g_MyInterface;
Then you need to implement the QueryInterface, I think it is an optional member for the metamod plugin class:
Code:

void *MyPlugin::QueryInterface(const char *version_string)
{
    if(FStrEq(version_string, MYINTERFACE_VERSION))
    {
        return (void*)g_MyInterface;
    }
    return (void*)0;
}

The MetaFactory function actually calls every QueryInterface and uses the non-null result.

Something like this for any plugin that tries to use MyInterface...
Code:

#include "IMyInterface.h"

...

IMyInterface *theInterface = (IMyInterface*)MetaFactory(MYINTERFACE_VERSION);
if(theInterface)
{
    theInterface->FunctionA();
    int result 1 = theInterface->FunctionB(1, 2);
    bool result2 = theInterface->FunctionC();
}
else
{
    Msg("Failed to find interface!\n");
}

Good luck.

CrimsonGT 11-19-2010 17:03

Re: Custom MMS Interfaces
 
I was just looking for a recommendation as far as another MMS plugin that used a custom iface, but that is perfect, thank you.

Chrisber 11-20-2010 11:22

Re: Custom MMS Interfaces
 
Hi,
one thing I don't understand is why you use different interface versions? If you, for example, have BLA_VER002, do you instantiate CBla001 and CBla002 and then pass that one that fits the version string? Or do I misunderstand something?

Thanks!

API 11-20-2010 16:07

Re: Custom MMS Interfaces
 
The version number ensures proper virtual function index mapping. For example, if I released a new version of my interface with new functions, lets say FunctionD and FunctionE:

Code:

#define MYINTERFACE_VERSION "MYINTERFACE002"

class IMyInterface
{
    public:
        // I forget if you need constructor/destructor, consider this my warning that you might need this:
        // virtual ~IMyInterface() = 0;
        virtual void FunctionA() = 0; // The "= 0" means the function is purely virtual. It MUST be overriden. Don't worry, this is shown later.
        virtual int FunctionB(int Param1, int Param2) = 0;
        virtual bool FunctionC() = 0;
        // The following functions were added in version 2 of the interface.
        virtual void FunctionD() = 0;
        virtual void FunctionE() = 0;
};

Now, if someone was using a plugin that required FunctionD and FunctionE, but it hasn't been updated, then their version 001 will not match the instance of 002 that exists. The plugin using your interface would not get a valid result from the meta factory. Here is an example.
Code:

if(StrEqual("INTERFACE_001", "INTERFACE_002")) {
// not true
}
else
{
    return NULL;
}

This is a good behavior. Without matching versions there is no way to ensure that the virtual table matches, and any calls to FunctionD or FunctionE would result in crashes.

BAILOPAN 11-20-2010 16:28

Re: Custom MMS Interfaces
 
FWIW, SourceMod exposes its extension system through MM:S, so you can use MM:S plugins as if they were also extensions.

Chrisber 11-21-2010 07:10

Re: Custom MMS Interfaces
 
Thanks! And when exactly I need to add a pure virtual destructor? If I'm informed correctly, it is not possible to instantiate abstract classes, so it shouldn't matter if it has a constructor/destructor?!


All times are GMT -4. The time now is 05:28.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.