Como configurar anti-dupe (duplicação de itens) no MU Online
Entenda como surgem os bugs de duplicação de itens no MU Online e configure defesas em camadas — serial único, transações atômicas, cooldowns e detecção automática — para blindar a economia do seu servidor.
Duplicação de itens — o famoso dupe — é o problema de segurança que mais destrói servidores de MU Online. Diferente de um simples cheat de dano ou velocidade, que afeta um jogador, o dupe ataca o coração do servidor: a economia. Um único item raro duplicado em massa vira dezenas de Excellent na mão
Duplicação de itens — o famoso dupe — é o problema de segurança que mais destrói servidores de MU Online. Diferente de um simples cheat de dano ou velocidade, que afeta um jogador, o dupe ataca o coração do servidor: a economia. Um único item raro duplicado em massa vira dezenas de Excellent na mão de poucos, os preços em Jewel e Zen colapsam, o mercado perde referência e os jogadores honestos, sentindo que o esforço não vale nada, simplesmente abandonam o jogo. Configurar anti-dupe não é ligar uma opção mágica no arquivo de configuração; é montar uma defesa em camadas que torna a duplicação impossível ou, no mínimo, imediatamente detectável. Este tutorial avançado mostra como pensar e implementar cada camada.
Antes de qualquer configuração, é preciso entender a causa raiz. Praticamente todo dupe nasce da mesma falha conceitual: uma operação que move um item é tratada como duas operações independentes — "adicionar no destino" e "remover da origem" — em vez de uma operação única e indivisível. Se o servidor adiciona o item ao baú, envia a confirmação, e só depois grava a remoção do inventário, existe uma janela de milissegundos em que o item vive nos dois lugares. Um jogador mal-intencionado força uma desconexão exatamente nessa janela (puxando o cabo de rede, usando um lag switch ou explorando um timeout) e o servidor persiste apenas o estado parcial: o item no baú permanece, e o inventário é restaurado do último save, onde o item ainda estava lá. Duas cópias. O anti-dupe, no fundo, é a disciplina de eliminar todas essas janelas.
Pré-requisitos
- Acesso administrativo ao GameServer e aos seus arquivos de configuração (
GameServerInfo,.ini,.datou equivalentes do seu emulador). - Acesso ao banco de dados (SQL Server ou MySQL, conforme o emulador) com permissão para criar tabelas, índices, triggers e stored procedures.
- Conhecimento do esquema do seu emulador: como os itens são armazenados (blob hexadecimal no inventário/warehouse, ou tabela normalizada com serial).
- Ambiente de teste isolado — nunca calibre anti-dupe direto em produção. Restaure um backup em uma máquina separada.
- Ferramenta de consulta SQL (SSMS, HeidiSQL, DBeaver) e, idealmente, acesso ao código-fonte do emulador se for open-source.
> Aviso: todos os nomes de tabela, coluna e configuração citados (warehouse, Serial, T_ItemSerial, TradeLock, Money) são exemplos de emuladores da linha Season 6 e derivados. Os nomes reais variam por season e por emulador. Confirme o mapeamento no seu ambiente antes de executar qualquer comando que altere dados.
Se você ainda está montando a base do servidor, o guia de como criar servidor de MU Online cobre a instalação do GameServer e do SGBD antes de você chegar à camada de segurança.
As camadas de defesa anti-dupe
Não existe uma bala de prata. Um anti-dupe robusto empilha defesas independentes, de modo que, se uma falhar, a próxima segura o golpe. Pense em cinco camadas.
| Camada | O que faz | Onde atua |
|---|---|---|
| 1. Serial único | Garante que cada item tenha identidade irrepetível | Banco de dados |
| 2. Transações atômicas | Torna mover item uma operação tudo-ou-nada | GameServer + banco |
| 3. Cooldowns e locks | Fecha as janelas de tempo exploráveis | GameServer |
| 4. Validação de origem | Rejeita itens sem procedência legítima | GameServer |
| 5. Detecção e alerta | Encontra dupes que passaram pelas camadas anteriores | Banco (auditoria) |
As três primeiras camadas previnem; as duas últimas detectam. Um servidor maduro tem todas. Vamos configurar cada uma.
Camada 1: serial único por item
A defesa mais forte contra dupe é dar a cada item uma identidade irrepetível. Se todo item Excellent carrega um número de série único no banco, duas cópias com o mesmo serial são prova matemática de duplicação — não há como argumentar. Muitos emuladores modernos já suportam isso; se o seu não suporta nativamente, dá para adicionar uma tabela de rastreamento.
O conceito é manter uma tabela central de seriais emitidos:
-- Exemplo (nomes variam por emulador)
CREATE TABLE T_ItemSerial (
Serial BIGINT NOT NULL PRIMARY KEY,
ItemCode INT NOT NULL, -- tipo do item (ex.: Espada, Set)
OwnerChar VARCHAR(10) NULL, -- personagem dono atual
OriginType TINYINT NOT NULL, -- 1=drop, 2=craft, 3=evento, 4=GM
CreatedAt DATETIME NOT NULL DEFAULT GETDATE(),
Active BIT NOT NULL DEFAULT 1
);
CREATE UNIQUE INDEX IX_ItemSerial_Serial ON T_ItemSerial(Serial);
Toda vez que o servidor cria um item raro (drop de boss, craft, entrega de evento), ele reserva um serial novo nessa tabela. A chave primária e o índice único garantem que o banco recusa a inserção de um serial repetido. Se, por causa de um bug de dupe, o servidor tentar persistir dois itens com o mesmo serial, o segundo INSERT falha e o erro vira alerta imediato. Este é o pilar: transforme a unicidade em uma restrição do banco, não em uma verificação opcional do código.
Quando o item é destruído (falha de refinamento, venda para NPC, expiração), marque Active = 0 em vez de apagar a linha — assim você preserva a trilha histórica para auditoria.
Camada 2: transações atômicas
Esta é a camada que ataca a causa raiz. Toda operação que move um item entre dois lugares (inventário ↔ warehouse, trade entre jogadores, drop no chão ↔ inventário) precisa ser atômica: ou acontece por completo, ou não acontece de forma alguma. Nada de estados intermediários persistidos.
No nível do banco, isso significa envolver a operação em uma transação com bloqueio adequado:
BEGIN TRANSACTION;
-- Trava as linhas envolvidas para ninguém mais mexer
SELECT * FROM warehouse WITH (UPDLOCK, ROWLOCK)
WHERE AccountID = @acc;
-- Remove da origem
UPDATE Inventory SET ItemSlot = NULL
WHERE CharID = @char AND Slot = @slotOrigem AND Serial = @serial;
-- Adiciona no destino
UPDATE warehouse SET Items = @novoBlob
WHERE AccountID = @acc;
-- Se qualquer passo falhar, tudo é desfeito
COMMIT TRANSACTION;
O ponto crucial é que o GameServer também precise cooperar: ele não pode enviar a confirmação ao cliente antes do COMMIT. A ordem correta é sempre: remover da origem, adicionar no destino, confirmar no banco e só então avisar o cliente. Se a conexão cair no meio, a transação sofre rollback e o item volta a existir em um único lugar — a origem. Nenhuma cópia é criada. Em emuladores open-source, procure no código as funções de MoveItem, WarehouseSave e TradeComplete e garanta que elas sigam essa sequência.
Camada 3: cooldowns e locks
Muitos dupes exploram a velocidade: o jogador executa a mesma ação dezenas de vezes por segundo, ou combina duas ações no mesmo instante, esperando pegar o servidor em um estado inconsistente. Cooldowns e locks fecham essas janelas.
Configure, no GameServer:
- Trade lock — enquanto uma janela de troca está aberta e sendo confirmada, os itens envolvidos ficam bloqueados para qualquer outra operação. O jogador não pode, ao mesmo tempo, colocar o item na troca e movê-lo para o baú.
- Warehouse lock — abrir o baú bloqueia movimentações de inventário por uma fração de segundo até a sincronização terminar. Isso impede o clássico "abrir baú e desconectar".
- Cooldown de drop/pickup — um intervalo mínimo entre soltar e pegar o mesmo item, para evitar o dupe de "dropar no chão e desconectar".
- Limite de operações por segundo — um teto de trades, movimentações de baú ou drops por janela de tempo. Um humano legítimo não faz 40 trades em um segundo; um script de dupe faz.
Exemplo de configuração (nomes ilustrativos):
[AntiDupe]
TradeLockMs = 800
WarehouseSyncLockMs = 500
DropPickupCooldownMs = 1500
MaxTradesPerMinute = 20
MaxWarehouseOpsPerMinute = 60
Comece com valores folgados para não punir jogadores legítimos e aperte gradualmente observando os logs de rejeição. Cooldowns agressivos demais geram falso positivo e reclamação; folgados demais deixam a janela aberta. O ponto de equilíbrio varia por season e por perfil de servidor.
Camada 4: validação de origem
Todo item que aparece no banco deveria ter uma procedência explicável: caiu de um monstro, foi craftado, veio de um evento ou foi dado por um GM. Um item sem origem registrada é suspeito por definição. Com a tabela T_ItemSerial da Camada 1, você pode cruzar cada item ativo com sua origem e sinalizar os órfãos.
A validação de origem também protege contra injeção via cliente modificado. Um cliente hackeado pode tentar mandar ao servidor "eu tenho este item Excellent" que nunca existiu. Se o GameServer valida que todo item recebido do cliente tem serial conhecido na tabela de emissão, ele rejeita o item forjado. A regra é dura e simples: o servidor nunca confia no que o cliente diz ter — ele confere contra sua própria fonte de verdade.
Camada 5: detecção e alerta
Nenhuma prevenção é perfeita. A última camada assume que algo passou e procura ativamente. Uma query agendada que roda a cada hora pode caçar seriais duplicados:
-- Detecta itens ativos com serial repetido = dupe
SELECT Serial, COUNT(*) AS Copias
FROM T_ItemSerial
WHERE Active = 1
GROUP BY Serial
HAVING COUNT(*) > 1;
Se o seu emulador não usa serial, a detecção vira estatística: volume de um item raro acima do total já dropado, mesmo item Excellent surgindo em várias contas no mesmo intervalo, picos anômalos de Jewel em contas específicas. Configure um job (SQL Agent, cron ou Task Scheduler) que roda essas queries e dispara um alerta — e-mail, webhook de Discord — quando qualquer indicador estoura o limiar. Detectar em uma hora, e não em uma semana, é a diferença entre remover três itens e ter que reverter a economia inteira.
Passo a passo de implementação
- Restaure um backup em ambiente de teste isolado. Nunca calibre em produção.
- Mapeie o esquema: descubra como seu emulador guarda itens e se há serial nativo.
- Crie a tabela de seriais (
T_ItemSerialou equivalente) e o índice único. - Instrumente a criação de itens para emitir serial em todo drop raro, craft e evento.
- Audite as funções de movimentação no GameServer e garanta atomicidade (remover → adicionar → commit → avisar cliente).
- Configure cooldowns e locks com valores folgados no
[AntiDupe]. - Ative a validação de origem rejeitando itens sem serial conhecido.
- Agende as queries de detecção e conecte a um canal de alerta.
- Teste os cenários de ataque: simule desconexão durante trade, spam de operações, injeção de item forjado.
- Suba para produção com monitoramento reforçado nas primeiras 48 horas.
Erros comuns e soluções
| Erro | Sintoma | Solução |
|---|---|---|
| Confiar só no cliente | Itens forjados aparecem no banco | Mover toda validação para o GameServer |
| Operação não atômica | Dupes surgem após lag/desconexão | Envolver movimentação em transação; avisar cliente só após commit |
| Sem serial único | Impossível provar duplicação | Criar tabela de seriais com índice único |
| Cooldown agressivo demais | Jogadores reclamam de trade travado | Afrouxar valores e monitorar logs de rejeição |
| Detecção manual e esporádica | Dupe só é visto após colapso do mercado | Agendar queries horárias com alerta automático |
| Apagar dupe sem investigar | Trilha de auditoria perdida, inocente punido | Congelar conta, exportar evidência, só então remover |
Checklist de lançamento
- Backup restaurado em ambiente de teste isolado
- Esquema de itens do emulador mapeado (com ou sem serial nativo)
- Tabela de seriais criada com índice único
- Emissão de serial ativa em drop, craft e evento
- Funções de movimentação auditadas e atômicas
- Cooldowns e locks configurados com valores folgados
- Validação de origem rejeitando itens sem serial
- Queries de detecção agendadas e conectadas a alerta
- Cenários de ataque simulados e barrados
- Monitoramento reforçado nas primeiras 48h em produção
Anti-dupe não é um produto que se instala, é uma postura de arquitetura: toda operação com item é tratada como potencialmente hostil até prova de atomicidade e procedência. Empilhe as cinco camadas, calibre com paciência e sua economia resistirá aos ataques que derrubam servidores despreparados.
Perguntas frequentes
O que é exatamente um dupe de itens no MU Online?
É qualquer falha que faz um item existir em duas cópias quando deveria existir em uma. Acontece quando uma operação de transferência (trade, warehouse, drop) não é atômica: o item é adicionado ao destino antes de ser removido da origem, e uma desconexão no meio do caminho deixa as duas cópias. O anti-dupe existe para tornar essas operações indivisíveis.
Preciso de serial único por item para ter anti-dupe?
É a defesa mais forte, mas não a única. Se o seu emulador já grava serial por item, use-o como chave de unicidade — dois itens com o mesmo serial são prova direta de dupe. Se o emulador guarda itens como blobs sem serial, você depende de transações atômicas, cooldowns e detecção estatística. O ideal é combinar as camadas.
O anti-dupe pode ser feito só no cliente?
Não. O cliente é território do jogador e pode ser modificado. Toda validação que importa precisa acontecer no GameServer e no banco de dados. Checagens no cliente servem apenas para reduzir tráfego e melhorar a experiência; a autoridade é sempre do servidor.
Ativar anti-dupe agressivo pode travar trades legítimos?
Pode, se os cooldowns e locks forem mal calibrados. Um lock de warehouse muito longo ou um limite de trades por minuto muito baixo gera falso positivo e reclamação. Comece com valores folgados, monitore os logs de rejeição e aperte aos poucos até achar o equilíbrio entre segurança e fluidez.
Já tenho itens duplicados no banco. O anti-dupe resolve isso?
Não retroativamente. O anti-dupe impede novas duplicações a partir do momento em que é ativado. Os dupes já existentes precisam ser caçados com auditoria SQL e removidos manualmente. Ative a defesa primeiro para estancar a sangria, depois limpe o passivo.