Raised This Month: $12 Target: $400
 3% 

[TUT] Plugin API


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 07-11-2006 , 17:16   [TUT] Plugin API
Reply With Quote #1

Before you get into this, please note that this tutorial assumes you are intermediate level in Pawn or higher. Beginners should avoid this as it may confuse them or not make sense.

API stands for application programming interface. But what is an API? Basically it's an interface that allows multiple programs/scripts to trade data and perform the same functions without having direct access to each other.

There is API functionality in AMXX plugins, implemented through a set of natives. The following natives, built into the core, allow API capabilities:
  • CreateMultiForward
  • CreateOneForward
  • ExecuteForward
  • PrepareArray
  • DestroyForward

But what are they used for? Well, let's take a look at an example and then pull it apart to figure out how it works. Please keep in mind that an API is designed for multiple plugins, so every example will be 2 individual scripts instead of 1 (although it's possible to put them both in one)

Code:
#include <amxmodx> new Float:g_flDelay public plugin_init() {     register_plugin("API Test - Core","1.0","Hawk552")         g_flDelay = random_float(0.1,0.5)     set_task(g_flDelay,"fnDoForward") } public fnDoForward() {     new iForward = CreateMultiForward("plugin_init_delay",ET_IGNORE,FP_FLOAT),iReturn     if(iForward < 0)         return log_amx("Forward could not be created.")         if(!ExecuteForward(iForward,iReturn,g_flDelay))         return log_amx("Could not execute forward.")             return DestroyForward(iForward) }

Code:
#include <amxmodx> public plugin_init()     register_plugin("API Test - Attachment","1.0","Hawk552")     public plugin_init_delay(Float:flDelay)     log_amx("Forward executed %f seconds after plugin_init.",flDelay)

Now, let's pick these two apart.

In the first script, the important part starts at fnDoForward. What we see is:

Code:
new iForward = CreateMultiForward("plugin_init_delay",ET_IGNORE,FP_FLOAT)

CreateMultiForward and CreateOneForward (which will be addressed later) return handles that can be used for ExecuteForward and DestroyForward.
  • NOTE: Difference between CreateMultiForward and CreateOneForward: multi accepts a return value and you must specify upon which condition it'll stop. Multi also sends to all plugins that have a public function after the name of const name[], as shown below. CreateOneForward requires a plugin id, and automatically ignores the return value (although you can still pass it byref)

But as for the parameters:

const name[] - this is the name of the public function you want to call from whatever plugin(s) specified
stop_type - this is what the plugin should obey in terms of stopping. For example, if you register a client command "kill" and then return PLUGIN_HANDLED, it'll stop right there. This parameter allows you to specify whether or not it will stop there, and whether or not the return value from plugins called matters. The possibilities are here:

Code:
#define ET_IGNORE        0    //ignore return val #define ET_STOP            1    //stop on PLUGIN_HANDLED #define ET_STOP2        2    //same, except return biggest #define ET_CONTINUE        3    //no stop, return biggest

In this case, we use ET_IGNORE because plugin_init never stops calling, despite what plugins return (which is why it's useless to return PLUGIN_CONTINUE/_HANDLED in plugin_init), and we want to duplicate that functionality.

... - This is where the parameters of the header of the function called should be specified. In the above example, FP_FLOAT was specified. This is to let the AMXX core know that we want to send a floating point int to the functions called.

Here are the possibilities for the previous section (I will explain how to pass an array/string later):

Code:
#define FP_CELL            0 #define FP_FLOAT        1 #define FP_STRING        2 #define FP_ARRAY        4

Next we check if iForward > 0, or if it's not we stop there and inform the server console. As said in the funcwiki, "Results will be > 0 for success.".

Next, we execute the forward using ExecuteForward. Picking this function apart:

forward_handle - this is the forward to call. It's the handle returned from CreateMultiForward / CreateOneForward.

&ret - this is the return value, passed by reference. It is effectively the value that the function being called returns (ex. return PLUGIN_HANDLED -> &ret == 1) It usually is effected by the stop_type in CreateMultiForward.

... - this is the param(s) where you can input the data that will be passed onto the function header for the function being called. In the example above, g_flDelay is passed and in the second plugin, the plugin_init_delay function recieves it in the header as Float:flDelay. NOTE: You can theoretically have infinite parameters, but they must match with the types passed into CreateOneForward / CreateMultiForward.

If ExecuteForward returns 0 (false) then we stop there and inform the server of this error. Otherwise, we continue onward to DestroyForward.

The next part we find is DestroyForward. The functionality for this is quite obvious, and can be used on any forward but should be used by the time plugin_end is called (or the FM forward for server shutting down) otherwise memory leaks can occur.

Now, what was the point of that? Not really much, that was pretty damn useless. Here's something a little more useful:

Code:
#include <amxmodx> #include <fakemeta> new g_iForward new g_iReturn public plugin_init() {     register_plugin("API Test 2 - Core","1.0","Hawk552")         g_iForward = CreateMultiForward("client_PreThink",ET_IGNORE,FP_CELL)     if(g_iForward < 0)         log_amx("Error creating forward")             register_forward(FM_PlayerPreThink,"fnForwardPlayerPreThink")     register_forward(FM_Sys_Error,"fnForwardSysError") } public fnForwardPlayerPreThink(id)     if(!ExecuteForward(g_iForward,g_iReturn,id))         log_amx("Could not execute forward")         public fnForwardSysError()     plugin_end()     public plugin_end()     DestroyForward(g_iForward)

Code:
#include <amxmodx> public plugin_init()     register_plugin("API Test - Attachment 2","1.0","Hawk552")     public client_PreThink(id)     log_amx("PreThink called on %d",id)

We just allowed a plugin to use client_PreThink using fakemeta without having to even create the fakemeta forward in the other plugin. On top of this, if we added another plugin to the API, it would call client_PreThink for that one too. Be careful though, it'll call it twice if you have engine included.

But one thing remains unanswered: how do you pass an array/string?

A special native has been implemented for this, PrepareArray. Here's an example of how to use it:

Code:
#include <amxmodx> #include <fakemeta> new g_iForward new g_iReturn public plugin_init() {     register_plugin("API Test 2 - Core","1.0","Hawk552")         g_iForward = CreateMultiForward("client_PreThink",ET_IGNORE,FP_ARRAY)     if(g_iForward < 0)         log_amx("Error creating forward")             register_forward(FM_PlayerPreThink,"fnForwardPlayerPreThink")     register_forward(FM_Sys_Error,"fnForwardSysError") } public fnForwardPlayerPreThink(id) {     new iRand = random(5),iArray[2]     iArray[0] = id     iArray[1] = iRand         new iArrayPass = PrepareArray(iArray,2,0)         if(!ExecuteForward(g_iForward,g_iReturn,iArrayPass))         log_amx("Could not execute forward") }         public fnForwardSysError()     plugin_end()     public plugin_end()     DestroyForward(g_iForward)

Code:
#include <amxmodx> public plugin_init()     register_plugin("API Test - Attachment 2","1.0","Hawk552")     public client_PreThink(iArray[2])     log_amx("PreThink called on %d, random value is %d",iArray[0],iArray[1])

Regardless of the fact we could use 2 cells instead of an array, this allows client_PreThink to have a random value from 0-5 packed into the parameters (which is quite useless, again this is just an example).

Now, to pick this apart:

We created an array and then packed it with data. You should know how to already do this.

We then use:

Code:
new iArrayPass = PrepareArray(iArray,2,0)

The usage of PrepareArray is as follows:

array[] - this is the array to be prepared
size - this is the amount of cells in the array (the same amount as when declaring it, not the highest cell)
copyback=0 - this is whether or not changing the array will result in the calling function's array being changed as well. This defaults to 0.

PrepareArray returns a handle as well that can be passed into ExecuteForward under the param of FP_ARRAY or FP_STRING. The difference between these two is that FP_STRING stops reading at the null terminator (and does not need to be prepared using PrepareArray), but FP_ARRAY must be prepared and only stops reading at the "size" cell.

Well, there you have it, if you have any questions or think a statement here is wrong, please post.
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Cheap_Suit
Veteran Member
Join Date: May 2004
Old 07-11-2006 , 19:14   Re: Plugin API
Reply With Quote #2

Your very resourcefull Hawk552 . Thanks for the tutoral.
__________________
HDD fried, failed to backup files. Sorry folks, just don't have free time anymore. This is goodbye.
Cheap_Suit is offline
VEN
Veteran Member
Join Date: Jan 2005
Old 08-24-2006 , 09:02   Re: Plugin API
Reply With Quote #3

Quote:
until ven gets done with the xp tutoriol
I've never worked on the XP tutorial.
VEN is offline
Lord_Destros
Veteran Member
Join Date: Jul 2004
Location: With stupid.
Old 08-24-2006 , 16:34   Re: Plugin API
Reply With Quote #4

1. Your banned again so this post may be pointless
2. I think your thinking of v3x
__________________
Quote:
Originally Posted by Twilight Suzuka
Don't worry m'lord. The turtles day will come.
Lord_Destros is offline
Send a message via AIM to Lord_Destros
Xanimos
Veteran Member
Join Date: Apr 2005
Location: Florida
Old 08-24-2006 , 20:32   Re: Plugin API
Reply With Quote #5

Speaking of v3x I havn't seen him in a long while. How about you guys?

[EDIT] Yep, hes been missing for over a month now....

Quote:
Originally Posted by v3x's Profile
Last Activity: 07-19-06 02:20 PM

Last edited by Xanimos; 08-24-2006 at 20:37.
Xanimos is offline
Send a message via AIM to Xanimos Send a message via MSN to Xanimos
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-25-2006 , 11:25   Re: Plugin API
Reply With Quote #6

Quote:
Originally Posted by gangstatothecore View Post
maybee it was v3x . I could have sworn that it was VEN tht was going to make an xp tutoiol to replace the old one
VEN is really beyond that stuff I think, he's more into the fakemeta hardcore stuff.
__________________

Last edited by Hawk552; 10-03-2006 at 16:48.
Hawk552 is offline
Send a message via AIM to Hawk552
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-25-2006 , 20:31   Re: Plugin API
Reply With Quote #7

Quote:
Originally Posted by nver_been_hit View Post
OMG did you just diss VEN ? lol. Hey hawk , I was wondering can the natives be used to return wether a plugin is on or off and if it could return cvars as values ? And So i should use the API in my core plugin to comunicate with the other supporting plugins? then have the supporting plugins use natives ?
No, I did not insult VEN, in fact that was more of a compliment.

Why not just use a name for a cvar and then a stock to check whether it's on or off? I suppose you could make a native that other plugins can use to check if your plugin is off, but if it has a cvar it's really better to avoid API / native functions.
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-25-2006 , 20:55   Re: Plugin API
Reply With Quote #8

Quote:
Originally Posted by nver_been_hit View Post
Ok well my cvars arnt for turning the plugins on and off . I hate cvars for that , there to muc of a pain in the ass . my cvars are in my core plugin , they hold values of the ranks , how many kills per rank can be changed by cvar. and i have a menu that has all the info and help of my whole mod . So im going to have my menu , get the wether a plugin is on or off , and the cvars . And if there on or off , it wil or wont display that part of the menu . so if my artilary strike plugin is off , the menu wont display it . also my ranks and values are in the menu too , so i want it to get the cvar values and display the current settings for the ranks . so my menu will be self suficiant auto detecting menu
Well what you can do is something like:

Code:
// ... register_native("BF_PointerPrivateKills","_BF_PointerPrivateKills") // ... public _BF_PointerPrivateKills()    return p_PrivateKills // or whatever you call the pointer to the cvar for kills that a private must get

Then in another plugin

Code:
if(get_pcvar_num(BF_PointerPrivateKills()) > 15) // do something

Your question is kinda unclear, but I think that's what you want. You can do the same thing with any cvar like that.
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-25-2006 , 21:09   Re: Plugin API
Reply With Quote #9

Quote:
Originally Posted by nver_been_hit View Post
ok well heres my core plugin (in beta stages now)www.ampaste.net/3390and heres my menu www.ampaste.net/3391 i want them to get values from my core , and return the cvar to display in my menu . also display only items that are on . because it creates some bit of lag and havoc when they do comands and the plugins arnt on . plus its anoying having to tel people that they arnt on 50 milion times day . so i want my menu to be auto detecting.
Both of those give errors for me.
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Hawk552
AMX Mod X Moderator
Join Date: Aug 2005
Old 08-25-2006 , 21:35   Re: Plugin API
Reply With Quote #10

uhh
  1. //battle field mod is not an open source plugins . You do not have permision to alter this code , or you will be sued . All rights are reserverd for Jared "RapHero2000" Chase//
  2. // Jared Chase 6-24-2006 ///
good luck, I'm not helping
__________________
Hawk552 is offline
Send a message via AIM to Hawk552
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 02:15.


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