Sincronização no SA-MP. - Levi.M - 28/02/2021
• Sincronização no SA-MP.
Citar:Conteúdo:
Citar:- Sincronização de dados;
- Funções Get*;
- Mundos virtuais e processo de "streaming";
- Pool interna de processamento de RPCs.
- Dessincronização.
• Sincronização de dados.
Citar:Todos os dados como posição, arma atual e velocidade vem em pacotes. Ou mais precisamente no caso de UDP, datagramas. Cada datagrama contém uma ou mais mensagens, podendo ser vida, posição atual, entre outros.
Cada pacote é identificado pelos seus primeiros 8 bits (1 byte), que nesse caso é o seu identificador numérico. Existem diferentes tipos de pacotes contendo diferentes mensagens/dados em si, sendo:
ID_PLAYER_SYNC (ID: 207) - Um pacote com este identificador numérico é responsável por atualizações a pé, dos jogadores. Este pacote sempre será enviado APENAS se o jogador estiver a pé, e é enviado a cada um segundo se o jogador não estiver se movendo. A sua estrutura de dados é a seguinte:
- lrKey - Seta para esquerda/direita (←→) - Se a tecla atual for seta para esquerda, então lrKey se iguala a KEY_LEFT, caso contrário KEY_RIGHT. 0 se nenhum dos casos.
- udKey - Seta para cima/baixo (↑↓) - Se a tecla atual for seta para cima, então lrKey se iguala a KEY_UP, caso contrário KEY_DOWN. 0 se nenhum dos casos.
- keys - Um mapa (bitmask) com as teclas pressionadas.
- position[3] - Posição atual (X, Y, Z).
- quaternion[4] - Quaterniões de rotação (W, X, Y, Z).
- health - Vida atual do jogador.
- armour - Colete atual do jogador.
- weaponId - Arma atual do jogador.
- additionalKey - Tecla adicional.
- specialAction - Ação especial.
- velocity[3] - Velocidade nos eixos X, Y e Z.
- surfingOffsets[3] - Offsets de surfing em um veículo - 0.0 em todas as offsets se o jogador não estiver surfando um veículo.
- surfingVehicleId - O ID do veículo que o jogador está surfando (0 se nenhum).
- animationId - ID da animação atual.
- animationFlags - Flags da animação atual.
ID_VEHICLE_SYNC (ID: 200) - Um pacote com este identificador numérico é responsável por atualizações do jogador dentro de um veículo (como motorista). A sua estrutura de dados é a seguinte:
- vehicleId - ID de veículo atual.
- lrKey - Seta para esquerda/direita (←→) - Se a tecla atual for seta para esquerda, então lrKey se iguala a KEY_LEFT, caso contrário KEY_RIGHT. 0 se nenhum dos casos.
- udKey - Seta para cima/baixo (↑↓) - Se a tecla atual for seta para cima, então lrKey se iguala a KEY_UP, caso contrário KEY_DOWN. 0 se nenhum dos casos.
- keys - Um mapa (bitmask) com as teclas pressionadas.
- quaternion[4] - Quaterniões de rotação do veículo (W, X, Y, Z).
- position[3] - Posição atual (X, Y, Z)
- velocity[3] - Velocidade nos eixos X, Y e Z.
- vehicleHealth - Vida atual do veículo.
- playerHealth - Vida do jogador.
- armour - Colete do jogador.
- weaponId - Arma atual do jogador.
- additionalKey - Tecla adicional.
- sirenState - Estado da sirene do veículo.
- landingGearState - Estado do trem de pouso (dado também utilizado por veículos como empilhadeira para representar o estado do garfo/forquilha).
- trailerId - ID de trailer anexado ao veículo (0 se nenhum).
- trainSpeed - Velocidade do trem (dado utilizado por trens).
ID_PASSENGER_SYNC (ID: 211) - Um pacote com este identificador numérico é responsável por atualizações do jogador dentro de um veículo (como passageiro). A sua estrutura de dados é a seguinte:
- vehicleId - ID de veículo atual.
seatId - Número do assento atual.
driveBy - 0 se o jogador não estiver em modo de drive-by, caso contrário 1.
weaponId - ID de arma atual.
additionalKey - Tecla adicional.
playerHealth - Vida do jogador.
playerArmour - Colete do jogador.
- lrKey - Seta para esquerda/direita (←→) - Se a tecla atual for seta para esquerda, então lrKey se iguala a KEY_LEFT, caso contrário KEY_RIGHT. 0 se nenhum dos casos.
- udKey - Seta para cima/baixo (↑↓) - Se a tecla atual for seta para cima, então lrKey se iguala a KEY_UP, caso contrário KEY_DOWN. 0 se nenhum dos casos.
- keys - Um mapa (bitmask) com as teclas pressionadas.
position[3] - Posição atual do jogador (X, Y, Z).
ID_AIM_SYNC (ID: 203) - Um pacote com este identificador numérico é responsável por atualizações relacionadas com a câmera/mira do jogador. A sua estrutura de dados é a seguinte:
ID_BULLET_SYNC (ID: 206) - Um pacote com este identificador numérico é responsável por atualizações de tiros/balas disparados por um jogador. A sua estrutura de dados é a seguinte:
ID_TRAILER_SYNC (ID: 210) - Um pacote com este identificador numérico é responsável por atualizações de trailers anexados a veículos sendo utilizados por jogadores. A sua estrutura de dados é a seguinte:
- trailerId - ID do trailer anexado.
- position[3] - Posição atual (X, Y, Z).
- quaternion[4] - Quaterniões de rotação do trailer (W, X, Y, Z).
- velocity[3] - Velocidade nos eixos X, Y e Z.
- angularVelocity[3] - Velocidade angular.
ID_WEAPONS_UPDATE (ID: 204) - Um pacote com este identificador numérico é responsável por atualizações de balas e armas em todas as slots. A sua estrutura de dados é a seguinte:
- slot[12] - Slot.
- arma0[12] - ID da arma.
- balas0[12] - Quantidade de balas.
ID_RCON_COMMAND (ID: 201) - Um pacote com este identificador numérico é responsável por mandar tentativas de comandos rcon para o servidor. Todos os comandos rcons são mandados por esse pacote, até mesmo tentativas de login. A sua estrutura de dados é a seguinte:
- text_length - UINT32 com a quantidade de células do texto do comando.
- cmdtext - Texto do comando.
• Funções Get*.
Citar:Funções Get* (como GetPlayerWeapon) retornam valores que o servidor já tem, sem nenhuma operação I/O. Esses valores são contidos nos dados dos pacotes de sincronização que jogadores enviam para o servidor. Assim que recebidos os dados, os valores são escritos em variáveis nas estruturas internas do servidor em CPlayerPool, assim, a função retornará o valor já presente em uma das variáveis nas estruturas internas.
Após um pacote de sincronização chegar no servidor e ter seus dados escritos nas estruturas internas, a callback OnPlayerUpdate é chamada. O valor retornado na callback OnPlayerUpdate determina se os dados recebidos pelo servidor vão ser transmitidos com outros jogadores ou não, nesse caso retornando 1 permite que os dados sejam transmitidos com outros jogadores após terem sidos salvos nas estruturas internas do servidor, e retornando 0 impedirá a transmissão desses dados.
• Mundos virtuais e processo de "streaming".
Citar:O servidor controla aquilo que será transmitido com o cliente. Outros jogadores só vão ser criados se você estiver a uma certa distância de suas posições atuais e se o mundo virtual for o mesmo, resultando no processo de stream-in com outros clientes.
No processo de stream-in com jogadores, o servidor manda a chamada de procedimento remoto (RPC - Remote Procedure Call) WorldPlayerAdd para seu cliente, criando os outros jogadores em seu cliente e então permitindo que você receba dados de sincronização desses outros clientes. O mesmo serve para veículos e objetos, o processo de stream-in ocorre quando você chega na distância necessária (geralmente uma distância menor que 200.0 no plano X, Y - O valor pode variar, depende de como você definiu stream_distance em server.cfg, mas por padrão é 200.0) e se estiver no mesmo mundo virtual.
Chegando a uma distância superior à stream_distance, os jogadores/veículos/objetos sofrem stream-out, em que são removidos do seu cliente, logo esses jogadores não terão dados de sincronização mandados para você.
O cliente não controla aquilo que será transmitido consigo mesmo, o servidor é responsável por isso baseado em fatores como posição e mundo virtual. O cliente pode chegar ao ponto de modificar a posição resultando no servidor em fazer o processo de stream-in/out, mas, o cliente nunca poderá alterar o mundo virtual, que é totalmente controlado pelo servidor.
No momento que o mundo virtual muda, todo jogador/objeto/carro que está próximo de você e dentro da distância de streaming e não pertencer ao seu mundo virtual, sofrerá o processo de stream-out, e aquilo que ainda não foi transmitido não será. Você estará limitado a outros jogadores/veículos/objetos que estejam no seu mesmo mundo virtual.
• Pool interna de processamento de RPCs.
Citar:Chamadas de procedimento remoto (RPCs - Remote Procedure Calls) tem o objetivo de executar funções internas no cliente. Quando você muda a ação especial de um jogador com a função SetPlayerSpecialAction, o RPC 88 é mandado para o cliente, tendo o ID da ação especial como parâmetro, e logo uma função interna é chamada no cliente e a ação especial muda de acordo com a providenciada na chamada de procedimento remoto.
Antes de uma chamada de procedimento remoto ser enviada, o servidor verifica se o cliente está mandando atualizações para se certificar que não esteja AFK. Se o cliente estiver AFK, os RPCs são colocados em uma pool de processamento interna, e assim que o cliente voltar, os RPCs são removidos da pool e processados, chegando no cliente.
Vamos considerar o seguinte exemplo:
- O servidor manda uma chamada de procedimento remoto para mudar a ação especial do cliente.
- O cliente está pausado, resultando na adição do RPC, na pool interna de processamento.
- O cliente volta, então o RPC é processado e removido da pool de processamento, chegando no cliente.
- O cliente manda a nova ação especial no pacote de sincronização a pé.
- Os dados do pacote são escritos nas variáveis das estruturas internas do servidor.
- OnPlayerUpdate é chamada, e se ela retornar 1, a atualização será transmitida para jogadores dentro da área de streaming.
- GetPlayerSpecialAction retornará o novo ID de ação especial mantido em uma variável em CPlayerPool->CPlayer[id_do_jogador].
• Dessincronização.
Citar:A dessincronização, também conhecida como "relógio travado" por algumas pessoas, é uma grande causa de falsos-positivos em relação a verificações de anti-cheat.
Um jogador sofrendo dessincronização, ainda manda pacotes de atualização para o servidor e recebe eles, mas não vai reagir a alguns RPCs mandados pelo servidor, como 145 (SetPlayerAmmo) com o intuito de atualizar/mudar alguma informação do cliente.
Como o cliente acaba não reagindo a certos RPCs, o mesmo não passará pelo processo de stream in/out que é feito com RPCs, resultando jogadores/veículos/objetos em não serem removidos, mas vão parar de mandar dados de sincronização, resultando em que o jogador dessincronizado veja todos como se estivessem pausados/AFK.
Fazer a detecção de um jogador dessincronizado não é complicado, leve em consideração que ele ainda manda atualizações para o servidor, logo a callback OnPlayerUpdate continua sendo chamada. Você pode fazer a detecção tentando mudar a munição na slot 0 utilizando SetPlayerAmmo, já que os jogadores não vão perceber a mudança de munição em punhos (id 0) ou soco inglês (id 1), e verificar se há alguma diferença de valores com a última atualização.
Créditos ao Jelly23.
RE: Sincronização no SA-MP. - guikommander2 - 01/03/2021
Olha esse vídeo: https://www.youtube.com/watch?v=S5B8-kXiyIY&t=32s
No exato momento 00:06 do vídeo, o jogador que vai jogar a bola do golf clica F para entrar na câmera e tacar a bola de golf.
Eu fiz um sistema de golf igualzinho a esse aí do vídeo. Só que tem só um problema que não consigo solucionar.
Quando eu clico F (no meu sistema de golf) para mirar a bola de golf que nem no vídeo, ao invés do jogador ficar do lado da bola de golf, ele fica encima da bola (Ele só fica do lado da bola quando eu pressiono a tecla para mudar o ângulo da câmera, ou seja, acho que isso é algo relacionado a sincronização, como eu faço pro jogador sincronizar a posição na mesma hora que eu pressiono a tecla F para mirar?)
RE: Sincronização no SA-MP. - guikommander2 - 02/03/2021
Por exemplo, olhe nessa print: Quando eu pressiono F, e não mecho nenhuma tecla, o personagem ele fica assim:
![[Imagem: jyCmlct.png]](https://i.imgur.com/jyCmlct.png)
Quando eu pressiono o botão para virar a câmera, ele fica assim:
![[Imagem: RV6Pqj5.png]](https://i.imgur.com/RV6Pqj5.png)
Como eu faço para o jogador ficar ao lado da bola, como na segunda print, quando eu clicar o F, e não pressionar nenhum botão depois?
RE: Sincronização no SA-MP. - Levi.M - 02/03/2021
Acho que o jogador esta sendo setado pra ficar em cima da bola. Não sei ao certo, pede ajuda na area de suporte, porque isso é apenas um tutorial kk.
RE: Sincronização no SA-MP. - xbruno1000x - 02/03/2021
(02/03/2021 12:40)guikommander2 Escreveu: Por exemplo, olhe nessa print: Quando eu pressiono F, e não mecho nenhuma tecla, o personagem ele fica assim:
![[Imagem: jyCmlct.png]](https://i.imgur.com/jyCmlct.png)
Quando eu pressiono o botão para virar a câmera, ele fica assim:
![[Imagem: RV6Pqj5.png]](https://i.imgur.com/RV6Pqj5.png)
Como eu faço para o jogador ficar ao lado da bola, como na segunda print, quando eu clicar o F, e não pressionar nenhum botão depois?
Sincronização se refere no quesito Player To Player, ou seja, a forma como eu vejo outro player na tela do meu PC. Isso não se aplica quando é você mesmo controlando o jogador. Você cometeu algum erro no código, caso queira ajuda, envie na área de suporte.
RE: Sincronização no SA-MP. - guikommander2 - 03/03/2021
(02/03/2021 20:49)xbruno1000x Escreveu: (02/03/2021 12:40)guikommander2 Escreveu: Por exemplo, olhe nessa print: Quando eu pressiono F, e não mecho nenhuma tecla, o personagem ele fica assim:
![[Imagem: jyCmlct.png]](https://i.imgur.com/jyCmlct.png)
Quando eu pressiono o botão para virar a câmera, ele fica assim:
![[Imagem: RV6Pqj5.png]](https://i.imgur.com/RV6Pqj5.png)
Como eu faço para o jogador ficar ao lado da bola, como na segunda print, quando eu clicar o F, e não pressionar nenhum botão depois?
Sincronização se refere no quesito Player To Player, ou seja, a forma como eu vejo outro player na tela do meu PC. Isso não se aplica quando é você mesmo controlando o jogador. Você cometeu algum erro no código, caso queira ajuda, envie na área de suporte.
O problema não é minha gamemode, Nunca erro, rarissimas vezes que erro.
Acredito que quando eu clico F para mirar com a bola branca do golf, não é enviado um pacote dessa atualização, por isso que não seta o jogador no lugar correto (posso estar errado), Lembrando, eu seto essa animação de mirar com a bola antes de setar a posição (Eu já ajustei os valores da animação para quando finalizar a animação não voltar a posição antiga)
|