Sistema de Log de Jogadores Avançado: Monitoramento Completo no MU
Configure um sistema completo de logs para monitorar ações de jogadores no MU Online: SQL, arquivos de log, alertas automáticos e painel admin.
Por Que um Sistema de Log Avançado é Essencial
Em servidores privados de MU Online, a ausência de logs detalhados torna impossível investigar dupes de itens, acusações entre jogadores e exploits. O sistema padrão do MuServer registra eventos básicos, mas com a configuração correta é possível rastrear cada ação relevante — do drop de um item Excellent até tentativas de speed hack — com timestamp preciso e IP do jogador.
Este tutorial cobre o stack completo: configuração do GameServer, criação de tabelas SQL dedicadas, stored procedures de logging, SQL Jobs para alertas automáticos e boas práticas de retenção de dados.
Passo 1: Habilitar Logs Nativos do GameServer
O arquivo central de configuração fica em GameServer/Data/GS_Config.ini. Abra-o em qualquer editor de texto e localize ou adicione as seguintes chaves na seção [GameServer]:
[GameServer]
; --- Logging ---
LogEnable=1
LogLevel=3
; 1=básico | 2=médio | 3=completo (recomendado para admin)
TradeLog=1
TradeLogLevel=2
DropLog=1
DropLogLevel=2
ChatLog=1
ChatLogLevel=1
; Nível 1 = apenas chat público, 2 = inclui whisper
HackLog=1
PKLog=1
; Diretório de saída dos logs em texto
LogPath=./Log/
Após salvar, reinicie o GameServer. Os arquivos de log serão gerados em GameServer/Log/ com nomenclatura:
GS_YYYYMMDD.log— log geralTrade_YYYYMMDD.log— trocas entre jogadoresDrop_YYYYMMDD.log— drops de itens no chãoHack_YYYYMMDD.log— eventos de segurança
Passo 2: Criar Tabelas SQL para Log Estruturado
Logs em arquivo de texto são difíceis de consultar. A solução é espelhar os eventos críticos em tabelas SQL. Conecte-se ao banco MuOnline via SQL Server Management Studio e execute:
USE MuOnline;
GO
-- Tabela de log de drops de itens
CREATE TABLE Log_ItemDrop (
LogID BIGINT IDENTITY(1,1) PRIMARY KEY,
LogDate DATETIME DEFAULT GETDATE(),
CharName VARCHAR(10) NOT NULL,
AccountID VARCHAR(10) NOT NULL,
MapNumber TINYINT NOT NULL,
MapX SMALLINT NOT NULL,
MapY SMALLINT NOT NULL,
ItemIndex SMALLINT NOT NULL,
ItemLevel TINYINT NOT NULL,
ItemOption TINYINT NOT NULL, -- 0=normal, 4=excellent
ItemSerial BIGINT NOT NULL,
DropType TINYINT NOT NULL, -- 1=chão, 2=trade, 3=warehouse
PlayerIP VARCHAR(20)
);
GO
-- Tabela de log de trades
CREATE TABLE Log_Trade (
LogID BIGINT IDENTITY(1,1) PRIMARY KEY,
LogDate DATETIME DEFAULT GETDATE(),
CharGive VARCHAR(10) NOT NULL,
CharReceive VARCHAR(10) NOT NULL,
ItemIndex SMALLINT NOT NULL,
ItemLevel TINYINT NOT NULL,
ItemOption TINYINT NOT NULL,
ItemSerial BIGINT NOT NULL,
ZenAmount INT DEFAULT 0
);
GO
-- Tabela de alertas para o painel admin
CREATE TABLE T_AdminAlerts (
AlertID INT IDENTITY(1,1) PRIMARY KEY,
AlertDate DATETIME DEFAULT GETDATE(),
AlertType VARCHAR(30) NOT NULL,
CharName VARCHAR(10),
Description VARCHAR(500),
IsRead BIT DEFAULT 0
);
GO
MEMB_INFO e Character do seu banco para confirmar o schema.Passo 3: Stored Procedures para Inserção de Logs
Crie procedures que o GameServer chama via ODBC (em versões que suportam extensão SQL) ou que você executa via triggers. Para servidores que usam extensão de log SQL nativa:
USE MuOnline;
GO
CREATE PROCEDURE WZ_InsertItemDropLog
@CharName VARCHAR(10),
@AccountID VARCHAR(10),
@MapNumber TINYINT,
@MapX SMALLINT,
@MapY SMALLINT,
@ItemIndex SMALLINT,
@ItemLevel TINYINT,
@ItemOption TINYINT,
@ItemSerial BIGINT,
@DropType TINYINT,
@PlayerIP VARCHAR(20)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Log_ItemDrop
(CharName, AccountID, MapNumber, MapX, MapY,
ItemIndex, ItemLevel, ItemOption, ItemSerial, DropType, PlayerIP)
VALUES
(@CharName, @AccountID, @MapNumber, @MapX, @MapY,
@ItemIndex, @ItemLevel, @ItemOption, @ItemSerial, @DropType, @PlayerIP);
END;
GO
CREATE PROCEDURE WZ_InsertTradeLog
@CharGive VARCHAR(10),
@CharReceive VARCHAR(10),
@ItemIndex SMALLINT,
@ItemLevel TINYINT,
@ItemOption TINYINT,
@ItemSerial BIGINT,
@ZenAmount INT = 0
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO Log_Trade
(CharGive, CharReceive, ItemIndex, ItemLevel, ItemOption, ItemSerial, ZenAmount)
VALUES
(@CharGive, @CharReceive, @ItemIndex, @ItemLevel, @ItemOption, @ItemSerial, @ZenAmount);
END;
GO
Passo 4: SQL Job para Detecção de Itens Suspeitos
Configure um SQL Server Agent Job que roda a cada 5 minutos e detecta automaticamente drops de itens com level alto ou opções raras:
- Abra o SQL Server Management Studio
- Expanda SQL Server Agent → clique com botão direito em Jobs → New Job
- Nome:
MU_DetectarDropsSuspeitos - Em Steps → New Step, cole o seguinte script:
USE MuOnline;
GO
-- Detectar drops de itens Level 13+ ou Excellent das últimas 5 min
INSERT INTO T_AdminAlerts (AlertType, CharName, Description)
SELECT
'DROP_SUSPEITO',
d.CharName,
'Drop: Item=' + CAST(d.ItemIndex AS VARCHAR) +
' Lv=' + CAST(d.ItemLevel AS VARCHAR) +
' Opt=' + CAST(d.ItemOption AS VARCHAR) +
' Map=' + CAST(d.MapNumber AS VARCHAR) +
' Pos=(' + CAST(d.MapX AS VARCHAR) + ',' + CAST(d.MapY AS VARCHAR) + ')' +
' IP=' + ISNULL(d.PlayerIP, 'N/A')
FROM Log_ItemDrop d
WHERE d.LogDate >= DATEADD(MINUTE, -5, GETDATE())
AND (d.ItemLevel >= 13 OR d.ItemOption >= 4);
-- Detectar trades com itens Level 15+ (possível dupe)
INSERT INTO T_AdminAlerts (AlertType, CharName, Description)
SELECT
'TRADE_LEVEL15',
t.CharGive,
'Trade: ' + t.CharGive + ' -> ' + t.CharReceive +
' Item=' + CAST(t.ItemIndex AS VARCHAR) +
' Lv=' + CAST(t.ItemLevel AS VARCHAR)
FROM Log_Trade t
WHERE t.LogDate >= DATEADD(MINUTE, -5, GETDATE())
AND t.ItemLevel >= 15;
- Em Schedules → New Schedule: Frequency = Daily, Recurs every 5 minutes
- Clique OK para salvar o Job
msdb.dbo.sp_send_dbmail com o conteúdo de T_AdminAlerts não lidos.Passo 5: Script Batch para Arquivar Logs Antigos
Logs acumulam rapidamente. Crie o arquivo GameServer/LogArchive.bat para compactar e mover logs com mais de 30 dias:
@echo off
REM Arquivo: GameServer/LogArchive.bat
REM Agendar no Agendador de Tarefas do Windows - diariamente às 03:00
set LOG_DIR=C:\MuServer\GameServer\Log
set ARCHIVE_DIR=C:\MuServer\GameServer\Log\Archive
set DAYS_OLD=30
if not exist "%ARCHIVE_DIR%" mkdir "%ARCHIVE_DIR%"
REM Mover logs antigos para pasta de arquivo
forfiles /p "%LOG_DIR%" /s /m *.log /d -%DAYS_OLD% /c "cmd /c move @path %ARCHIVE_DIR%\"
REM Compactar arquivos movidos (requer 7-Zip instalado em C:\Program Files\7-Zip\)
"C:\Program Files\7-Zip\7z.exe" a "%ARCHIVE_DIR%\logs_%date:~6,4%%date:~3,2%%date:~0,2%.7z" "%ARCHIVE_DIR%\*.log" -sdel
echo Arquivamento concluido: %date% %time%
forfiles.Passo 6: Consultas SQL Úteis para Investigação
Use estas queries no dia a dia para investigar denúncias de jogadores:
-- Histórico completo de um jogador nas últimas 24h
SELECT LogDate, DropType, ItemIndex, ItemLevel, ItemOption,
MapNumber, MapX, MapY, PlayerIP
FROM Log_ItemDrop
WHERE CharName = 'NomeDoJogador'
AND LogDate >= DATEADD(HOUR, -24, GETDATE())
ORDER BY LogDate DESC;
-- Verificar se um item serial apareceu em múltiplos jogadores (dupe)
SELECT CharName, LogDate, DropType
FROM Log_ItemDrop
WHERE ItemSerial = 123456789
ORDER BY LogDate;
-- Jogadores com maior volume de drops em itens raros (possível farm bot)
SELECT CharName, COUNT(*) AS TotalDrops
FROM Log_ItemDrop
WHERE ItemLevel >= 10
AND LogDate >= DATEADD(DAY, -7, GETDATE())
GROUP BY CharName
ORDER BY TotalDrops DESC;
-- Alertas não lidos para o painel
SELECT AlertDate, AlertType, CharName, Description
FROM T_AdminAlerts
WHERE IsRead = 0
ORDER BY AlertDate DESC;
-- Marcar alertas como lidos após revisão
UPDATE T_AdminAlerts SET IsRead = 1
WHERE IsRead = 0 AND AlertDate < DATEADD(HOUR, -1, GETDATE());
Manutenção e Retenção de Dados
Manter logs indefinidamente consome espaço em disco e degrada a performance das consultas. Configure uma rotina de limpeza no SQL Server Agent:
-- Job de limpeza mensal: apagar logs com mais de 90 dias
DELETE FROM Log_ItemDrop WHERE LogDate < DATEADD(DAY, -90, GETDATE());
DELETE FROM Log_Trade WHERE LogDate < DATEADD(DAY, -90, GETDATE());
DELETE FROM T_AdminAlerts WHERE AlertDate < DATEADD(DAY, -30, GETDATE()) AND IsRead = 1;
MuOnline_Archive. Isso preserva histórico sem pesar no banco principal.Troubleshooting Comum
GameServer não grava logs em texto: Verifique se a pasta GameServer/Log/ existe e se o processo do GameServer tem permissão de escrita nela. No Windows Server, o usuário que executa o GameServer.exe precisa ter permissão de Modify na pasta Log.
Stored procedure não é chamada: Em MuServers que não suportam extensão SQL nativa para logs, você precisará de um middleware ou parsear os arquivos de texto e inserir via script agendado. Crie um script PowerShell que leia o arquivo GS_YYYYMMDD.log e insira linhas novas no SQL a cada minuto.
Tabela Log_ItemDrop cresceu demais: Execute DBCC SHRINKFILE após a limpeza e recrie o índice: ALTER INDEX ALL ON Log_ItemDrop REBUILD. Isso recupera espaço e mantém performance de consulta.
Perguntas frequentes
Onde o GameServer grava os logs por padrão?
O GameServer grava logs em texto na pasta GameServer/Log/, com arquivos separados por data no formato GS_YYYYMMDD.log. Cada linha contém timestamp, tipo de evento e dados do jogador.
Como habilitar o log de troca de itens entre jogadores?
No arquivo GameServer/Data/GS_Config.ini, defina TradeLog=1 e TradeLogLevel=2 para registrar todos os itens trocados com código serial, nível e opções de cada item.
É possível registrar ações de hack e tentativas de exploit?
Sim. Defina HackLog=1 no GS_Config.ini. Tentativas de packet injection, speed hack e uso de itens inválidos são registradas na tabela Log_HackCheck do banco MuOnline com IP do jogador.
Como criar alertas automáticos quando um jogador dropa itens raros?
Crie um SQL Job no SQL Server Agent que execute a cada 5 minutos consultando a tabela Log_ItemDrop onde ItemLevel >= 13 ou ItemOption = 4 (excelente), e insira alertas na tabela T_AdminAlerts para exibição no painel web.