Funções get
(com o uso de Pawn.RakNet)
(com o uso de Pawn.RakNet)
Bom, estou um certo tempo sem trazer contribuiзхes para a board, entгo, vim trazer um pouco do meu conhecimento sobre Pawn.RakNet, por aqui, jб existem diversos tуpicos sobre Pawn.RakNet construнdos pelo BrunoBM23 e pela Jelly23. Mas vou trazer um simples tуpico sobre como funcionam as funзхes Get com o uso de Pawn.RakNet, e mostrarei como fiz um conserto de uma funзгo nativa.
Vamos comeзar...
Para vocк entender o que eu irei fazer, й necessбrio vocк ler os tуpicos sobre RPCs, Pacotes e Leitura/escritura de Offsets.
Vou explicar tudo o que eu fiz na minha correзгo da funзгo nativa, a GetPlayerVehicleSeat.
"Qual o problema da funзгo nativa?"
A funзгo nativa nгo retorna exatamente os valores dos assentos, algumas vezes ela retorna com valores aleatуrios. Mas com a minha correзгo, a funзгo vai retornar exatamente aonde o jogador estб sentado, pois com a minha funзгo, os dados extraнdos diretamente do pacote em que й transmito via IncomingPackets.
Primeiro temos que criar uma definiзгo em prй-processamento para a nossa correзгo. (Lembrando, estou retratando tudo que fiz na correзгo, pois a correзгo й uma include)
Vamos comeзar verificando se existe alguma definiзгo com a nomenclatura que vamos fazer.:
- Código:
#if defined _GPVS_included
#endinput
#endif
#define _GPVS_included
Eu fiz uma simples condicional, caso jб esteja definida/inserida a include com a nomenclatura carregada como "_GPVS_included", nгo inserir ("#endinput").
Apуs a condicional, foi inserida a nomenclatura em prй-processamento da minha include. (Que й "_GPVS_included")
Agora, vamos fazer outra condicional, que й para verificar se a include do plugin RakNet estб inserida.
- Código:
#if !defined PAWNRAKNET_INC_
#error Pawn.RakNet is necessary.
#endif
O que foi feito acima, foi para retornar com uma mensagem de erro caso a include do Pawn.RakNet nгo esteja inserida/definida.
Agora, vamos criar uma definiзгo, para identificar o valor de um assento invбlido.
- Código:
#define INVALID_SEAT_ID (-1)
Apуs, iremos criar uma variбvel estбtica com a matriz MAX_PLAYERS em char.
- Código:
static GPVS_PlayerSeat[MAX_PLAYERS char];
Agora, vamos para onde й o nosso "X" da questгo, que й aonde tudo vai acontecer.
Primeiro temos que procurar saber aonde que ocorre a passagem desses dados.
Logicamente, dados sobre o assento do jogador, sгo passados pelos pacotes ID_DRIVER_SYNC(ID: 200) e ID_PASSENGER_SYNC (ID: 211). Que os mesmos sгo responsбveis por questхes relacionados ao veнculo e ao passageiro.
Agora, para nуs iniciarmos, й necessбrio saber em qual tipo de pacote nуs vamos comeзar a usar a callback. No caso, se iremos usar Incoming ou Outgoing Packet.
Neste caso, nуs iremos utilizar o IncomingPacket, pois o valor de cada assento sгo dados criados pelo cliente e enviados ao servidor.
Entгo, iremos utilizar a callback OnIncomingPacket.
Sim, nуs usaremos Hook, nуs vamos utilizar o ALS Hook Method 7.
- Código:
public OnIncomingPacket(playerid, packetid, BitStream:bs)
{
#if defined GPVS_OnIncomingPacket
return GPVS_OnIncomingPacket(playerid, packetid, bs);
#else
return true;
#endif
}
Para comeзar, vamos fazer uma condicional sobre o assento do motorista, logo, o mesmo deverб ser setado para 0. Entгo, vamos setar a array estбtica que fizemos.
- Código:
public OnIncomingPacket(playerid, packetid, BitStream:bs)
{
if(packetid == 200)
GPVS_PlayerSeat{playerid} = 0;
#if defined GPVS_OnIncomingPacket
return GPVS_OnIncomingPacket(playerid, packetid, bs);
#else
return true;
#endif
}
Apуs nуs setarmos o valor da variбvel para 0, quando o jogador estiver no assento do motorista, a variбvel serб setada para 0, logo, a funзгo tambйm retornarб 0.
Agora, vamos tratar sobre o pacote responsбvel pelo passageiro do veнculo, que й aonde vamos comeзar os processos.
- Código:
public OnIncomingPacket(playerid, packetid, BitStream:bs)
{
if(packetid == 200)
GPVS_PlayerSeat{playerid} = 0;
else if(packetid == 211)
{
BS_SetReadOffset(bs, 26);
BS_ReadValue\
(\
bs,
PR_BITS, GPVS_PlayerSeat{playerid}, 6
);
BS_ResetReadPointer(bs);
}
#if defined GPVS_OnIncomingPacket
return GPVS_OnIncomingPacket(playerid, packetid, bs);
#else
return true;
#endif
}
Agora, vamos entender o que foi feito na condicional sobre o pacote dos passageiros.
No caso abaixo:
- Código:
BS_SetReadOffset(bs, 26);
Й necessбrio entender que:
Code:
- Código:
stock BS_ReadPassengerSync(BitStream:bs, data[PR_PassengerSync])
{
BS_ReadValue\
(\
bs,
PR_UINT16, data[PR_vehicleId],
PR_BITS, data[PR_driveBy], 2,
PR_BITS, data[PR_seatId], 6,
PR_BITS, data[PR_additionalKey], 2,
PR_BITS, data[PR_weaponId], 6,
PR_UINT8, data[PR_playerHealth],
PR_UINT8, data[PR_playerArmour],
PR_UINT16, data[PR_lrKey],
PR_UINT16, data[PR_udKey],
PR_UINT16, data[PR_keys],
PR_FLOAT, data[PR_position][0],
PR_FLOAT, data[PR_position][1],
PR_FLOAT, data[PR_position][2]
);
}
A linhagem acima, estб o que percorre todo o pacote, e o que consegue ser lido pelo mesmo.
Nуs queremos interceptar o assento do jogador, que no caso, й o seatId, й uma variбvel com o tipo de dados em BITS, que possui 6 bits.
Agora, que nуs iremos aplicar o que foi dado no tуpico do BrunoBM23 sobre escritura/leitura das offsets.
O parвmetro que queremos chegar, й o terceiro, logo, nуs devemos obrigatoriamente inserir os primeiros 8bits do bitStream junto а soma.
O que й pra se fazer й apenas somar os valores.
Code:
- Código:
Primeiros oito bits = 8
PR_UINT16 = 16
PR_BITS = 2 (O valor de PR_BITS й variado com o valor dado ao lado, apуs passar a variбvel, mas nesse caso, й 2)
8 + 16 + 2 = 26
Nota: Nгo insira o valor do parвmetro que vocк quer chegar, sempre insira um antes dele mesmo, como foi feito acima.:
Eu quero chegar no seatId, entгo eu tenho que somar atй o driveBy. E nгo atй o seatId.
Apуs entendermos o que foi feito na contagem e inserзгo da quantidade bits a serem lidos, vamos ler os valores. (Que foi o caso abaixo)
- Código:
BS_ReadValue\
(\
bs,
PR_BITS, GPVS_PlayerSeat{playerid}, 6
);
O valor foi lido e consequentemente, devemos colocar a nossa variбvel estбtica como referкncia para que os valores sejam lidos, ou seja, eles estгo passando os valores que foram lidos para a nossa variбvel estбtica.
Claro, quando finalizarmos, vamos fechar/deletar todos os pontos de leitura de qualquer bitStream, para nгo entrar em conflito com nenhum outro que jб esteja com a soma inserida.(Como foi feito no caso abaixo)
- Código:
BS_ResetReadPointer(bs);
Finalizado a parte mais "complexa". Agora, vamos desenvolver a correзгo da funзгo.
- Código:
stock GetPlayerVehicleSeat(playerid)
{
if(!IsPlayerConnected(playerid) || !IsPlayerInAnyVehicle(playerid))
return INVALID_SEAT_ID;
else
return GPVS_PlayerSeat{playerid};
}
Criamos a nomenclatura da funзгo, logo apуs, foi feita a condicional, se o jogador nгo estiver conectado ou se ele nгo estiver em nenhum veнculo, obviamente, irб retornar o valor invбlido de assento(-1), que foi definido no topo da include. Caso contrбrio, irб retornar o valor que estб dentro da nossa variбvel estбtica.
Pronto, quase tudo estб pronto, agora, sу falta finalizar a ъltima parte do Hook.:
- Código:
/*----------------------------------------------*/
#if defined _ALS_OnIncomingPacket
#undef OnIncomingPacket
#else
#define _ALS_OnIncomingPacket
#endif
#define OnIncomingPacket GPVS_OnIncomingPacket
#if defined GPVS_OnIncomingPacket
forward GPVS_OnIncomingPacket(playerid, packetid, BitStream:bs);
#endif
/*----------------------------------------------*/
#if defined _ALS_GetPlayerVehicleSeat
#undef GetPlayerVehicleSeat
#else
#define _ALS_GetPlayerVehicleSeat
#endif
#define GetPlayerVehicleSeat GPVS_GetPlayerVehicleSeat
Finalizando, toda a include ficou da seguinte forma:
- Código:
#if defined _GPVS_included
#endinput
#endif
#define _GPVS_included
#if !defined PAWNRAKNET_INC_
#error Pawn.RakNet is necessary.
#endif
#define INVALID_SEAT_ID (-1)
/* Variable */
static GPVS_PlayerSeat[MAX_PLAYERS char];
/* Function */
stock GetPlayerVehicleSeat(playerid)
{
if(!IsPlayerConnected(playerid) || !IsPlayerInAnyVehicle(playerid))
return INVALID_SEAT_ID;
else
return GPVS_PlayerSeat{playerid};
}
/* Callback */
public OnIncomingPacket(playerid, packetid, BitStream:bs)
{
if(packetid == 0xC8)
GPVS_PlayerSeat{playerid} = 0;
else if(packetid == 0xD3)
{
BS_SetReadOffset(bs, 26);
BS_ReadValue\
(\
bs,
PR_BITS, GPVS_PlayerSeat{playerid}, 6
);
BS_ResetReadPointer(bs);
}
#if defined GPVS_OnIncomingPacket
return GPVS_OnIncomingPacket(playerid, packetid, bs);
#else
return true;
#endif
}
/* Hook */
/*----------------------------------------------*/
#if defined _ALS_OnIncomingPacket
#undef OnIncomingPacket
#else
#define _ALS_OnIncomingPacket
#endif
#define OnIncomingPacket GPVS_OnIncomingPacket
#if defined GPVS_OnIncomingPacket
forward GPVS_OnIncomingPacket(playerid, packetid, BitStream:bs);
#endif
/*----------------------------------------------*/
#if defined _ALS_GetPlayerVehicleSeat
#undef GetPlayerVehicleSeat
#else
#define _ALS_GetPlayerVehicleSeat
#endif
#define GetPlayerVehicleSeat GPVS_GetPlayerVehicleSeat
Obrigado, nгo й algo tгo longo, mas que acredito que possa contribuir e ajudar em algo para os demais da board.
+Informations:
Outro exemplo, й esta reproduзгo da funзгo GetPlayerWeapon.:
- Código:
static GPW_RakNet[MAX_PLAYERS char];
stock GetPlayerWeapon(playerid)
{
if(playerid < 0 || playerid > MAX_PLAYERS)
return false;
return GPW_RakNet{playerid};
}
public OnIncomingPacket(playerid, packetid, BitStream:bs)
{
if(packetid == 207)
{
BS_SetReadOffset(bs, 234);
BS_ReadValue\
(\
bs,
PR_BITS, GPW_RakNet{playerid}, 6
);
BS_ResetReadPointer(bs);
}
#if defined GPW_RakNet_OnIncomingPacket
return GPW_RakNet_OnIncomingPacket(playerid, packetid, BitStream:bs);
#else
return true;
#endif
}
#if defined _ALS_OnIncomingPacket
#undef OnIncomingPacket
#else
#define _ALS_OnIncomingPacket
#endif
#define OnIncomingPacket _ALS_OnIncomingPacket
#if defined GPW_RakNet_OnIncomingPacket
forward GPW_RakNet_OnIncomingPacket(playerid, packetid, BitStream:bs);
#endif
// --------------------
#if defined _ALS_GetPlayerWeapon
#undef GetPlayerWeapon
#else
#define _ALS_GetPlayerWeapon
#endif
#define GetPlayerWeapon GPW_GetPlayerWeapon
Creditos: Jelly23