Vice City: Multiplayer

Server Development => Community Plugins => Topic started by: hotdogcat on October 17th, 2014, 12:24 AM

Title: Introduction to the Plugin SDK
Post by: hotdogcat on October 17th, 2014, 12:24 AM
Note: i just imported this documentation from old forum, so credits goes to stormeus


One of the major new features available in the 0.4 server is the plugin SDK. Any user can now use an official SDK header to create plugins that can be used to interact with the server, clients, game world and other plugins.

The current plugin SDK can be found here:
https://bitbucket.org/stormeus/0.4-squirrel/src/3a1c0e0bf0ed6760455c14ccf684e38346443cd1/VCMP.h?at=master



Creating a Loadable Plugin
The VC:MP server expects the existence of a special exported function, VcmpPluginInit, to exist in a plugin in order to be able to load one. As part of this function, the server will pass a set of callable functions, a structure for the plugin to set the callbacks it accepts, and a structure for the plugin to set information about itself.

The structure of VcmpPluginInit is as follows:
Code: [Select]
#ifdef WIN32
#define EXPORT __declspec(dllexport)
#else
#define EXPORT
#endif

extern "C" EXPORT unsigned int VcmpPluginInit( PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo )
{
    return 1;
}




Setting a Callback
To receive callbacks from the server, you need to create a function in the same format as the defined type of the callback:

Code: [Select]
typedef int (*SDK_OnInitServer) (void);
typedef void (*SDK_OnShutdownServer) (void);
typedef void (*SDK_OnFrame) (float fElapsedTime);
typedef void (*SDK_OnPlayerConnect) (int nPlayerId);
typedef void (*SDK_OnPlayerDisconnect) (int nPlayerId, int nReason);
typedef void (*SDK_OnPlayerBeginTyping) (int nPlayerId);
typedef void (*SDK_OnPlayerEndTyping) (int nPlayerId);
typedef int (*SDK_OnPlayerRequestClass) (int nPlayerId, int nOffset);
typedef int (*SDK_OnPlayerRequestSpawn) (int nPlayerId);
typedef void (*SDK_OnPlayerSpawn) (int nPlayerId);
typedef void (*SDK_OnPlayerDeath) (int nPlayerId, int nKillerId, int nReason, int nBodyPart);
typedef void (*SDK_OnPlayerUpdate) (int nPlayerId, int nUpdateType);
typedef int (*SDK_OnPlayerRequestEnter) (int nPlayerId, int nVehicleId, int nSlotId);
typedef void (*SDK_OnPlayerEnterVehicle) (int nPlayerId, int nVehicleId, int nSlotId);
typedef void (*SDK_OnPlayerExitVehicle) (int nPlayerId, int nVehicleId);
typedef int (*SDK_OnPickupClaimPicked) (int nPickupId, int nPlayerId);
typedef void (*SDK_OnPickupPickedUp) (int nPickupId, int nPlayerId);
typedef void (*SDK_OnPickupRespawn) (int nPickupId);
typedef void (*SDK_OnVehicleUpdate) (int nVehicleId, int nUpdateType);
typedef void (*SDK_OnVehicleExplode) (int nVehicleId);
typedef void (*SDK_OnVehicleRespawn) (int nVehicleId);
typedef void (*SDK_OnObjectShot) (int nObjectId, int nPlayerId, int nWeapon);
typedef void (*SDK_OnObjectBump) (int nObjectId, int nPlayerId);
typedef int (*SDK_OnPublicMessage) (int nPlayerId, const char* pszText);
typedef int (*SDK_OnCommandMessage) (int nPlayerId, const char* pszText);
typedef int (*SDK_OnPrivateMessage) (int nPlayerId, int nTargetId, const char* pszText);
typedef int (*SDK_OnInternalCommand) (unsigned int uCmdType, const char* pszText);
typedef int (*SDK_OnLoginAttempt) (char* pszPlayerName, const char* pszUserPassword, const char* pszIpAddress);
typedef void (*SDK_OnEntityPoolChange) (int nEntityType, int nEntityId, unsigned int bDeleted);
typedef void (*SDK_OnKeyBindDown) (int nPlayerId, int nBindId);
typedef void (*SDK_OnKeyBindUp) (int nPlayerId, int nBindId);
typedef void (*SDK_OnPlayerAwayChange) (int nPlayerId, unsigned int bNewStatus);
typedef void (*SDK_OnPlayerSpectate) (int nPlayerId, int nTargetId);
typedef void (*SDK_OnPlayerCrashReport) (int nPlayerId, const char* pszReport);
typedef void (*SDK_OnServerPerformanceReport) (int nNumStats, const char** ppszDescription, unsigned long long* pnMillisecsSpent);

For example, to create a callback for OnPublicMessage:
Code: [Select]
typedef int (*SDK_OnPublicMessage) (int nPlayerId, const char* pszText);

You would need to create a function like so:
Code: [Select]
int MyOnPublicMessage (int nPlayerId, const char* pszText)
{
    return 1;
}

void functions need not return anything (and should not), whereas callbacks with a return type expect a value to be returned, and will react differently according to their return values. For example, returning 0 in OnPublicMessage will reject a given chat message and essentially mute it. Returning 1 will send it to other players if no other plugins suppress it.

To have the server recognize the callback and make use of it, set it in VcmpPluginInit:
Code: [Select]
extern "C" EXPORT unsigned int VcmpPluginInit( PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo )
{
    pluginCalls->OnPublicMessage = MyOnPublicMessage;
    return 1;
}



Using Plugin Functions
Using plugin functions is easier still than dealing with callbacks. To use a function, you can simply make a direct call to a function in the pluginFuncs struct:

Code: [Select]
extern "C" EXPORT unsigned int VcmpPluginInit( PluginFuncs* pluginFuncs, PluginCallbacks* pluginCalls, PluginInfo* pluginInfo )
{
    pluginFuncs->SetServerName("My VC:MP Server");
    return 1;
}
Title: Re: Introduction to the Plugin SDK
Post by: Sebastian on October 28th, 2014, 05:03 PM
Quote from theahmadzai on October 28th, 2014, 05:00 PM
I think so only developers may post SDK's etc.. If a newbie comes and search related to SDK and he see your rank as a member and Your post about development..He won't trust the source.
Since it is stickied, they should trust the source. ;)
Title: Re: Introduction to the Plugin SDK
Post by: ysc3839 on November 15th, 2014, 03:22 PM
I ported this to the VCMP wiki. :D
http://wiki.vc-mp.org/wiki/Introduction_to_the_Plugin_SDK
Title: Re: Introduction to the Plugin SDK
Post by: jWeb on January 2nd, 2017, 02:59 AM
Sorry for the bump. But after the last updates, people that create plugins must also include the SDK version for which their plugin was compiled. Otherwise the server will reject your plugin.

To do that, you should add have this somewhere before you return out of the `VcmpPluginInit()` function:
Code: [Select]

pluginInfo->apiMajorVersion = PLUGIN_API_MAJOR;
pluginInfo->apiMinorVersion = PLUGIN_API_MINOR;