Aula 06 - Aprofundando-se em Comandos
Vamos nos aprofundar um pouco mais no assunto "Comandos" (0x334) e iremos conhecer o "Chat", que é o que o player digita (0x333).
Sempre quando mandamos um comando pelo client, o sevidor recebe em forma de packet. O packet é desencriptado pelo servidor e a DLL que a gente usa, lê o packet desencriptado e com uma função, ele interpreta-o.
A tal função para interpretá-lo é a Commands_Game. Com essa função, podemos criar qualquer tipo de comando. A informação do comando digitado é mandada para o pServer->eCommand. Com a informação do comando digitado, podemos fazer a comparação do comando digitado com um comando que você queria utilizar com strcmp();. - strcmp reference O comando strcmp compara duas strings e se forem iguais retorna 0.
Depois de compararmos, e ela for zero, temos um bloco de comandos do tamanho que quisermos, fazendo o que quisermos dentro do jogo (desde que você tenha todas as funções para exercer o que quer, poderá fazer qualquer coisa).
Na aula 4 (quatro) aprendemos como adicionar um novo comando. Agora iremos aprender a pegar parâmetros nele. Como por exemplo: caso eu queira criar o comando /move teríamos também que pegar também as coordenadas, correto? E você tem ideia de como fazer isso?
Para fazermos isso, teremos que usar uma função da biblioteca cstdio.h. A função se chama sscanf();. Com essa, poderemos "escanear" a string (parâmetro 1) de acordo com o formato (parâmetro 2) e registra nos parâmetros adicionais. Nossa string "escaneada" seria o pServer->eValue os parâmetros adicionais serão o que vamos aprender. Um exemplo é mais fácil para aprendermos.
No caso do comando move teríamos que escanear dois argumentos tipo integer. Ficaria assim:
Temos que declarar sempre a quantidade de variáveis que vão ser escaneadas. Se precisamos de 3 argumentos para o comando, temos que declarar para variáveis. É claro que um tipo de variável é diferente de outro. Então, caso você vá precisar pegar um texto nesse escaneamento, você deve declarar variáveis tipo char.
E o que são os %d %d?
São o que vai ser escaneado. Digamos assim: o pServer->eValue (chamarei daqui por diante de eValue apenas) retorna o valor APÓS o comando, ou seja, "/item eValue" e cada %d siginifica o que será armazenado numa variável. Se temos o move, temos então /move 2100 2100. São duas variáveis. No caso, duas %d. Os %d serão armazenados respectivamente. Se o 1° %d tem referência para X, nos parâmetros adicionais teremos que botar o 1° como X.
Lista de tipos de variáveis:
(Fonte: cplusplus.com - Traduzido e reescrito por Shepher)
Bom, caso tenha entendido, para criarmos um texto em que captura o nome do personagem, deveremos usar qual tipo de variável?
Bem simples, você não acha?
Para fazermos isso, teremos que usar uma função da biblioteca cstdio.h. A função se chama sscanf();. Com essa, poderemos "escanear" a string (parâmetro 1) de acordo com o formato (parâmetro 2) e registra nos parâmetros adicionais. Nossa string "escaneada" seria o pServer->eValue os parâmetros adicionais serão o que vamos aprender. Um exemplo é mais fácil para aprendermos.
No caso do comando move teríamos que escanear dois argumentos tipo integer. Ficaria assim:
int x, y;sscanf(pServer->eValue, "%d %d", &x, &y);Temos que declarar sempre a quantidade de variáveis que vão ser escaneadas. Se precisamos de 3 argumentos para o comando, temos que declarar para variáveis. É claro que um tipo de variável é diferente de outro. Então, caso você vá precisar pegar um texto nesse escaneamento, você deve declarar variáveis tipo char.
E o que são os %d %d?
São o que vai ser escaneado. Digamos assim: o pServer->eValue (chamarei daqui por diante de eValue apenas) retorna o valor APÓS o comando, ou seja, "/item eValue" e cada %d siginifica o que será armazenado numa variável. Se temos o move, temos então /move 2100 2100. São duas variáveis. No caso, duas %d. Os %d serão armazenados respectivamente. Se o 1° %d tem referência para X, nos parâmetros adicionais teremos que botar o 1° como X.
Lista de tipos de variáveis:
Tipo
|
O que é?
|
Tipo de argumento
|
%c
|
Texto simples: lê apenas
um caractere. Se o tamanho for maior que um, a variável é armazenado no local
especificado passado no argumento numa matriz
|
char *
|
%d
|
Número decimal: Número
opcional precedido de + ou -
|
int *
|
%e %E %f %g %G
|
Ponto flutuante (float): Número
decimal contendo um ponto decimal, opcionalmente precedido de + ou – e opcionalmente
precedido por um e ou E caracteres e um número decimal. Dois exemplos válidos
são: -732.103 e 7.12e4
|
float *
|
%o
|
Octagonal integer
|
int *
|
%s
|
Cadeia de caracteres: Esse
tipo de sscanf lê todos os caracteres até encontrar um espaço (espaço são
considerados brancos, novas linhas e tabs)
|
char *
|
%u
|
Unsigned decimal integer
|
unsigned int *
|
%x %X
|
Hexadecimal
|
int *
|
Resposta :
Você acertou? Parabéns!
E agora, como ficaria no sscanf?
Bom, com isso podemos já pegar variáveis tipo char e int. E se o nosso caso não for até um espaço em branco, e sim uma vírgula, ou até achar uma nova linha?
Teremos que usar a sequencia [^caractere]; Como funciona?
Caso quisermos até encontrar um sinal de igualdade, fica:
Sacou? Outro exemplo, agora até uma nova linha:
Isso fará com que ele carregue até achar uma nova linha!
Tá e aí, tínhamos falado do comando /move não vamos fazê-lo?
Calma aí. Estávamos aprendendo tudo sobre sscanf antes. Agora vamos partir.
Primeiramente, pensaremos, como sempre! O que um comando /move precisa?
Caso você tenha lido todas as aulas, conseguirá fazer. E a resolução está aqui:
E agora, como ficaria no sscanf?
char nick[96]; // ** OBS abaixosscanf(pServer->eValue, "%s", nick);Importante **: Para variáveis tipo char devemos sempre por um valor acima de 48, pois quando uma matriz passa de seu limite, ocorre overflow (sobrecarrega e o servidor fecha). Se botassemos 12, que é o tamanho de um nick, e uma pessoa digitasse por exemplo: VOUCAUSARCRASHNOSEUSERVIDORMANÉ iria causar um crash, porque a variável nick guarda apenas 13 caracteres (contagem de 0~12) e como a digita é maior que isso, causaria overflow.
Bom, com isso podemos já pegar variáveis tipo char e int. E se o nosso caso não for até um espaço em branco, e sim uma vírgula, ou até achar uma nova linha?
Teremos que usar a sequencia [^caractere]; Como funciona?
Caso quisermos até encontrar um sinal de igualdade, fica:
char nick[96]; // Lembre-se da obs acimasscanf(pServer->eValue, "%[^=]", nickSacou? Outro exemplo, agora até uma nova linha:
char nick[96];sscanf(pServer->eValue, "%[^\n]", nickIsso fará com que ele carregue até achar uma nova linha!
Tá e aí, tínhamos falado do comando /move não vamos fazê-lo?
Calma aí. Estávamos aprendendo tudo sobre sscanf antes. Agora vamos partir.
Primeiramente, pensaremos, como sempre! O que um comando /move precisa?
Pegar as coordenadas digitadasVerificar se foi digitado as duas coordenadas (x e y)Comparar com os limites do servidor (aula 2) se for menor que os limites e maior que 0, teleporta.Caso você tenha lido todas as aulas, conseguirá fazer. E a resolução está aqui:
Resolução :
Chat (0x333)
O tal "chat" é o que é digitado normalmente, e não como um comando. Ou seja, é você falando com outro player. O nome da sua funções é Commands_Say();. Bom, não há muito o que explicar.
O que é escrito vem no pServer->eChat. Se você, por exemplo, usar strcmp e digitar UP TEAM (exemplo da própria DLL) irá comparar apenas o início, e não tudo. E caso for escrito isso, você pode fazer qualquer coisa.
Um exemplo para os novos usuários, é um filtro de palavrões. O que seria? Nada mais do que se você digitar uma palavra feia, você irá fazer com que mostre uma mensagem para o player. Mas não só no início do que foi digitado, mas sim no meio de tudo. Utilizando a função strstr(); que compara a string 2 com a string 1. Se não for encontrado a string 2 na string 1, retorna NULL.
O código ficaria o seguinte:
char Palavroes[7][10] = {{"porra"}, {"merda"}, {"cacete"}, {"bosta"}, {"vtnc"}, {"viado"}, {"puto"}}; for(int i; i<8;i++) if(strstr(pServer->eChat, Palavroes[i]) != NULL) { SendClientMsg(clientid, "Lave a boca com sabão!"); return; }![]() |
| Filtro de palavrões - Shepher |
Finalizando
Bom, galera. Esse foi nossa aula mais extensa. E vou fechando por aqui. Fiquem com Deus!

Nenhum comentário:
Postar um comentário