• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Plugin] mysql_samp — MySQL support for SA-MP and open.mp, now featuring an open.mp-style API
#1
🦀 mysql_samp 1.3.0

MySQL para SA-MP e open.mp — o mesmo binário nos dois
MySQL for SA-MP and open.mp — the same binary on both


Download · GitHub · Documentação

Quote:🇧🇷 Um plugin MySQL escrito em Rust, com 75 natives e nenhuma dependência para instalar. O novo desta versão: a API inteira também está disponível na convenção de nomes do open.mpMySQL_Connect, Cache_GetRowCount, ORM_Create — para quem não quer snake_case no meio do gamemode.

🇬🇧 A MySQL plugin written in Rust, with 75 natives and nothing to install alongside it. New in this release: the whole API is also available in open.mp's naming convention — for anyone who doesn't want snake_case in the middle of their gamemode.



📦 Instalar é copiar um arquivo / Installing is copying one file

🇧🇷 Não há libmysqlclient para caçar na versão certa, nem Boost, nem OpenSSL no sistema. O protocolo do MySQL e o TLS estão compilados dentro do binário. Você joga o .so ou o .dll na pasta e acabou — inclusive em host compartilhado, onde você não instala pacote nenhum.

🇬🇧 No libmysqlclient to hunt down, no Boost, no system OpenSSL. The MySQL protocol and TLS are compiled into the binary. Drop the .so or .dll in and you're done — including on shared hosting, where you install nothing.

🇧🇷 E é um binário só para os dois servidores:
🇬🇧 And it's one binary for both servers:
  • SA-MP — 🇧🇷 em plugins/, nome no server.cfg / 🇬🇧 in plugins/, name in server.cfg
  • open.mp nativo — 🇧🇷 em components/. É encontrado sozinho, sem mexer no config.json / 🇬🇧 in components/. Auto-discovered, no config.json entry
  • open.mp legacy — 🇧🇷 o mesmo arquivo em plugins/, declarado em legacy_plugins / 🇬🇧 same file in plugins/, listed under legacy_plugins



🆕 A novidade da 1.3.0: a API no estilo open.mp
New in 1.3.0: the API in open.mp style

🇧🇷 Quem desenvolve para open.mp escreve CreateVehicle, GetPlayerName, TogglePlayerControllable. Aí chega a parte do banco de dados e o código vira mysql_connect, cache_get_row_count. Funciona, mas destoa.

🇬🇧 If you develop for open.mp you write CreateVehicle, GetPlayerName. Then the database part arrives and the code turns into mysql_connect, cache_get_row_count. It works, but it clashes.

🇧🇷 A partir desta versão existe um segundo include com todas as 75 natives na convenção Prefixo_PascalCase:
🇬🇧 From this release there's a second include with all 75 natives in Prefix_PascalCase:

Code:
// mysql_samp.inc                    // mysql_samp_omp.inc
mysql_connect(...)                  MySQL_Connect(...)
mysql_query(...)                    MySQL_Query(...)
cache_get_row_count()                Cache_GetRowCount()
orm_create(...)                      ORM_Create(...)
mysql_hash_password(...)            MySQL_HashPassword(...)

🇧🇷 São apelidos de Pawn (native MySQL_Connect(...) = mysql_connect;) — nenhum custo em tempo de execução, nada muda no plugin, é o mesmo binário. O include é gerado a partir do outro a cada build, então os dois nunca ficam fora de sincronia: native nova aparece nos dois automaticamente.

🇬🇧 They're Pawn aliaseszero runtime cost, nothing changes plugin-side, same binary. The include is generated from the other one on every build, so the two can never drift.

Quote:🇧🇷 Os dois includes são alternativas, não camadas: escolha um por script. Quem já usa o <mysql_samp> não precisa mudar nada — nenhuma native foi removida ou renomeada.
🇬🇧 The two includes are alternatives, not layers: pick one per script. Existing code needs no change — nothing was removed or renamed.

📖 Documentação no editor / Docs in the editor
🇧🇷 Junto com isso, as 75 natives ganharam bloco JavaDoc (@param, @return) direto no include. Num editor que renderize isso — como a extensão PawnPro para VS Code — você passa o mouse sobre a função e lê a descrição e o que cada parâmetro espera, sem abrir o .inc para conferir a ordem dos argumentos. Em editor que não renderize, o comentário continua lá, legível como texto.
🇬🇧 The 75 natives also got JavaDoc blocks in the include. In an editor that renders them — such as the PawnPro extension for VS Code — hover a function and read the description and what each parameter expects. In editors that don't, it's still readable as a comment.



🔧 O que o plugin faz / What the plugin does

🇧🇷 Para quem está chegando agora, o conjunto completo:
🇬🇧 For anyone arriving now, the full set:

🇧🇷 Nenhuma query trava o servidor / 🇬🇧 No query stalls the server
🇧🇷 Não existe versão síncrona na API. mysql_query roda em thread separada e entrega os callbacks na ordem em que você pediu; mysql_pquery entrega assim que cada uma termina, sem ordem garantida.
🇬🇧 There is no synchronous version in the API. mysql_query runs off-thread and delivers callbacks in submission order; mysql_pquery delivers as each finishes.

Code:
mysql_query(g_mysql, "SELECT id, nome FROM contas LIMIT 10", "OnContasCarregadas", "");

forward OnContasCarregadas();
public OnContasCarregadas()
{
    new nome[MAX_PLAYER_NAME];
    for (new i = 0, rows = cache_get_row_count(); i < rows; i++)
    {
        cache_get_value_name(i, "nome", nome);
        printf("conta: %s", nome);
    }
    return 1;
}

🇧🇷 ORM: a tabela vira variável / 🇬🇧 ORM: the table becomes a variable
🇧🇷 Você registra as variáveis do gamemode como colunas e usa orm_select / orm_save. Sem escrever SELECT e UPDATE à mão para cada campo de conta.
🇬🇧 Register your gamemode variables as columns, then use orm_select / orm_save.

Code:
new ormId = orm_create("contas", g_mysql);
orm_addvar_int(ormId, gPlayerId[playerid], "id");
orm_addvar_int(ormId, gDinheiro[playerid], "dinheiro");
orm_addvar_string(ormId, gNome[playerid], MAX_PLAYER_NAME, "nome");
orm_setkey(ormId, "nome");

orm_select(ormId, "OnContaCarregada", "d", playerid);  // preenche as variáveis
// ... e no logout:
orm_save(ormId);                                      // INSERT ou UPDATE sozinho

🇧🇷 Senha de jogador com Argon2id / 🇬🇧 Player passwords with Argon2id
🇧🇷 mysql_hash_password e mysql_verify_password rodam fora da thread do servidor — hash forte não trava o tick. O texto puro nunca entra numa query, então nunca entra num log.
🇬🇧 Both run off the server thread — strong hashing doesn't stall the tick. The plaintext never reaches SQL, so it never reaches a log.

Code:
mysql_hash_password(senhaDigitada, "OnSenhaGerada", "d", playerid);

forward OnSenhaGerada(const hash[], playerid);
public OnSenhaGerada(const hash[], playerid)  // guarde este hash no banco

🇧🇷 Prepared statements / 🇬🇧 Prepared statements
🇧🇷 Para qualquer coisa digitada pelo jogador. Os valores vão pelo protocolo binário do MySQL: não há string montada, então não há escape para errar.
🇬🇧 For anything a player typed. Values go over MySQL's binary protocol: no string is assembled, so there's no escaping to get wrong.

Code:
new stmt = mysql_stmt_new(g_mysql, "SELECT id FROM contas WHERE nome = ?");
mysql_stmt_bind_str(stmt, nomeDigitado);
mysql_stmt_execute(stmt, "OnContaEncontrada", "d", playerid);

🇧🇷 E ainda / 🇬🇧 And also
  • 🇧🇷 Transações / 🇬🇧 Transactions — 🇧🇷 lote atômico: ou todos os passos entram, ou nenhum entra / 🇬🇧 atomic batch: all steps or none
  • 🇧🇷 Cache de resultados / 🇬🇧 Result cache — 🇧🇷 pilha automática dentro do callback, ou guardado à mão com cache_save, inclusive múltiplos resultados de stored procedure / 🇬🇧 automatic stack, or kept manually with cache_save
  • 🇧🇷 Credenciais fora do código / 🇬🇧 Credentials out of the source — 🇧🇷 mysql_connect_file lê de um .ini que seu repositório não precisa carregar / 🇬🇧 read from an .ini your repo doesn't have to carry
  • 🇧🇷 Scripts .sql / 🇬🇧 .sql scripts — 🇧🇷 mysql_query_file executa o arquivo inteiro, em ordem, sem bloquear / 🇬🇧 runs the whole file, in order, non-blocking
  • 🇧🇷 TLS embutido / 🇬🇧 Built-in TLS — 🇧🇷 com CA fixa, TLS mútuo e verificação de certificado ligada por padrão / 🇬🇧 CA pinning, mTLS, verification on by default
  • 🇧🇷 Log próprio / 🇬🇧 Its own log — 🇧🇷 logs/mysql.log com o detalhe do erro; no console fica só a mensagem curta, sem dado sensível / 🇬🇧 full detail in the file, short message on the console



🎯 Começando / Getting started

🇧🇷 Baixe o binário da sua plataforma e o include que preferir — os dois são 32 bits, como o servidor. Depois:
🇬🇧 Download the binary for your platform and the include you prefer — both are 32-bit, like the server. Then:

Code:
#include <a_samp>
#include <mysql_samp>        // ou <mysql_samp_omp>, no estilo open.mp

new g_mysql;

public OnGameModeInit()
{
    g_mysql = mysql_connect("127.0.0.1", "root", "senha", "meu_banco");

    if (mysql_errno() != MYSQL_OK)
    {
        print("[MySQL] falha ao conectar - veja logs/mysql.log");
        return 1;
    }
    return 1;
}

🇧🇷 O passo a passo por servidor, os caminhos de include e o que fazer quando algo não conecta estão na página de instalação.
🇬🇧 Per-server steps, include paths and troubleshooting are on the installation page.



📚 Links
  • Documentação — 🇧🇷 conexão, queries, cache, ORM, opções e segurança / 🇬🇧 connection, queries, cache, ORM, options, security
  • Referência da API — 🇧🇷 as 75 natives, uma a uma / 🇬🇧 all 75 natives
  • Guia de migração — 🇧🇷 para quem vem de outro plugin MySQL / 🇬🇧 coming from another MySQL plugin
  • CHANGELOG — 🇧🇷 o que mudou em cada versão / 🇬🇧 what changed in each release

🇧🇷 Este projeto não é afiliado, endossado nem patrocinado pelo SA-MP ou pelo open.mp. "SA-MP", "open.mp" e "MySQL" pertencem a seus respectivos donos e são citados apenas para descrever compatibilidade.
🇬🇧 This project is not affiliated with, endorsed by, or sponsored by SA-MP or open.mp. "SA-MP", "open.mp", and "MySQL" are trademarks of their respective owners and are mentioned solely to describe compatibility.


🇧🇷 Dúvidas, sugestões e relatos de bug são bem-vindos — aqui no tópico ou nas issues.
🇬🇧 Questions, suggestions and bug reports are welcome — here or on GitHub issues.


⭐ github.com/NullSablex/mysql_samp
  Reply