O maior portal de MU Online do Brasil — desde 2003
Tutorial Avançado Servidor

Como integrar o site e o jogo no servidor de MU Online

Integre o site PHP com o banco SQL Server do servidor de MU Online — criar conta no site que registra no jogo, ranking real de personagens, painel de controle de conta e sistema de VIP pelo site.

EQ Equipe ViciadosMU · Atualizado em 1 jul 2026 · ⏱ 22 min de leitura
Resposta rápida

A integração entre o site e o jogo no MU Online é feita através de conexão direta ao banco SQL Server que o MuServer usa. O site PHP lê e escreve diretamente nas tabelas do jogo — não há API intermediária.

A integração entre o site e o jogo no MU Online é feita através de conexão direta ao banco SQL Server que o MuServer usa. O site PHP lê e escreve diretamente nas tabelas do jogo — não há API intermediária.

Arquitetura de integração

SITE (PHP/Apache)                JOGO (MuServer)
        │                               │
        │  PDO + sqlsrv driver          │
        └─────────────────────────┐     │
                                  ▼     ▼
                          SQL SERVER (banco MuOnline)
                          ├── MEMB_INFO    (contas)
                          ├── Character    (personagens)
                          ├── Character_Items (inventário)
                          └── MEMB_VIP     (VIP)

O site e o GameServer compartilham o mesmo banco. Quando o site cria uma conta na MEMB_INFO, ela imediatamente fica disponível para login no jogo.

Configurar o driver sqlsrv no PHP

No Linux (Ubuntu/Debian) com PHP 8.x

# Instalar ODBC driver da Microsoft para SQL Server
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/22.04/prod.list \
     > /etc/apt/sources.list.d/mssql-release.list

sudo apt update
sudo ACCEPT_EULA=Y apt install -y msodbcsql17 unixodbc-dev

# Instalar extensão PHP sqlsrv
sudo pecl install sqlsrv pdo_sqlsrv

# Habilitar no PHP
echo "extension=sqlsrv.so"     | sudo tee -a /etc/php/8.1/apache2/php.ini
echo "extension=pdo_sqlsrv.so" | sudo tee -a /etc/php/8.1/apache2/php.ini

# Reiniciar Apache
sudo systemctl restart apache2

# Verificar
php -m | grep sqlsrv

No Windows (AppServ/XAMPP)

  1. Baixe o driver em github.com/microsoft/msphpsql/releases — escolha a versão correta para seu PHP (ex: php_sqlsrv_83_ts_x64.dll para PHP 8.3 Thread-Safe 64-bit);
  2. Copie para a pasta ext/ do PHP (ex: C:\AppServ\php\ext\);
  3. Edite o php.ini:

``ini extension=php_sqlsrv_83_ts_x64.dll extension=php_pdo_sqlsrv_83_ts_x64.dll ``

  1. Reinicie o Apache.

Configuração de conexão com o banco

<?php
// config/db-muserver.php

define('MU_SQL_SERVER',   '(local)');        // IP ou nome do SQL Server
define('MU_SQL_DATABASE', 'MuOnline');
define('MU_SQL_USER',     'mu_app');          // usuário SQL dedicado
define('MU_SQL_PASSWORD', 'SenhaMuApp@2026!');

function getMuDB() {
    static $conn = null;
    
    if ($conn === null) {
        $conn = sqlsrv_connect(MU_SQL_SERVER, [
            'Database'                  => MU_SQL_DATABASE,
            'UID'                       => MU_SQL_USER,
            'PWD'                       => MU_SQL_PASSWORD,
            'CharacterSet'              => 'UTF-8',
            'ReturnDatesAsStrings'      => true,
            'MultipleActiveResultSets'  => true,
        ]);
        
        if ($conn === false) {
            error_log("Erro SQL Server: " . print_r(sqlsrv_errors(), true));
            throw new RuntimeException('Erro ao conectar ao banco do servidor MU');
        }
    }
    
    return $conn;
}

// Alternativa com PDO (sqlsrv driver)
function getMuPDO(): PDO {
    static $pdo = null;
    
    if ($pdo === null) {
        $dsn = "sqlsrv:Server=" . MU_SQL_SERVER . ";Database=" . MU_SQL_DATABASE;
        $pdo = new PDO($dsn, MU_SQL_USER, MU_SQL_PASSWORD, [
            PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
            PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        ]);
    }
    
    return $pdo;
}

Criar conta no site com registro no jogo

<?php
// registro.php — criar conta no site e no jogo simultaneamente

require 'config/db-muserver.php';

function registrarConta(string $login, string $senha, string $email): array {
    // Validação básica
    if (strlen($login) < 4 || strlen($login) > 10) {
        return ['sucesso' => false, 'erro' => 'Login deve ter 4-10 caracteres'];
    }
    
    if (!preg_match('/^[a-zA-Z0-9]+$/', $login)) {
        return ['sucesso' => false, 'erro' => 'Login: apenas letras e números'];
    }
    
    if (strlen($senha) < 6) {
        return ['sucesso' => false, 'erro' => 'Senha deve ter no mínimo 6 caracteres'];
    }
    
    $conn = getMuDB();
    
    // Verificar se login já existe
    $checkStmt = sqlsrv_prepare($conn,
        "SELECT COUNT(*) FROM MEMB_INFO WHERE memb_id = ?",
        [[$login, SQLSRV_PARAM_IN]]
    );
    sqlsrv_execute($checkStmt);
    sqlsrv_fetch($checkStmt);
    $existe = sqlsrv_get_field($checkStmt, 0);
    
    if ($existe > 0) {
        return ['sucesso' => false, 'erro' => 'Este login já está em uso'];
    }
    
    // Criptografar senha (SQL Server usa SHA2_256 internamente)
    // O MuServer valida a senha de formas diferentes por versão
    // Versão mais comum S6: senha em texto claro na MEMB_INFO, comparada em MD5
    $senhaCript = strtoupper(md5($senha)); // MD5 maiúsculo
    
    // Inserir na MEMB_INFO (tabela de contas do MuServer)
    $insertStmt = sqlsrv_prepare($conn, "
        INSERT INTO MEMB_INFO (
            memb_id,
            memb_pw,
            memb_name,
            sno_u_stat,
            memb_stat,
            mail_addr,
            bloc_code,
            appl_days
        ) VALUES (?, ?, ?, 1, 1, ?, 0, GETDATE())
    ", [
        [$login,      SQLSRV_PARAM_IN],
        [$senhaCript, SQLSRV_PARAM_IN],
        [$login,      SQLSRV_PARAM_IN], // nome (usar login como nome)
        [$email,      SQLSRV_PARAM_IN],
    ]);
    
    if (!sqlsrv_execute($insertStmt)) {
        error_log("Erro ao criar conta: " . print_r(sqlsrv_errors(), true));
        return ['sucesso' => false, 'erro' => 'Erro interno ao criar conta'];
    }
    
    return ['sucesso' => true, 'login' => $login];
}

// Processar formulário
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $resultado = registrarConta(
        trim($_POST['login'] ?? ''),
        $_POST['senha'] ?? '',
        trim($_POST['email'] ?? '')
    );
    
    if ($resultado['sucesso']) {
        echo "Conta '{$resultado['login']}' criada com sucesso! Já pode fazer login no jogo.";
    } else {
        echo "Erro: " . htmlspecialchars($resultado['erro']);
    }
}
?>
Atenção: O formato de senha varia por versão do MuServer e distribuição. Algumas usam MD5 maiúsculo (strtoupper(md5($senha))), outras usam HashBytes('SHA2_256', ...) do SQL Server, outras texto claro. Sempre verifique como as senhas estão armazenadas na sua MEMB_INFO antes de implementar.

Ranking de personagens no site

<?php
// ranking.php — ranking de level e resets

require 'config/db-muserver.php';

function getRankingLevel(int $limit = 50): array {
    $conn = getMuDB();
    
    $sql = "
        SELECT TOP $limit
            ROW_NUMBER() OVER (ORDER BY c.Resets DESC, c.cLevel DESC) AS Posicao,
            c.Name,
            c.Class,
            c.cLevel AS Level,
            c.Resets,
            c.ConnectStat AS Online,
            m.mail_addr AS Email
        FROM Character c
        INNER JOIN MEMB_INFO m ON m.memb_id = c.AccountID
        WHERE c.CtlCode = 0   -- excluir GMs do ranking
        ORDER BY c.Resets DESC, c.cLevel DESC
    ";
    
    $stmt = sqlsrv_query($conn, $sql);
    $ranking = [];
    
    while ($row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC)) {
        $row['Classe'] = nomeDaClasse($row['Class']);
        $ranking[] = $row;
    }
    
    return $ranking;
}

function nomeDaClasse(int $classCode): string {
    // Classes do S6 (classe base = múltiplos de 16)
    $classes = [
        0  => 'Dark Wizard',
        1  => 'Soul Master',
        2  => 'Grand Master',
        16 => 'Dark Knight',
        17 => 'Blade Knight',
        18 => 'Blade Master',
        32 => 'Elf',
        33 => 'Muse Elf',
        34 => 'High Elf',
        48 => 'Magic Gladiator',
        49 => 'Duel Master',
        64 => 'Dark Lord',
        65 => 'Lord Emperor',
        80 => 'Summoner',
        81 => 'Bloody Summoner',
        82 => 'Dimension Master',
        96 => 'Rage Fighter',
        97 => 'Fist Master',
    ];
    
    // Código da classe pode ter modificadores de EVO
    $baseClass = (int)($classCode / 16) * 16 + ($classCode % 16);
    return $classes[$classCode] ?? $classes[$baseClass] ?? "Classe $classCode";
}

// Exibir ranking em tabela HTML
$ranking = getRankingLevel();
?>
<table class="ranking">
<tr>
    <th>#</th><th>Personagem</th><th>Classe</th>
    <th>Level</th><th>Resets</th><th>Status</th>
</tr>
<?php foreach ($ranking as $row): ?>
<tr class="<?= $row['Online'] ? 'online' : 'offline' ?>">
    <td><?= $row['Posicao'] ?></td>
    <td><?= htmlspecialchars($row['Name']) ?></td>
    <td><?= htmlspecialchars($row['Classe']) ?></td>
    <td><?= $row['Level'] ?></td>
    <td><?= $row['Resets'] ?></td>
    <td><?= $row['Online'] ? '🟢 Online' : '⚫ Offline' ?></td>
</tr>
<?php endforeach; ?>
</table>

Painel de controle de conta no site

<?php
// painel.php — o jogador gerencia sua conta pelo site

require 'config/db-muserver.php';
session_start();

// Verificar se está logado no site
if (!isset($_SESSION['conta_mu'])) {
    header('Location: /login');
    exit;
}

$conta = $_SESSION['conta_mu'];
$conn = getMuDB();

// Buscar dados da conta e personagens
$stmt = sqlsrv_query($conn, "
    SELECT m.memb_id, m.mail_addr, m.bloc_code,
           v.vip_type, v.start_date, v.end_date
    FROM MEMB_INFO m
    LEFT JOIN MEMB_VIP v ON v.memb_id = m.memb_id
    WHERE m.memb_id = ?
", [[$conta, SQLSRV_PARAM_IN]]);

$dadosConta = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);

// Buscar personagens da conta
$stmtChars = sqlsrv_query($conn, "
    SELECT Name, Class, cLevel, Resets, ConnectStat
    FROM Character
    WHERE AccountID = ?
    ORDER BY cLevel DESC
", [[$conta, SQLSRV_PARAM_IN]]);

$personagens = [];
while ($row = sqlsrv_fetch_array($stmtChars, SQLSRV_FETCH_ASSOC)) {
    $personagens[] = $row;
}

// Alterar senha
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['nova_senha'])) {
    $novaSenha = strtoupper(md5($_POST['nova_senha']));
    
    sqlsrv_query($conn,
        "UPDATE MEMB_INFO SET memb_pw = ? WHERE memb_id = ?",
        [[$novaSenha, SQLSRV_PARAM_IN], [$conta, SQLSRV_PARAM_IN]]
    );
    
    $mensagem = "Senha alterada com sucesso!";
}
?>

<h1>Minha Conta: <?= htmlspecialchars($conta) ?></h1>
<p>Email: <?= htmlspecialchars($dadosConta['mail_addr']) ?></p>
<?php if ($dadosConta['vip_type']): ?>
<p>VIP Ativo: Tipo <?= $dadosConta['vip_type'] ?> até <?= $dadosConta['end_date'] ?></p>
<?php endif; ?>

<h2>Personagens</h2>
<ul>
<?php foreach ($personagens as $char): ?>
    <li><?= htmlspecialchars($char['Name']) ?> — Level <?= $char['cLevel'] ?> — Resets: <?= $char['Resets'] ?></li>
<?php endforeach; ?>
</ul>

Adicionar VIP via site (integração com pagamento)

<?php
// webhook-pagamento.php — chamado após confirmação de pagamento

require 'config/db-muserver.php';

function ativarVIP(string $conta, int $tipovip, int $dias): bool {
    $conn = getMuDB();
    
    // MERGE para criar ou estender VIP
    $sql = "
        MERGE MEMB_VIP AS target
        USING (SELECT ? AS memb_id) AS source ON target.memb_id = source.memb_id
        WHEN MATCHED THEN
            UPDATE SET
                vip_type  = ?,
                end_date  = CASE 
                    WHEN end_date > GETDATE() 
                    THEN DATEADD(DAY, ?, end_date)   -- estender se ainda ativo
                    ELSE DATEADD(DAY, ?, GETDATE())  -- novo prazo se expirado
                END
        WHEN NOT MATCHED THEN
            INSERT (memb_id, vip_type, start_date, end_date)
            VALUES (?, ?, GETDATE(), DATEADD(DAY, ?, GETDATE()));
    ";
    
    $stmt = sqlsrv_query($conn, $sql, [
        [$conta,   SQLSRV_PARAM_IN],
        [$tipovip, SQLSRV_PARAM_IN],
        [$dias,    SQLSRV_PARAM_IN],
        [$dias,    SQLSRV_PARAM_IN],
        [$conta,   SQLSRV_PARAM_IN],
        [$tipovip, SQLSRV_PARAM_IN],
        [$dias,    SQLSRV_PARAM_IN],
    ]);
    
    return $stmt !== false;
}

// Exemplo: ativar VIP tipo 1 por 30 dias
ativarVIP('minhaConta', 1, 30);

Checklist de integração site-jogo

DRIVER PHP
[ ] sqlsrv instalado e funcionando (php -m | grep sqlsrv)
[ ] Driver ODBC Microsoft instalado (Linux)
[ ] Conexão testada com script simples

BANCO
[ ] Usuário SQL dedicado para o site criado
[ ] Permissões: SELECT/INSERT/UPDATE em MEMB_INFO, Character, MEMB_VIP
[ ] Porta 1433 acessível do servidor do site

FUNCIONALIDADES
[ ] Registro de conta funcionando
[ ] Login no site funcionando
[ ] Ranking exibindo dados reais do banco
[ ] Painel de conta exibindo personagens
[ ] Troca de senha funcionando

SEGURANÇA
[ ] Prepared statements em todas as queries (sem SQL injection)
[ ] Senha criptografada antes de salvar
[ ] Rate limiting no endpoint de registro
[ ] Proteção CSRF nos formulários

Perguntas frequentes

O site do servidor pode criar contas no jogo?

Sim — o site PHP se conecta diretamente ao banco SQL Server do MuServer e insere na tabela MEMB_INFO. É a forma mais comum de cadastro em servidores privados.

Como o site se conecta ao SQL Server?

Via PHP usando o driver sqlsrv (para Linux/Windows) ou PDO com driver ODBC. O driver sqlsrv é o mais indicado para SQL Server — instala-se separadamente no PHP.

Posso ter ranking em tempo real no site?

Sim — o site lê as tabelas Character e Account do SQL Server. Ranking de level, resets e tempo online são todos possíveis com queries SQL simples.

O site precisa estar no mesmo servidor que o MuServer?

Não — pode ser em servidores separados. O site só precisa de acesso ao SQL Server (porta 1433). Por segurança, configure o SQL Server para aceitar conexões apenas do IP do site.

EQ

Equipe editorial do ViciadosMU — portal de MU Online no ar desde 2003.

Continue lendo

Artigos relacionados