Salvando dados de jogadores: dinheiro, inventário e posição
Perder dinheiro ou itens por causa de um crash é uma das maiores frustrações dos jogadores. Um sistema de salvamento bem feito evita isso.
O que salvar
- Dinheiro (em mãos e no banco);
- Posição, interior e dimensão;
- Vida, colete, skin;
- Inventário;
- Emprego, facção, nível, tempo de jogo;
- Armas e munição (se o servidor permitir).
Estrutura
Dados simples em colunas da tabela de personagens:
CREATE TABLE personagens (
id INT AUTO_INCREMENT PRIMARY KEY,
conta_id INT NOT NULL,
nome VARCHAR(32) NOT NULL,
dinheiro BIGINT NOT NULL DEFAULT 0,
banco BIGINT NOT NULL DEFAULT 0,
x FLOAT, y FLOAT, z FLOAT,
interior INT DEFAULT 0, dimensao INT DEFAULT 0,
vida FLOAT DEFAULT 100,
skin INT DEFAULT 0,
INDEX (conta_id)
) DEFAULT CHARSET=utf8mb4;
Inventário em tabela separada (uma linha por item):
CREATE TABLE inventario (
personagem_id INT NOT NULL,
item VARCHAR(32) NOT NULL,
quantidade INT NOT NULL,
PRIMARY KEY (personagem_id, item)
);
Mantenha os dados na memória
Durante o jogo, guarde os dados em tabelas Lua no servidor e trabalhe com eles ali. Ir ao banco a cada mudança pequena gera carga desnecessária.
Quando salvar
- Ao sair (
onPlayerQuit); - Periodicamente (ex.: a cada 5 minutos), para não perder muito em caso de crash;
- Imediatamente em operações críticas: compras caras, transferências, venda de propriedades;
- Ao parar o resource (
onResourceStop).
addEventHandler("onPlayerQuit", root, function()
salvarPersonagem(source)
dados[source] = nil
end)
setTimer(function()
for jogador in pairs(dados) do
salvarPersonagem(jogador)
end
end, 5 * 60 * 1000, 0)
Transações para operações críticas
Transferências entre jogadores devem atualizar os dois lados juntos. No MySQL, use transações (START TRANSACTION / COMMIT) ou atualizações atômicas:
UPDATE personagens SET banco = banco - ? WHERE id = ? AND banco >= ?
Verifique se a linha foi afetada antes de creditar o outro lado.
Evite duplicação
Exploits de duplicação costumam explorar salvamentos fora de ordem (sair do jogo no meio de uma troca, crash forçado). Por isso:
- Salve ambos os lados de uma troca imediatamente;
- Bloqueie ações durante o processamento;
- Registre logs de transações para auditoria.
Backups
Mesmo com tudo certo, faça backups frequentes do banco — veja o post "Backups de banco de dados para servidores de MTA".
Hospede seu servidor com a VittHost
Todos os planos MTASA-BR da VittHost incluem 1 banco MySQL. Servidores no Brasil, painel Pterodactyl, proteção DDoS, downloads acelerados por nginx dedicado e teste grátis de 3 dias.