[Tutorial] Plugin development guide
#41

Since im taking a sort of programming hiatus for the holidays, i decided to add what i currently had done for the next update NOW. This way people dont have to wait as long for something that should've been added in the initial release.

The next update will include the GDK, but it wont be for a bit. Im still thinking how im going to restructure the article to fit it in (Since its not an addition to the SDK, but rather includes it and expands on it, its a bit difficult).
Reply
#42

Quote:
Originally Posted by Y_Less
View Post
I hadn't seen this before. This is incredible work - very well done!
Thanks, that means a lot coming from you ! If you notice any mistakes or any areas for improvement, feel free to let me know.
Reply
#43

And where should I place the files that come in the SDK?
Reply
#44

Quote:
Originally Posted by CookieJar
View Post
And where should I place the files that come in the SDK?
Did you even read my guide at all? I completely walk you through setting a project up. Please read the last 2 steps in the getting started section. They explain exactly what to do with the SDK files.
Reply
#45

Wow,this is huge ! :O
nice work you done there...
Reply
#46

Very nice work!
Reply
#47

Quote:
Originally Posted by Y_Less
View Post
This could do with more documentation on the rest of the amx_ functions. I came here the other day to look up some things and they weren't documented.
Could you share which particular amx functions that you believe should be added to the guide? I know i left out quite a bit of AMX functions, but there were a couple of reasons for doing so. While i want this guide to document everything, i also want to keep it compact as i can (reasonably). Every time i add an amx function i also have to create an example for it, if i didnt it just wouldnt be fair to the readers. The functions you see listed are only the ones i've used in this guide. Another reason i left out a few was simply because some of them dont apply to plugin development, so there's no point in listing those.

Tell me which ones you think should be added and i'll write the examples and add them to the guide (as long as they pertain to plugins - like amx_FindPublicVar).

Quote:
Originally Posted by Y_Less
View Post
I'm not sure why you mention natives there at all.

Also, it would be helpful to explain a little more about "callbacks". We call PUBLIC functions "callbacks", the PAWN VM calls NATIVE functions "callbacks" and this can lead to some confusion if you don't remember that it's all point-of-view specific. The VM executes PAWN code and they some times "call back" in to the VM through natives. PAWN code executes functions, including natives, and these sometimes "call back" in to the PAWN script through publics.
I didnt write those function references, i simply copied them over from the implementers guide and made them "pretty". I didnt want to spend so much time reinventing the wheel, especially when i probably wouldnt be able to beat what already existed. This would be my best attempt at documenting this function (keep in mind the index parameter would already be explained):

Code:
amx_Exec accesses an entry point (public function) in the script based off of the specified "index" parameter value. Any native function that the script uses will be sent to the amx_Callback function assuming that it wasnt overrided with amx_SetCallback. In this "callback" function any return value that is non-zero will result in the halting of execution of amx_Exec.
Im not sure if thats a better explanation, but its the best i can do with the little information i have read on the function. I havent really read all the implementers guide simply because my primary interest has been with plugins, not implementing/setting up the abstract machine. This of courses means my understanding of certain functions and bits of the abstract machine (ie: op codes) arent as high as they COULD be.

There may be a time when i completely rewrite the amx function documentation in my own words, but im also trying to better myself as a programmer, so im not sure when this might be.
Reply
#48

This is a very good topic!!
It makes me want to dive into learning C++ and write some un-useful plugin just for learning!!
I love learning new stuff and have been recently diving into some c++ for fun. Now I have actually got something to build on.

thank you
Reply
#49

What the hell... I'm just trying to use invoke and here is my results . Please, help someone.



Code:
#include "SDK\amx\amx.h"
#include "SDK\plugincommon.h"

#include "Invoke.h"

typedef void (*logprintf_t)(char* format, ...);


logprintf_t logprintf;
extern void *pAMXFunctions;


cell AMX_NATIVE_CALL HelloWorld(AMX* amx, cell* params)
{
    logprintf("This was printed from the Test plugin! Yay!");
    return 1;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() 
{
    return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) 
{
	invoke = new Invoke;
    pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t) ppData[PLUGIN_DATA_LOGPRINTF];

    logprintf(" * Test plugin was loaded.");

    return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
    logprintf(" * Test plugin was unloaded.");
}

AMX_NATIVE_INFO PluginNatives[] =
{
    {"HelloWorld", HelloWorld},
    {0, 0}
};

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx ) 
{
	invoke->amx_list.push_back(amx);
    return amx_Register(amx, PluginNatives, -1);
}


PLUGIN_EXPORT int PLUGIN_CALL AmxUnload( AMX *amx ) 
{
	for (std::list<AMX *>::iterator i = invoke->amx_list.begin(); i != invoke->amx_list.end(); ++i)
	{
	    if (* i == amx)
		{
			invoke->amx_list.erase(i);
			break;
		}
	}
    return AMX_ERR_NONE;
}
Reply
#50

Quote:
Originally Posted by zgintasz
View Post
What the hell... I'm just trying to use invoke and here is my results . Please, help someone.



Code:
#include "SDK\amx\amx.h"
#include "SDK\plugincommon.h"

#include "Invoke.h"

typedef void (*logprintf_t)(char* format, ...);


logprintf_t logprintf;
extern void *pAMXFunctions;


cell AMX_NATIVE_CALL HelloWorld(AMX* amx, cell* params)
{
    logprintf("This was printed from the Test plugin! Yay!");
    return 1;
}

PLUGIN_EXPORT unsigned int PLUGIN_CALL Supports() 
{
    return SUPPORTS_VERSION | SUPPORTS_AMX_NATIVES;
}

PLUGIN_EXPORT bool PLUGIN_CALL Load(void **ppData) 
{
	invoke = new Invoke;
    pAMXFunctions = ppData[PLUGIN_DATA_AMX_EXPORTS];
    logprintf = (logprintf_t) ppData[PLUGIN_DATA_LOGPRINTF];

    logprintf(" * Test plugin was loaded.");

    return true;
}

PLUGIN_EXPORT void PLUGIN_CALL Unload()
{
    logprintf(" * Test plugin was unloaded.");
}

AMX_NATIVE_INFO PluginNatives[] =
{
    {"HelloWorld", HelloWorld},
    {0, 0}
};

PLUGIN_EXPORT int PLUGIN_CALL AmxLoad( AMX *amx ) 
{
	invoke->amx_list.push_back(amx);
    return amx_Register(amx, PluginNatives, -1);
}


PLUGIN_EXPORT int PLUGIN_CALL AmxUnload( AMX *amx ) 
{
	for (std::list<AMX *>::iterator i = invoke->amx_list.begin(); i != invoke->amx_list.end(); ++i)
	{
	    if (* i == amx)
		{
			invoke->amx_list.erase(i);
			break;
		}
	}
    return AMX_ERR_NONE;
}
It looks like you are using VS 2010. Can you try compiling manually using GCC++ from Command Prompt?
Reply
#51

Quote:
Originally Posted by Rancho
Посмотреть сообщение
Hello, I'm trying to make something..
C++:
Код:
int playerid = params[1];
	int idx;
	if(!amx_FindPublic(amx,"__GetPlayerName",&idx)){
		cell ret;
		cell* str_phys;
		cell amxaddr;
		amx_Push(amx,playerid);
		amx_Allot(amx,24,&amxaddr,&str_phys);
		
		amx_Push(amx,amxaddr);
		amx_Exec(amx,&ret,idx);

		char name[24];
		amx_GetString(name,str_phys,0,24);
		amx_Release(amx,amxaddr);
		printf("%s",name);
	}else{
		printf("Native");
	}
Pawn:
Код:
forward __GetPlayerName(playerid,name[]);
public __GetPlayerName(playerid,name[]){
	GetPlayerName(playerid,name,MAX_PLAYER_NAME);
}
It doesn't crash but prints player name: "" (empty)

P.S: I don't want to use invoke or gdk.I want to make this.
P.S: playerid is correct.I tested.
Up+++
Reply
#52

What I'm doing wrong? plugin_test prints wrong values.

pawn Код:
forward plugin_test( itg_MinX, itg_MinY, itg_MaxX, itg_MaxY );
public plugin_test( itg_MinX, itg_MinY, itg_MaxX, itg_MaxY )
{
    printf( "comes from c++: %d, %d, %d, %d", itg_MinX, itg_MinY, itg_MaxX, itg_MaxY );
}
Код:
// calling:
testfunc( amx, 5, 3, 2, 8 );

// function:

void testfunc( AMX* amx, int itg_MinX, int itg_MinY, int itg_MaxX, int itg_MaxY )
{
    int idx;

    const cell arr[] = { itg_MinX, itg_MinY, itg_MaxX, itg_MaxY };

    if(!amx_FindPublic(amx, "plugin_test", &idx))
    {
        cell
            ret, 
            addr = 0;

        cell
            amx_addr, 
            *phys_addr;

	amx_Allot(amx, sizeof(arr) / sizeof(cell), &amx_addr, &phys_addr);
        memcpy(phys_addr, arr, sizeof(arr));
        amx_Push(amx, amx_addr);
        amx_Exec(amx, &ret, idx);
        amx_Release(amx, addr);
    }
}
Reply
#53

@Rancho
use amx_PushString, you can get working examples in some of plugins(just look up some with callbacks that receive strings)
@zgintasz
You must amx_Push all values in reverse order(right-to-left), push theirs' amx addr of course.
Reply
#54

Quote:
Originally Posted by JoBullet
Посмотреть сообщение
@Rancho
use amx_PushString, you can get working examples in some of plugins(just look up some with callbacks that receive strings)
@zgintasz
You must amx_Push all values in reverse order(right-to-left), push theirs' amx addr of course.
Can you give me a fixed code? I'm just trying to learn it.
Reply
#55

Quote:
Originally Posted by zgintasz
Посмотреть сообщение
Can you give me a fixed code? I'm just trying to learn it.
There are plenty of plugins which shows exactly that and by the way, do not be lazy
Reply
#56

I get a strange Error, when i try to start my plugin on Linux.
it always says
Quote:

Failed (plugins/Plugin.so: undefined symbol: sampgdk_TextDrawShowForPlayer)

I compiled all .cpp files with the libary included but nothing worked.
Reply
#57

Does anyone know just how to get the SAMPGDK library installed?

Код:
#include <sampgdk/a_samp.h>
I want to know how I can have it be included like that. Thanks.
Reply
#58

Quote:
Originally Posted by Rancho
Посмотреть сообщение
Hello, I'm trying to make something..
C++:
Код:
int playerid = params[1];
	int idx;
	if(!amx_FindPublic(amx,"__GetPlayerName",&idx)){
		cell ret;
		cell* str_phys;
		cell amxaddr;
		amx_Push(amx,playerid);
		amx_Allot(amx,24,&amxaddr,&str_phys);
		
		amx_Push(amx,amxaddr);
		amx_Exec(amx,&ret,idx);

		char name[24];
		amx_GetString(name,str_phys,0,24);
		amx_Release(amx,amxaddr);
		printf("%s",name);
	}else{
		printf("Native");
	}
Pawn:
Код:
forward __GetPlayerName(playerid,name[]);
public __GetPlayerName(playerid,name[]){
	GetPlayerName(playerid,name,MAX_PLAYER_NAME);
}
It doesn't crash but prints player name: "" (empty)

P.S: I don't want to use invoke or gdk.I want to make this.
P.S: playerid is correct.I tested.
I fixed, I was push playerid, string_addr but I couldn't think reverse pushing sort.

Fİrst I pushed string addr, after playerid.It worked for me.
Reply
#59

DELETED
Reply
#60

Wow, awesome tutorial, very very good explained.
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)