3 hours ago
(This post was last modified: 3 hours ago by NullSablex.)
🦀 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
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.mp — MySQL_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 aliases — zero 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
🇬🇧 Questions, suggestions and bug reports are welcome — here or on GitHub issues.
⭐ github.com/NullSablex/mysql_samp
