[Tutorial] Usando MySQL + Cache + ORM
#1

Como muitos sabem, para usar MySQL no SA-MP, й necessбrio o Plugin MySQL.
Hб vбrias versхes atualizadas do MySQL Plugin. Iremos usar, uma das versхes mais atuais do MySQL, e esse tutorial serб funcional em versхes R33 ou superiores.

Versхes R33 ou Superiores, hб sistema de cache e orm.
Bбsicamente, com o sistema de cache, vocк pode efetuar Querys, e armazena-las em variaveis. Assim, podendo ser chamadas/deletadas de acordo com sua necessidade.

Os "ORM"s sгo uma forma mais fбcil de usar o MySQL, evitando variaveis para efetuar Querys. Assim, funcionando de forma atй mais simples e prбtica. Caso queira saber mais sobre ORMs, acesse esse link.

Tуpico do Plugin MySQL by BlueG
Atualmente, estб na versгo R39-2. Vocк pode efetuar o download ou saber versхes em desenvolvimento neste link.

MYSQL
As funзхes do Plugin:
pawn Код:
native mysql_log(E_LOGLEVEL:loglevel = LOG_ERROR | LOG_WARNING, E_LOGTYPE:logtype = LOG_TYPE_TEXT);
native mysql_connect(const host[], const user[], const database[], const password[], port = 3306, bool:autoreconnect = true, pool_size = 2);
native mysql_close(connectionHandle = 1);
native mysql_reconnect(connectionHandle = 1);

native mysql_unprocessed_queries(connectionHandle = 1);
native mysql_current_handle();
native mysql_option(E_MYSQL_OPTION:type, value);

native mysql_errno(connectionHandle = 1);
native mysql_escape_string(const source[], destination[], connectionHandle = 1, max_len = sizeof(destination));
native mysql_format(connectionHandle, output[], len, format[], {Float,_}:...);
native mysql_pquery(connectionHandle, query[], callback[] = "", format[] = "", {Float,_}:...);

native mysql_tquery(connectionHandle, query[], callback[] = "", format[] = "", {Float,_}:...);

native Cache:mysql_query(conhandle, query[], bool:use_cache = true);

native mysql_stat(destination[], connectionHandle = 1, max_len = sizeof(destination));
native mysql_get_charset(destination[], connectionHandle = 1, max_len = sizeof(destination));
native mysql_set_charset(charset[], connectionHandle = 1);
Callback:
pawn Код:
forward OnQueryError(errorid, error[], callback[], query[], connectionHandle);
As nativas principais do Plugin! Sem elas, vocк nгo pode usar nenhuma das citadas abaixo.
Primeiramente, conectar ao banco de dados.

mysql_connect
pawn Код:
new mysql = mysql_connect("host", "usuario", "database", "senha"); //Obrigado Schocc
O valor mysql serб o id da conexгo. Vocк tambйm pode conectar em mais de um hosting, porйm vocк deve separar os ids das conexхes '-'
pawn Код:
new mysql[3];
public OnGameModeInit() {
    mysql[0] = mysql_connect("localhost", "root", "forum_samp", "");
    mysql[1] = mysql_connect("localhost", "root", "servidor", "");
    mysql[2] = mysql_connect("www.meuserver.com", "NicK", "servidor", "uimeututorial");
    return 1;
}
Em uso de funзхes, deve especificar qual conexгo, ou sempre irб ser a primeira.

mysql_close
No caso, isso й para fechar uma conexгo do MySQL. Й mais ъtil usar quando o servidor for desligado/reniciado.
pawn Код:
public OnGameModeExit()
{
    for(new i; i < sizeof(mysql); i++)
        mysql_close(mysql[i]); // Fechando as conexхes do exemplo anterior
    return 1;
}
mysql_escape_string
Isso servirб para retornar um string, sem problemas.
Isso por que, um string onde pode receber quaisquer caractere pode ser prejudicial ao prуprio mysql, ocorrendo o chamado sql-injection. Entгo, usando o mysql_escape_string ele irб corrigir os caracteres que podem atrapalhar uma query.

Exemplo de uso:
pawn Код:
mysql_escape_string(inputtext, APlayerData[playerid][Senha],mysql[1]);
inputtext > Valor que serб convertido.
APlayerData[playerid][Senha] > O valor jб convertido.
mysql[1] > Seria no caso a conexгo do MySQL, dos exemplos acima.

mysql_format
mysql_format basicamente seria o format padrгo do SA-MP, sу que com funзгo extra.
pawn Код:
%e   > escapa um string, nгo necessitando do mysql_escape_string
%s   > insere um string
%d / %i  > insere um valor inteiro
%f   > insere um valor float
%X   > insere um valor hexadecimal em maiъsculo.
%x   > insere um valor hexadecimal em minъsculo.
%b   > insere um nъmero binбrio.
Entгo, posso formatar uma query com mysql_format, sem necessitar usar o mysql_escape_string.
pawn Код:
mysql_format(mysql[1], Query, sizeof(Query), "UPDATE usuarios SET Senha='%e' WHERE ID=%i", APlayerData[playerid][Senha], APlayerData[playerid][MySQL_ID]); //Demostraзгo

mysql_query || mysql_tquery || mysql_pquery
Aparentemente, mysql_tquery e mysql_pquery sгo semelhantes o uso.
Mas, BlueG diz:
Quote:

A diferenзa entre este nativo e mysql_tquery () й que este tipo de consulta usa multi-threading, portanto, й mais rбpido, dependendo de quantas conexхes sгo usadas. O nъmero de conexхes podem ser especificados no mysql_connect () atravйs do parвmetro POOL_SIZE. Cada conexгo se assemelha a um fio.

Esse tipo de consulta nгo suporta transaзхes.

Deu pra entender um pouco o que ele quis dizer.. (****** Tradutor)

mysql_query
Esta funзгo, pode servir para adicionar, atualizar ou selecionar dados!
(Para selecionar dados, deve se usar cache)
Por padrгo o cache й ativo, mas vocк pode desativa-lo, conforme o desejado.
Exemplo 1 (Usando Cache para exibir dados, veja mais a baixo):
pawn Код:
CMD:primeiroregistrado(playerid) {
    new Cache:Temp = mysql_query(mysql[1], "SELECT Nome FROM usuarios ORDER BY ID DESC WHERE LIMIT 1",   true); //Cache local
    if(cache_get_row_count(mysql[1]) > 0) //Se houver um resultado
    {
        new Nome[24], Msg[144];
        cache_get_field_content(0, "Nome", Nome, mysql[1]);
        format(Msg, 144, "{ffff00}O jogador %s й o primeiro registrado do servidor!", Nome);
        SendClientMessage(playerid, -1, Msg);
    }
    else
        SendClientMessage(playerid, -1, "{ff0000}Nгo foi possнvel pegar o primeiro registrado!"); //Coisa que seria meio dificil nй '-'
    cache_delete(Temp, mysql[1]); //Deletar o cache
    return 1;
}
Exemplo 2 (Atualizando dados):
pawn Код:
CMD:mudarsenha(playerid, params[]) {
    if(strlen(params) < 3) return SendClientMessage(playerid, -1, "{ff0000}Sua senha estб pequena!");
    new Query[150], Nome[24];
    GetPlayerName(playerid, Nome, 24);
    mysql_format(mysql[1], Query, 150, "UPDATE usuarios SET Senha='%e' WHERE Nome='%s'", params, Nome);
    mysql_query(mysql[1], Query, false);
    return 1;
}
Exemplo 3: (Inserindo dados):
pawn Код:
CMD:registrarplayer(playerid, params[]) {
    new Nome[24], Senha[128]; //Vou usar a sscanf aqui
    if(sscanf(params, "s[24]s[128]", Nome,Senha)) return SendClientMessage(playerid, -1, "{ff0000}Use: /registrarplayer [nome do jogador] [senha do jogdor]");
    new Query[190], Msg[144];
    mysql_format(mysql[1], Query, sizeof(Query), "INSERT INTO usuarios (Nome,Senha) VALUES ('%e','%e')", Nome, Senha);
    mysql_query(mysql[1], Query, false);
    format(Msg, 144, "{ffff00}Vocк inseriu uma nova conta! Usuбrio: %s, Senha: %s", Nome, Senha);
    SendClientMessage(playerid, -1, Msg);
    return 1;
}
mysql_tquery & mysql_pquery
Estas funзхes necessitam de uma callback de resultado.
Elas nгo usam cache, como a callback mysql_query.
pawn Код:
public OnPlayerConnect(playerid) {
    new Nome[24], Query[128];
    GetPlayerName(playerid, Nome, 24);
    mysql_format(mysql[1], Query, 128, "SELECT * FROM usuarios WHERE Nome='%s'", Nome);
    mysql_tquery(mysql[1], Query, "OnPlayerLogin", "d", playerid);
    return 1;
}
forward OnPlayerLogin(playerid);
public OnPlayerLogin(playerid) {
    if(cache_get_row_count(mysql[1]) == 0) //Nгo registrado
    else // Registrado
    return 1;
}
pawn Код:
public OnPlayerConnect(playerid) {
    new Nome[24], Query[128];
    GetPlayerName(playerid, Nome, 24);
    mysql_format(mysql[1], Query, 128, "SELECT * FROM usuarios WHERE Nome='%s'", Nome);
    mysql_pquery(mysql[1], Query, "OnPlayerLogin", "d", playerid);
    return 1;
}
forward OnPlayerLogin(playerid);
public OnPlayerLogin(playerid) {
    if(cache_get_row_count(mysql[1]) == 0) //Nгo registrado
    else // Registrado
    return 1;
}

Alguma query que ocorrer erro, serб retornado em OnQueryError.


ORM
Acima expliquei basicamente o que й o ORM no MySQL Plugin.
Funзхes:
pawn Код:
native ORM:orm_create(const table[], connectionHandle = 1); //Cria um orm em uma tabela, e sua conexгo do MySQL
native orm_destroy(ORM:id); //Destroi um ORM criado pelo ID

native ORM_Error:orm_errno(ORM:id); // Retorna o erro de um orm pelo id

native orm_apply_cache(ORM:id, row); //Aplica cache em um orm
native orm_select(ORM:id, callback[] = "", format[] = "", {Float, _}:...); //Seleciona e Retorna dados de um ORM

native orm_update(ORM:id); //Atualiza os dados do ORM
native orm_insert(ORM:id, callback[] = "", format[] = "", {Float, _}:...); //Insere dados de um ORM

native orm_delete(ORM:id, bool:clearvars=true); //Deleta um ORM, opcional zerar variaveis usadas

native orm_load(ORM:id, callback[] = "", format[] = "", {Float, _}:...) = orm_select; //Ler um ORM
native orm_save(ORM:id, callback[] = "", format[] = "", {Float, _}:...); //Salva um ORM

native orm_addvar_int(ORM:id, &var, varname[]); //Adiciona uma variavel a um ORM
native orm_addvar_float(ORM:id, &Float:var, varname[]); //Adiciona uma variavel float a um ORM
native orm_addvar_string(ORM:id, var[], var_maxlen, varname[]); //Adiciona uma variavel string a um ORM

native orm_delvar(ORM:id, varname[]); //Deleta uma variavel de um ORM
native orm_setkey(ORM:id, varname[]); //Seta a condiзгo de atualizaзгo/selecionar em ORMs
orm_create*
Cria um novo orm, e irб retornar no id do orm.
Necessбrio especificar a tabela, e a conexгo usada.

orm_destroy*
Destroy um orm criado, atravйs do seu ID.

orm_errno*
Retorna um resultado/erro.

orm_addvar_int*
Aqui adiciona uma variavel (int), e sua respectiva coluna tabela.
Necessбrio adicionar uma variavel global, em casos de adicionar variavel local, deve ocorrer warnings/erros.

orm_addvar_float*
Adiciona uma variavel (float) e sua respectiva coluna na tabela.
Necessбrio adicionar uma variavel global, em casos de adicionar variavel local, deve ocorrer warnings/erros.

orm_addvar_string*
Adiciona uma variavel (string) e sua respectiva coluna na tabela.
Necessбrio adicionar uma variavel global, em casos de adicionar variavel local, deve ocorrer warnings/erros.

orm_setkey*
Seta a condiзгo para atualizaзгo/inserзгo/selecionar dados. (Como se funcionasse "WHERE Nome='meunome'")

orm_update*
Atualiza os dados de um orm criado. Todas as variaveis especificadas, serгo atualizadas na tabela.

orm_select*
Seleciona os dados da tabela, resultando os valores sem suas respectivas variaveis.
Assim, irб resultar se foi com sucesso ou nгo em uma callback, que serб necessбrio especifica-la. (exemplos abaixo)

orm_insert*
Insere os dados na tabela. Nгo й tгo necessбrio especificar a callback onde serб retornado, apenas irб retornar se foi com sucesso ou nгo.

* Hб exemplos.


Exemplos
Necessбrio entender, que usando por exemplo.
pawn Код:
//Exemplo
    orm_addvar_string(ormdid, APlayerData[playerid][Name], 24, "Nome");
    orm_addvar_string(ormdid, APlayerData[playerid][Senha], 128, "Senha");
    orm_addvar_string(ormdid, APlayerData[playerid][Email], 128, "Email");
    orm_addvar_int(ormdid, APlayerData[playerid][Dinheiro], "Dinheiro");
    orm_addvar_int(ormdid, APlayerData[playerid][Scores], "Scores");
    orm_addvar_int(ormdid, APlayerData[playerid][Mortes], "Mortes");
    orm_addvar_int(ormdid, APlayerData[playerid][Matou], "Matou");
    orm_addvar_string(ormdid, APlayerData[playerid][pIP], 16, "IP");
    orm_addvar_string(ormdid, APlayerData[playerid][DataRegistro], 50, "DataRegistro");
    orm_addvar_int(ormdid, APlayerData[playerid][ID], "ID");
   
    orm_setkey(ormdid, "Nome");
Seria o mesmo, se usasse
pawn Код:
new Query[800];
// Selecionar Dados
format(Query, sizeof(Query), "SELECT Nome,Senha,Email,Dinheiro,Scores,Mortes,Matou,IP,DataRegistro,ID FROM usuarios WHERE Nome='%s'",  APlayerData[playerid][Name]);
//Ou atualizar dados
format(Query, sizeof(Query), "UPDATE contas SET Nome='%s',Senha='%s',Email='%s',Dinheiro=%i,Scores=%i,Mortes=%i,Matou=%i,IP='%s',DataRegistro='%s',ID=%i WHERE Nome='%s'", ....);
//Ou inserir dados
format(Query, sizeof(Query), "INSERT INTO usuarios (Nome,Senha,Email,Dinheiro,Scores,Mortes,Matou,IP,DataRegistro,ID) VALUES ('%s','%s','%s',%i,%i,%i,%i,'%s','%s',%i)", ...);
Sу que vocк, usando ORM, vocк decide o que fazer, usando as nativas
pawn Код:
orm_select
orm_update
orm_insert
Usando ORM
Usando os ORM's, й possнvel fazer sistemas de registro/login por exemplo!
pawn Код:
#define DialogLogin 1
#define DialogRegistro 2
new mysql;
enum pInfo //Variaveis do Player
{
    bool:Logado,
    Name[24],
    Senha[128],
    Email[128],
    pIP[16],
    DataRegistro[50],
    Scores,
    Dinheiro,
    Matou,
    Mortes,
    ID, // ID do MySQL
    ORM:OrmID // Teste
};
new APlayerData[MAX_PLAYERS][pInfo]; //Variavel do Player
public OnGameModeInit() //Ao ligar o gamemode
{
    mysql = mysql_connect("localhost", "root", "test", ""); //Conexгo do MySQL, isso й necessбrio
    return 1;
}
public OnGameModeExit() // gamemode desligar
{
    mysql_close(mysql); //Fechar conexгo do  MySQL, й necessбrio, em caso de nгo fechar conexгo do MySQL, em um GMX o servidor pode crashar.
    return 1;
}
public OnPlayerConnect(playerid) //Ao jogador se conectar
{
    GetPlayerName(playerid, APlayerData[playerid][Name], 24); //Pegar o nome do player..
    new ORM:ormdid = APlayerData[playerid][OrmID] = orm_create("usuarios", mysql); //Crio um novo ORM, na tabela "Usuarios" e na conexгo "mysql"
    orm_addvar_string(ormdid, APlayerData[playerid][Name], 24, "Nome"); //Adiciono o string 'Nome' juntamente a variavel Name
    orm_addvar_string(ormdid, APlayerData[playerid][Senha], 128, "Senha"); //Adiciono o string 'Senha' juntamente a variavel Senha..
    orm_addvar_string(ormdid, APlayerData[playerid][Email], 128, "Email"); //merma coisa
    orm_addvar_int(ormdid, APlayerData[playerid][Dinheiro], "Dinheiro"); //Adiciono o inteiro 'Dinheiro' a variavel Dinheiro '-'
    orm_addvar_int(ormdid, APlayerData[playerid][Scores], "Scores"); //merma coisa
    orm_addvar_int(ormdid, APlayerData[playerid][Mortes], "Mortes"); //merma coisa
    orm_addvar_int(ormdid, APlayerData[playerid][Matou], "Matou"); //merma coisa
    orm_addvar_string(ormdid, APlayerData[playerid][pIP], 16, "IP"); //merma coisa '-'
    orm_addvar_string(ormdid, APlayerData[playerid][DataRegistro], 50, "DataRegistro"); //й a mesma
    orm_addvar_int(ormdid, APlayerData[playerid][ID], "ID"); //Isso iremos usar mais a frente
   
    orm_setkey(ormdid, "Nome"); //Seto a condiзгo, como se usasse "WHERE Nome='nomedocara'"
    orm_select(ormdid, "OnPlayerLogin", "d", playerid); //Seleciona os dados e diz o resultado na callback OnPlayerLogin
    return 1;
}
forward OnPlayerLogin(playerid);
public OnPlayerLogin(playerid) {
    if(orm_errno(APlayerData[playerid][OrmID]) == ERROR_OK) //Se houver dados, sinal que o jogador estб registrado
        ShowPlayerDialog(playerid, DialogLogin, DIALOG_STYLE_PASSWORD, "{ff0000} # {ffffff}Login", "Digite sua senha para logar!", "Login", "Cancelar");
    else //Se nгo estiver dados, o jogador nгo estб registrado!
        ShowPlayerDialog(playerid, DialogRegistro, DIALOG_STYLE_INPUT, "{00ff00} # {ffffff}Seja bem vindo novato!", "Digite uma senha para se registrar", "Registrar", "Cancelar");
    orm_setkey(APlayerData[playerid][OrmID], "ID"); //Seta a condiзгo, mesmo nгo havendo registro, ele irб inserir, e o ID serб automaticamente dado ;)
    return 1;
}

public OnPlayerDisconnect(playerid, reason) //Ao sair
{
    if(APlayerData[playerid][Logado] == true) { //Caso esteja logado
        orm_update(APlayerData[playerid][OrmID]); //Atualizar informaзхes
    }
    orm_destroy(APlayerData[playerid][OrmID]);  //Destruir ORM, e isso nгo irб zerar as informaзхes
    for(new pInfo:i; i < pInfo; i++)
        APlayerData[playerid][i] = 0; //dados zerados.
    return 1;
}
public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[]) //Dialogs
{
    switch(dialogid) {
        case DialogLogin: { //Para efetuar login
            if(!response || strlen(inputtext) == 0) return Kick(playerid);
            if(strcmp(APlayerData[playerid][Senha], inputtext, false) != 0) return Kick(playerid);
            APlayerData[playerid][Logado] = true; //Efetuar Login
            GetPlayerIp(playerid, APlayerData[playerid][pIP], 16); //Novo IP
            orm_update(APlayerData[playerid][OrmID]); //Atualizar informaзхes, e incluindo o novo Ip que acabou de se conectar.
            return SendClientMessage(playerid, -1, "{ffff00}Conectado com sucesso ao gamemode de estudos!");
        }
        case DialogRegistro: { //Para efetuar registro
            if(!response || strlen(inputtext) == 0) return Kick(playerid);
            format(APlayerData[playerid][Senha], 128, inputtext); //Senha inserida
            APlayerData[playerid][Logado] = true; //Logado
            new d, m, a;
            GetPlayerIp(playerid, APlayerData[playerid][pIP], 16); //novo ip
            getdate(a, m, d);
            format(APlayerData[playerid][DataRegistro], 50, "%02d/%02d/%d", d, m, a); //Data de registro
            orm_insert(APlayerData[playerid][OrmID], "", ""); //Insere as informaзхes, nгo usei nenhuma callback para inserir, mas poderia atй ter colocado, porйm nгo й tгo necessбrio.
            return SendClientMessage(playerid, -1, "{ffff00}Registrado com sucesso ao gamemode de estudos!");
        }
    }
    return 1;
}
Entendendo
Vamos entender agora de forma mais explicada, pois acima sгo apenas cуdigos.
Em OnPlayerConnect, crio um novo ORM. Assim, esse ORM й respectivo com os dados do jogador que acabou de se conectar.
Ponho as variaveis que sempre receberгo e terгo dados a atualizar.
Seto a condiзгo, que irб pegar a conta que tem o nome do player que conectou. (como se fosse WHERE Nome='%s')
E vai dizer se estб registrado ou nгo, com o tal nome, em OnPlayerLogin.

Em OnPlayerLogin, irб serar a condiзгo, que antes era o Nome, para ID. Assim, o jogador pode atй alterar seu nome, que os dados ainda receberгo atualizaзхes normalmente.
OBS: ERROR_OK = Hб algo. | ERROR_NO_DATA = Nгo hб resultado.

Em OnPlayerDisconnect, irб checar se estб logado ou nгo, e aн, irб atualizar os dados. E nisso, irб deletar o ORM do player, e zerando os dados de todas as variбveis.

CACHE
Usando cache, como o explicado de forma resumida acima, vocк necessita primeiro do uso de funзхes do MySQL mesmo. ORM's nгo sгo necessбrios cache.
Funзхes:
pawn Код:
native cache_get_data(&num_rows, &num_fields, connectionHandle = 1);
native cache_get_row_count(connectionHandle = 1);
native cache_get_field_count(connectionHandle = 1);
native cache_get_field_name(field_index, destination[], connectionHandle = 1, max_len = sizeof(destination));

native cache_get_row(row, field_idx, destination[], connectionHandle = 1, max_len = sizeof(destination));
native cache_get_row_int(row, field_idx, connectionHandle = 1);
native Float:cache_get_row_float(row, field_idx, connectionHandle = 1);

native cache_get_field_content(row, const field_name[], destination[], connectionHandle = 1, max_len = sizeof(destination));
native cache_get_field_content_int(row, const field_name[], connectionHandle = 1);
native Float:cache_get_field_content_float(row, const field_name[], connectionHandle = 1);

native Cache:cache_save(connectionHandle = 1);
native cache_delete(Cache:cache_id, connectionHandle = 1);
native cache_set_active(Cache:cache_id, connectionHandle = 1);
native cache_is_valid(Cache:cache_id, connectionHandle = 1);

native cache_affected_rows(connectionHandle = 1);
native cache_insert_id(connectionHandle = 1);
native cache_warning_count(connectionHandle = 1);

native cache_get_query_exec_time(E_EXECTIME_UNIT:unit = UNIT_MICROSECONDS);
native cache_get_query_string(destination[], max_len = sizeof(destination));
Vendo essas nativas, parece que tudo й difнcil. Porйm, tudo й bem fбcil.

cache_get_data
Retorna o nъmero de resultados, e colunas, da conexгo feita (no caso, de uma query).

cache_get_row_count*
Retorna apenas o nъmero de resultados de uma query, da conexгo indicada.

cache_save
Salva uma query em cache.

cache_delete*
Deleta um cache salvo.

cache_is_valid
Detecta ver se o cache й vбlido.

cache_set_active*
Deixa um cache em modo ativo.
Pode ser usado, para pegar resultados nгo necessбrios em tais momentos.
Por exemplo, para dados que sгo atualizados de tempos em tempos.

cache_get_field_content*
Pega o resultado de uma query, assim vocк especifica o id do resultado (inicial do 0) atй o valor mбximo (que nгo pode ser igual a rows).
Se uma query, retorna 10 rows (10 resultados) as informaзхes dos resultados serгo de 0 atй 9. 10 serб NULL.

cache_get_field_content_int
Semelhante ao cache_get_field_content porйm, o valor serб logo retornado.
pawn Код:
new Scores = cache_get_field_content_int(0, "Scores", mysql);
cache_get_field_content_float
Semelhante ao cache_get_field_content porйm o valor serб logo retornado.
pawn Код:
new Float:pPos[3];
pPos[0] = cache_get_field_content_float(0, "PosX", mysql);
pPos[1] = cache_get_field_content_float(0, "PosY", mysql);
pPos[2] = cache_get_field_content_float(0, "PosZ", mysql);
* Hб exemplos

Exemplos
Vamos supor, que eu quero que pegue o log de banidos de 15 em 15 minutos, uma query serб feita e o resultado serб sempre exibido se eu usar /banidos.

Bбsicamente, eu teria que usar um cache, e um settimer.

pawn Код:
new mysql, Cache:Banidos; //Variavel da conexгo, e do Cache
public OnGameModeInit() {
    mysql = mysql_connect("localhost", "root", "test", ""); //Conexгo do MySQL
    SetTimer("AtualizarListaBanidos", 1000 * 60 * 15, true); // 15 minutos
    return 1;
}
forward AtualizarListaBanidos();
public AtualziarListaBanidos() {
    Banidos = mysql_query(mysql, "SELECT * FROM banidos ORDER BY ID DESC LIMIT 30", true); //Resultados armazenados em "Banidos"
    return 1;
}
CMD:banidos(playerid) {
    cache_set_active(Banidos, mysql); //Seta o cache como ativo.
    if(cache_get_row_count(mysql) == 0) return SendClientMessage(playerid, -1, "{ff0000}Nгo hб pessoas banidas!"); //Caso nгo tenha resultados
    new Lista[1000];
    for(new i; i < cache_get_row_count(mysql); i++) { // Um loop, atй chegar o mбximo de resultados.
        new Nome[24], BanPor[24]; //Variaveis
        cache_get_field_content(i, "Nome", Nome, mysql); //Pega o valor que estava no banco de dados na tabela 'Nome' e pхe na variavel Nome
        cache_get_field_content(i, "BanAdmin", BanPor, mysql); //Pega o valor que estava tambйm no banco de dados  na tabela 'BanAdmin' e pхe na variavel BanPor
        format(Lista, sizeof(Lista), "%s%s banido por %s\n", Nome, BanPor);
    }
    format(Lista, sizeof(Lista), "Mostrando %i banidos\n\n%s", cache_get_row_count(mysql), Lista); //"Mostrando 30 banidos, e logo abaixo todos os resultados
    ShowPlayerDialog(playerid, 25000, DIALOG_STYLE_MSGBOX, "{ff0000}# {ffffff}Banidos", Lista, "Fechar", "");
    return 1;
}
Cуdigo de exemplo acima. Que tal agora, um sistema de ranking, que seja atualizado de 10 em 10 minutos?
pawn Код:
new mysql, Cache:RankDemo;
public OnGameModeInit() {
    mysql = mysql_connect("localhost", "root", "test", "");
    SetTimer("AtualizarRanking", 1000 * 60 * 10, true); //10 minutos
    return 1;
}
forward AtualizarRanking();
public AtualizarRanking() {
    RankDemo = mysql_query(mysql, "SELECT Nome,Scores FROM usuarios ORDER BY Scores DESC LIMIT 10", true);
    /*
    Irб ordenar o resultado dos que tem mais scores para os que tem menos.
    Irб limitar o resultado em 10, ou seja, os 10 que tem maior quantidade de scores.
    */

    return 1;
}
CMD:rank(playerid) {
    cache_set_active(RankDemo, mysql);
    if(cache_get_row_count(mysql) == 0) return SendClientMessage(playerid, -1, "{ff0000}Nada encontrado!");
    new Lista[800];
    for(new i; i < cache_get_row_count(mysql); i++) {
        new Nome[24], Score;
        cache_get_field_content(i, "Nome", Nome, mysql);
        Score = cache_get_field_content_int(i, "Scores", mysql);
        format(Lista, sizeof(Lista), "%s%iє - %s - Scores: %i", i+1, Nome, Score);
    }
    ShowPlayerDialog(playerid, 25000, DIALOG_STYLE_MSGBOX, "{ff0000}# {ffffff}Exibindo ranking!", Lista, "Ok", "");
    return 1;
}
Lembrando que o plugin pode receber atualizaзхes, e algumas callbacks podem ser sim removidas ou alteradas. Sempre dк uma olhada nas nativas.
Caso nгo tenha entendido algo do tуpico, por favor, diga e eu tentarei tirar sua dъvida.

Muitas callbacks nгo foram utilizadas neste tutorial, por nгo serem necessбrias atй certo ponto.
A Wiki explica basicamente o funcionamento de cada nativa do Plugin. (Link)


Espero que tenha entendido, e lhe ajudado!

Tutoriais semelhantes ao uso do MySQL:
[Tutorial] Criando um sistema em MySQL
[Tutorial] Usando MySQL

Vocк deve entender como й o MySQL!
Tenha um conhecimento em SQL, pesquise, estude! Este tutorial destaca funзхes do MySQL Plugin (para versхes R33 e superiores).

* Caso tenha dъvidas, comente no tуpico que tentarei lhe explicar..
Reply
#2

o mysql foi um dos motivos para eu entrar para o sa-mp pois vi como um modo de treinar para minhas aplicaзхes

achei o tutorial super informatico so tem 1 coisa que me incomoda... nessa comunidade vi que vcs tem a mania de usar "getar" e "setar" verbos que nao existem a impressгo e q vcs tentam abrasileirar o verbo "get" e "set" do ingles. ao meu ver isso fica bem estranho e sem nexo para o portugues. poderia trocar isso para "pegar", "capturar", "informar", "colocar" ou algo do genero


#edit
ponha tbm as video aulas do joaopedro como topicos aconselhaveis. foi o primeiro tutorial q vi de mysql pra sa-mp e consegui perfeitamente aplicar
Reply
#3

Quote:
Originally Posted by WooPz
Посмотреть сообщение
o mysql foi um dos motivos para eu entrar para o sa-mp pois vi como um modo de treinar para minhas aplicaзхes

achei o tutorial super informatico so tem 1 coisa que me incomoda... nessa comunidade vi que vcs tem a mania de usar "getar" e "setar" verbos que nao existem a impressгo e q vcs tentam abrasileirar o verbo "get" e "set" do ingles. ao meu ver isso fica bem estranho e sem nexo para o portugues. poderia trocar isso para "pegar", "capturar", "informar", "colocar" ou algo do genero
Questгo de costume mesmo.
Reply
#4

Parabйns, уtimo tutorial.

+Rep
Reply
#5

parabens belo tutorial!!
Reply
#6

Quote:
Originally Posted by ProKillerpa
Посмотреть сообщение
Parabйns, уtimo tutorial.

+Rep
Quote:
Originally Posted by Caio_Freeze
Посмотреть сообщение
parabens belo tutorial!!
Opa, obrigado
Reply
#7

Sem duvida o ORM veio facilitar e melhorar muito as coisas.

esta muito bem explicado.

Parabens, +rep.
Reply
#8

Quote:
Originally Posted by PT
Посмотреть сообщение
Sem duvida o ORM veio facilitar e melhorar muito as coisas.

esta muito bem explicado.

Parabens, +rep.
Valeu PT. *-*

#Off
e.e teu REP vale quanto? 6? OMG
que delнcia cara!
Reply
#9

Nossaaaaaaaa Foda *.* #Rep

pawn Код:
if(cache_get_row_count(mysql[1]) == 0) //Nгo registrado
Poderia Retornar Rows mysql_num_rows Para Poder Ver se o Sujeito Tem ou Nгo Conta Banco de Dados?

pawn Код:
new TopicoDelicia = mysql_num_rows();
if(!TopicoDelicia)
{
SendClientMessage(playerid,-1, " Voce nгo tem uma Conta vlh ");
}
if(TopicoDelicia)
{
SendClientMessage(playerid,-1," Voce tem Uma Conta logae parзaa ");
}
Tipo Isso?
Reply
#10

Quote:
Originally Posted by WooPz
Посмотреть сообщение
o mysql .. aplicar
vc me lembra uma pessoa ^^
espero que seja apenas impressгo !


@уtimo tutorial ...
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)