Servidores de Jogos

Salvando dados de jogadores: dinheiro, inventário e posição

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

  1. Ao sair (onPlayerQuit);
  2. Periodicamente (ex.: a cada 5 minutos), para não perder muito em caso de crash;
  3. Imediatamente em operações críticas: compras caras, transferências, venda de propriedades;
  4. 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.

Compartilhar:

Pronto para hospedar seu próximo projeto?

VPS com painel pré-instalado em 1 clique. Ativação imediata.

Ver planos VPS