[Tutorial] Plugin development guide

Quote:
Originally Posted by Slice
Посмотреть сообщение
Try changing the order you include stdlib/stdint and amx.h.
That's funny. Now I only get the last two errors, but I'll keep re-organizing code.
Thank you.
Reply

Add HAVE_STDINT_H preprocessor definition to your project settings and try recompile again.
Reply

Quote:
Originally Posted by Neavorce
Посмотреть сообщение
Add HAVE_STDINT_H preprocessor definition to your project settings and try recompile again.
That worked, thank you.
Reply

It's possible to pass variable by reference to callback?

I would like to do something like this to call a callback from plugin, and get them after function call.

public OnPlayerDoSomething(playerid &param1, &param2, &param3)
{
if(param1 > 10) param1 = 15;
param2 = 0;
return 1;
}
Reply

Of course (that's how strings are passed), just make sure to place them on the heap (unlike some samp callbacks...).
Reply

My dick is out of with this fucking AMX. I've tried to do this what I mentioned before, for first argument it works, but for more not.

My code

Printed result should be:
szőrцs fasz 0, 2000

But it:
szőrцs fasz 0, 150 <- setting second parameter doesn't work

pawn Код:
void CCallbackManager::OnPlayerClientGameInit(WORD playerid, bool* limitglobalchat, float* globalchatradius, float* nametagdistance, bool* disableenterexits)
{
    int idx = -1;
    cell ret = 1;
    for (std::vector<AMX*>::const_iterator iter = m_vecAMX.begin(); iter != m_vecAMX.end(); ++iter)
    {
        if (!amx_FindPublic(*iter, "OnPlayerClientGameInit", &idx))
        {
            cell addr = NULL, amx_addr, *phys_ptr;
            cell data[2];

            data[0] = static_cast<cell>(*limitglobalchat);
            data[1] = static_cast<cell>(*globalchatradius);

            //data[2] = amx_ftoc(*nametagdistance);
            //data[3] = static_cast<cell>(*disableenterexits);

            amx_PushArray(*iter, &amx_addr, &phys_ptr, data, 2);
            //*globalchatradius = reinterpret_cast<cell*>(phys_ptr);

            //cell limitglobalchat_ = 1;

            //amx_PushArray(*iter, &amx_addr, &phys_ptr, reinterpret_cast<cell*>(&limitglobalchat), 1);


            //amx_PushString(*iter, &addr, NULL, str.c_str(), NULL, NULL);
           
            amx_Push(*iter, static_cast<cell>(playerid));
            amx_Exec(*iter, &ret, idx);
            amx_Release(*iter, amx_addr);

            //*limitglobalchat = !!*phys_ptr;
            logprintf("szőrцs fasz %d, %d", phys_ptr[0], phys_ptr[1]);

            //logprintf("globalchat: %d, %f", *limitglobalchat, *globalchatradius);

        }
    }
}

forward OnPlayerClientGameInit(playerid, &limitglobalchat, &globalchatradius);
public OnPlayerClientGameInit(playerid, &limitglobalchat, &globalchatradius)
{
    limitglobalchat = 0;
    globalchatradius = 2000;
//    nametagdistance = -50.2;
  //  disableenterexits = false;
    printf("lуfasz - %d", limitglobalchat);
}
Any ideas how to solve this problem?
Reply

You should use PushArray with singleton array two times (once for each variable).

PushArray will allocate memory for your 2-element array in the heap. Your callback will receive the 'whole array' in limitglobalradius argument but since its just a reference variable not an array, only the first element of the array which you pushed will be pointed by limitglobalchat.

I don't even know what globalchatradius would be point to. The issue is globalchatradius doesn't take up the 2nd index of the array which you passed because of which you are not getting expected results.

Its intuitive that globalchatradius would be pointing to the very next set of 4 bytes after limitglobalchat. The reference variables are modified using SREF.S ([[FRM + offset]] = PRI). So [[]]? How can you say that the arguments are pointing to cells which are next to each other?

I doubt if using PushArray wiht 2-element array is same as using PushArray twice with singleton array.

I believe this is the way to access the second index of your array using the limitglobalchat argument.
Код:
#emit LOAD.S.pri limitglobalchat
#emit ADD.C 4
#emit MOVE.alt
#emit CONST.pri 2000
#emit STOR.I
But using the globalchatradius argument, I guess the assembly output would be
Код:
#emit CONST.pri 2000
#emit SREF.S.pri globalchatradius
I don't understand what will the globalchatradius be pointing to.
Reply

You need to call amx_PushArray() twice - first for globalchatradius, then once again for limitglobalchat.

For some reason AMX doesn't have a function for pushing references, only arrays. But references may be thought of as a special case of one-dimensional arrays - they look the same in memory, only difference is the number of elements (i.e. references are 1-element arrays).
Reply

Dan once made a function to push PAWN references/addresses:
Code:
int AMXAPI amx_PushAddress(AMX *amx, cell *address) 
{
	AMX_HEADER *hdr;
	unsigned char *data;
	cell xaddr;
	/* reverse relocate the address */
	assert(amx != NULL);
	hdr = (AMX_HEADER *) amx->base;
	assert(hdr != NULL);
	assert(hdr->magic == AMX_MAGIC);
	data = (amx->data != NULL) ? amx->data : amx->base + (int) hdr->dat;
	xaddr = (cell) ((unsigned char*) address-data);
	if ((ucell) xaddr >= (ucell) amx->stp) 
	{
		return AMX_ERR_MEMACCESS;
	}
	return amx_Push(amx,xaddr);
}
Reply

Yashas, Zeex: Thanks for help, it worked. U will see the result in next version of YSF xD

Quote:
Originally Posted by maddinat0r
View Post
Dan once made a function to push PAWN references/addresses:
Code:
int AMXAPI amx_PushAddress(AMX *amx, cell *address) 
{
	AMX_HEADER *hdr;
	unsigned char *data;
	cell xaddr;
	/* reverse relocate the address */
	assert(amx != NULL);
	hdr = (AMX_HEADER *) amx->base;
	assert(hdr != NULL);
	assert(hdr->magic == AMX_MAGIC);
	data = (amx->data != NULL) ? amx->data : amx->base + (int) hdr->dat;
	xaddr = (cell) ((unsigned char*) address-data);
	if ((ucell) xaddr >= (ucell) amx->stp) 
	{
		return AMX_ERR_MEMACCESS;
	}
	return amx_Push(amx,xaddr);
}
Thanks, but function crashed for me.
Reply

E:

Thanks for help, result: https://github.com/kurta999/YSF/comm...d34b8ef3bda2e5
Reply

Guys could someone share snippet for calling native from C++? I would like to avoid GDK or Invoke ( i just need to call one native on plugin load and that's it )

Oh and i need to read returned data (its integer)
Reply

Yashas, convert the strings from pawn to C/++ format.
vannesenn, see sampGDK by Zeex.
Reply

Quote:
Originally Posted by codectile
View Post
Yashas, convert the strings from pawn to C/++ format.
vannesenn, see sampGDK by Zeex.
Why is it needed? PAWN cell is 4 bytes and only the first byte stores the character. So copying characters should be same as copying cells?
Reply

Quote:
Originally Posted by Yashas
View Post
Why is it needed? PAWN cell is 4 bytes and only the first byte stores the character. So copying characters should be same as copying cells?
Yes, each pawn cell is of 4 bytes. But do you really think that strings in the abstract machine are in a such simple format?
Try using amx_GetString and check whether you get same results or not.

EDIT:

Shouldn't this: string_strncpy(AMX amx, cell params)
be: string_strncpy(AMX* amx, cell* params) ?
Reply

Quote:
Originally Posted by codectile
View Post
Yes, each pawn cell is of 4 bytes. But do you really think that strings in the abstract machine are in a such simple format?
Srtings are arrays so what is so different? Each character is stored in each cell linearly in PAWN (unpacked strings) so I can treat it as it was an array but with a null at the end?

Of course, that code won't work with packed strings and I don't use packed strings so I won't need to add support for that.

I have many more algorithms which work on arrays which use the exact same method (directly modifying the contents through pointers) and they work.

Quote:
Originally Posted by codectile
View Post
Try using amx_GetString and check whether you get same results or not.
And SetString again? will reply after doing it...

Quote:
Originally Posted by codectile
View Post
EDIT:

Shouldn't this: string_strncpy(AMX amx, cell params)
be: string_strncpy(AMX* amx, cell* params) ?
Yea, I asked about it with few people in skype and copied the code from the skype chat which is why few * are missing.

Here is a copy from the actual source.
Code:
cell AMX_NATIVE_CALL string_strncpy(AMX* amx, cell* params)
	{
		cell* dest = NULL;
		cell* source = NULL;

		amx_GetAddr(amx, params[1], &dest);
		amx_GetAddr(amx, params[2], &source);

		int num = static_cast<int>(params[3]);
		unsigned int size_dest = static_cast<unsigned int>(params[4]);
		unsigned int size_src = static_cast<unsigned int>(params[5]);

		while (num-- && size_dest-- && size_src--) {
			logprintf("%d", *(source));
			*dest++ = *source++;
		}
		*dest = 0;
		return 0;
	}
------------------------------------------------------------
wtf I sware I did not change the code at all =,= the array size is 11 and it works today -_-
Code:
[13:05:59] t
[13:05:59] e
[13:05:59] s
[13:05:59] t
[13:05:59]  
[13:05:59] s
[13:05:59] t
[13:05:59] r
[13:05:59] i
[13:05:59] n
[13:05:59] test strin
Reply

Yes, it works. I tried out your code yesterday and it worked out for me. I was about to edit my comment but unfortunately had no time.
Reply

Hi guys!

I've just created a new way of setting amx parameters from plugin.

pawn Code:
// native GetSpawnInfo(playerid, &teamid, &modelid, &Float:spawn_x, &Float:spawn_y, &Float:spawn_z, &Float:z_angle, &weapon1, &weapon1_ammo, &weapon2, &weapon2_ammo,& weapon3, &weapon3_ammo);

CAMXParameters amxparams(amx, params, 2);

amxparams.Add(pSpawn->byteTeam);
amxparams.Add(pSpawn->iSkin);
amxparams.Add(pSpawn->vecPos);
amxparams.Add(pSpawn->fRotation);
amxparams.Add(pSpawn->iSpawnWeapons[0]);
amxparams.Add(pSpawn->iSpawnWeaponsAmmo[0]);
amxparams.Add(pSpawn->iSpawnWeapons[1]);
amxparams.Add(pSpawn->iSpawnWeaponsAmmo[1]);
amxparams.Add(pSpawn->iSpawnWeapons[2]);
amxparams.Add(pSpawn->iSpawnWeaponsAmmo[2]);
Does it looks good? I'm waiting for other people's opinion
Reply

PHP Code:
Loading pluginEmailSender
 Plugin does not conform to architecture
.
 
Failed
what the hell ?
Reply

Quote:
Originally Posted by Yaa
View Post
PHP Code:
Loading pluginEmailSender
 Plugin does not conform to architecture
.
 
Failed
what the hell ?
Literally the first result in ******..
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)