Scripts úteis para Game Master em lote no servidor de MU Online
Automatize tarefas repetitivas de Game Master no seu servidor de MU Online com scripts em lote: distribuição de itens, banimentos, resets em massa, limpeza de contas inativas e anúncios programados.
Administrar um servidor de MU Online com centenas ou milhares de contas ativas torna inviável executar cada ação de moderação, evento ou manutenção manualmente, uma conta por vez. Scripts de GM em lote resolvem esse gargalo, permitindo distribuir prêmios de evento para uma lista de vencedores, banir
Administrar um servidor de MU Online com centenas ou milhares de contas ativas torna inviável executar cada ação de moderação, evento ou manutenção manualmente, uma conta por vez. Scripts de GM em lote resolvem esse gargalo, permitindo distribuir prêmios de evento para uma lista de vencedores, banir contas por padrão de comportamento, resetar personagens em massa ou limpar contas inativas com um único comando revisado e auditável. Este tutorial reúne os scripts mais úteis para o dia a dia de administração, com o cuidado que ações em lote exigem — porque um UPDATE sem WHERE correto pode destruir a economia do servidor em segundos.
Por que centralizar ações de GM em scripts
Ações feitas manualmente, comando por comando, têm três problemas: são lentas em escala, não deixam rastro de auditoria confiável e são inconsistentes entre GMs diferentes. Um script versionado resolve os três: roda em segundos sobre milhares de linhas, grava log de cada ação, e qualquer GM autorizado executa da mesma forma. A regra de ouro é sempre rodar a versão SELECT do filtro antes da versão UPDATE/DELETE, conferindo o número de linhas afetadas.
Pré-requisitos
- Acesso de leitura e escrita ao banco de dados do servidor (MSSQL ou MySQL, dependendo do emulador).
- Backup recente do banco antes de qualquer execução em lote.
- Uma tabela de auditoria (
GMActionLogou equivalente) para registrar quem executou o quê e quando. - Ambiente de teste/staging com uma cópia do banco para validar scripts novos antes de rodar em produção.
Estrutura de log de auditoria
Antes de qualquer script em lote, garanta que existe uma tabela para registrar as ações administrativas:
CREATE TABLE GMActionLog (
LogId INT IDENTITY(1,1) PRIMARY KEY,
GMAccount VARCHAR(50) NOT NULL,
ActionType VARCHAR(50) NOT NULL,
TargetAccount VARCHAR(50) NULL,
Details VARCHAR(500) NULL,
ExecutedAt DATETIME DEFAULT GETDATE()
);
Toda ação em lote descrita abaixo deve terminar com um INSERT nessa tabela, mesmo que o resto do script seja simples.
Script 1 — Distribuição de itens em lote (prêmio de evento)
Para entregar um item a uma lista de vencedores de evento sem repetir comando por comando:
-- Conferência antes de executar
SELECT AccountID, CharacterName FROM Character
WHERE CharacterName IN ('Jogador1','Jogador2','Jogador3');
-- Distribuição (exemplo MuEMU/IGCN, ajuste tabela conforme emulador)
INSERT INTO WarehouseItems (AccountID, ItemIndex, ItemLevel, ItemOptions, Durability)
SELECT AccountID, 168, 15, 0, 255
FROM Character
WHERE CharacterName IN ('Jogador1','Jogador2','Jogador3');
INSERT INTO GMActionLog (GMAccount, ActionType, Details)
VALUES ('admin_root', 'ITEM_DISTRIBUTION', 'Premio evento verao - 3 contas');
Evite entregar itens direto no inventário do personagem online — prefira o warehouse (baú), que não exige que o jogador esteja deslogado.
Script 2 — Prevenção de entrega duplicada
Para eventos recorrentes, controle quem já recebeu o prêmio com uma tabela de log dedicada:
CREATE TABLE ItemDistributionLog (
AccountID VARCHAR(50),
EventCode VARCHAR(50),
DistributedAt DATETIME DEFAULT GETDATE(),
PRIMARY KEY (AccountID, EventCode)
);
-- Entrega apenas para quem ainda não recebeu
INSERT INTO WarehouseItems (AccountID, ItemIndex, ItemLevel)
SELECT c.AccountID, 168, 15
FROM Character c
WHERE c.CharacterName IN ('Jogador1','Jogador2')
AND NOT EXISTS (
SELECT 1 FROM ItemDistributionLog d
WHERE d.AccountID = c.AccountID AND d.EventCode = 'VERAO2026'
);
Esse padrão evita o erro clássico de rodar o script duas vezes por engano e duplicar prêmios valiosos.
Script 3 — Banimento em lote por padrão de comportamento
Para banir contas que compartilham características suspeitas (ex. mesmo IP com múltiplas contas farmando bot):
-- Conferência: quantas contas serão afetadas
SELECT AccountID, LastIP, LastLoginDate FROM Account
WHERE LastIP IN ('203.0.113.10','203.0.113.11') AND BanStatus = 0;
-- Banimento
UPDATE Account
SET BanStatus = 1, BanReason = 'Uso de bot - IP compartilhado suspeito'
WHERE LastIP IN ('203.0.113.10','203.0.113.11') AND BanStatus = 0;
INSERT INTO GMActionLog (GMAccount, ActionType, Details)
VALUES ('admin_root', 'BAN_BATCH', 'Ban por IP suspeito - 2 IPs, ver SELECT anterior');
Sempre filtre por BanStatus = 0 para não reprocessar contas já banidas e poluir o log.
Script 4 — Reset em massa de personagens (evento de reset gratuito)
Para um evento de reset gratuito limitado a personagens acima de determinado nível:
-- Conferência
SELECT Name, cLevel, ResetCount FROM Character WHERE cLevel >= 400;
-- Reset em massa
UPDATE Character
SET cLevel = 1, Experience = 0, LevelUpPoint = 0,
ResetCount = ResetCount + 1,
Strength = 30, Dexterity = 30, Vitality = 30, Energy = 30
WHERE cLevel >= 400;
INSERT INTO GMActionLog (GMAccount, ActionType, Details)
VALUES ('admin_root', 'MASS_RESET', 'Evento reset gratuito - cLevel >= 400');
Os valores base de atributo (Strength, Dexterity etc.) variam por classe — ajuste a query com um CASE por classe se o seu servidor não usa atributos base uniformes.
Script 5 — Limpeza de contas inativas
Para identificar e opcionalmente arquivar contas sem login há muito tempo, liberando nomes de personagem e espaço em banco:
-- Identificar contas inativas há mais de 365 dias
SELECT AccountID, LastLoginDate FROM Account
WHERE LastLoginDate < DATEADD(DAY, -365, GETDATE());
-- Marcar (não excluir diretamente) para arquivamento
UPDATE Account
SET AccountStatus = 'ARCHIVED_CANDIDATE'
WHERE LastLoginDate < DATEADD(DAY, -365, GETDATE()) AND AccountStatus = 'ACTIVE';
Nunca faça DELETE direto de contas antigas em um único passo — marque para arquivamento, aguarde um período de carência (30-60 dias) anunciado publicamente, e só então exclua ou mova para uma tabela de histórico.
Script 6 — Anúncios programados no servidor
Para notificar jogadores sobre manutenção ou eventos sem depender de um GM digitando na hora certa, use uma tabela de anúncios lida por um serviço agendado:
CREATE TABLE ScheduledAnnouncements (
Id INT IDENTITY(1,1) PRIMARY KEY,
Message VARCHAR(500),
ScheduledTime DATETIME,
Sent BIT DEFAULT 0
);
INSERT INTO ScheduledAnnouncements (Message, ScheduledTime)
VALUES ('Manutenção em 30 minutos - salve seu progresso', DATEADD(MINUTE, 30, GETDATE()));
Um serviço externo (job agendado) consulta essa tabela a cada minuto e envia a mensagem via pipe de comando do GameServer quando ScheduledTime chega, marcando Sent = 1 para não repetir.
Boas práticas ao rodar scripts em lote
| Prática | Por quê |
|---|---|
| Sempre rodar SELECT antes do UPDATE/DELETE | Confirma o número de linhas afetadas antes de comprometer dados |
| Rodar primeiro em staging/cópia do banco | Evita descobrir um erro de lógica direto em produção |
| Registrar toda ação na tabela de auditoria | Permite investigar reclamações e reverter decisões com contexto |
Usar transações (BEGIN TRAN/COMMIT) | Permite ROLLBACK imediato se o resultado não bater com o esperado |
| Nunca dar acesso de execução a todos os GMs | Reduz risco de erro ou abuso; centralize scripts sensíveis em poucos admins |
Usando transações para reduzir risco
Envolver o script em uma transação permite conferir o resultado antes de confirmar:
BEGIN TRAN;
UPDATE Account SET BanStatus = 1 WHERE LastIP = '203.0.113.10';
-- Confira o resultado
SELECT * FROM Account WHERE LastIP = '203.0.113.10';
-- Se estiver correto:
COMMIT;
-- Se algo estiver errado:
-- ROLLBACK;
Esse padrão é especialmente valioso para ações irreversíveis como banimento e reset em massa, onde um erro de filtro custa caro.
Organizando os scripts em um repositório
Assim como o código do servidor, os scripts de GM devem ser versionados. Uma estrutura simples:
gm-scripts/
├── eventos/
│ ├── reset-gratuito-2026-07.sql
│ └── premio-verao.sql
├── moderacao/
│ ├── ban-por-ip.sql
│ └── limpeza-inativos.sql
└── README.md
Cada arquivo deve conter, em comentário, a data de uso, o GM responsável e o resultado esperado (quantas linhas afetadas). Isso transforma scripts avulsos em um histórico auditável da administração do servidor.
Erros comuns e soluções
| Sintoma | Causa provável | Solução |
|---|---|---|
| Item entregue em dobro | Script rodado duas vezes sem checagem de log | Adicione tabela de controle de distribuição (Script 2) |
| Contas erradas banidas | Filtro do WHERE mais amplo do que o pretendido | Sempre rode o SELECT de conferência antes do UPDATE |
| Reset afetou personagens que não deveriam | Faixa de nível ou classe mal filtrada | Ajuste o WHERE e valide com SELECT em staging primeiro |
| Perda de dados após DELETE em massa | Ausência de backup imediatamente anterior | Sempre faça backup e prefira marcar para arquivamento a excluir direto |
| Anúncio programado não disparou | Serviço agendado não está rodando ou tabela não é lida | Verifique o job/cron responsável e o pipe de comando do GameServer |
Checklist antes de rodar um script de GM em lote
- Backup do banco feito imediatamente antes da execução.
- Versão SELECT do filtro rodada e conferida.
- Script testado em staging ou cópia do banco.
- Transação (BEGIN TRAN) usada para ações irreversíveis.
- Ação registrada na tabela de auditoria (GMActionLog).
- Script versionado no repositório de scripts de GM.
- Acesso de execução restrito a administradores autorizados.
Com esses scripts organizados e auditáveis, o próximo passo natural é integrá-los ao pipeline de manutenção do servidor como um todo — veja o tutorial de criação de servidor de MU Online para entender como esse fluxo administrativo se encaixa na operação completa.
Perguntas frequentes
É seguro rodar scripts SQL diretamente em produção para ações de GM?
Só com backup imediatamente anterior e um teste prévio em staging ou em uma cópia do banco. Ações em lote (UPDATE/DELETE sem WHERE preciso) são a causa mais comum de acidentes graves em servidores de MU — sempre rode primeiro um SELECT com os mesmos filtros para conferir quantas linhas serão afetadas.
Esses scripts substituem os comandos de GM in-game?
Não totalmente. Comandos in-game (como /additem ou /ban) são melhores para ações pontuais e para GMs sem acesso técnico ao banco. Scripts em lote fazem sentido quando a ação afeta dezenas ou centenas de contas de uma vez, o que seria inviável comando por comando.
Como evitar que um script de distribuição de itens duplique entregas?
Registre cada entrega em uma tabela de log (ex. ItemDistributionLog) com o ID da conta e o ID do evento, e faça o script verificar essa tabela antes de inserir o item novamente. Isso também serve como auditoria caso um jogador reclame que não recebeu o prêmio.
Posso agendar esses scripts para rodar sozinhos?
Sim, usando o SQL Server Agent (MSSQL) ou um cron job que chama um script que executa a query. É comum para tarefas como limpeza de contas inativas ou reset de eventos diários, mas ações sensíveis (banimento, remoção de item) devem manter aprovação manual antes da execução.
Qual o risco de dar reset em massa em todos os personagens?
Se a query não filtrar corretamente por nível mínimo ou classe, você pode resetar personagens que não deveriam, causando perda de builds e reclamações em massa. Sempre rode o SELECT de conferência antes e avise a comunidade com antecedência sobre a janela de manutenção.