Saltar a contenido

Consultas SQL

La API SQL te permite consultar la base de datos del juego directamente desde scripts Lua usando conexiones ODBC.

Obtener una Conexión

local db = GetConnection("GameDB")
db:Connect("MuOnline_GameDB", "sa", "your_password")

Tip

Las conexiones se almacenan en caché por nombre. Llamar a GetConnection("GameDB") una segunda vez retorna la misma instancia — no es necesario reconectar.

Leer Datos del Jugador

local function GetPlayerResets(playerName)
    local db = GetConnection("GameDB")
    db:ExecQuery("SELECT Reset, MasterReset FROM Character WHERE Name = '" .. playerName .. "'")

    if db:Fetch() then
        local resets = db:GetAsInteger("Reset")
        local masterResets = db:GetAsInteger("MasterReset")
        db:Close()
        return resets, masterResets
    end

    db:Close()
    return 0, 0
end

-- Usage in a command handler
BridgeFunctionAttach("OnCommandManager", function(aIndex, code, arg)
    if code == 200 then
        local player = GetUser(aIndex)
        if player == nil then return 0 end

        local resets, mr = GetPlayerResets(player.Name)
        GCNoticeSend(aIndex, 1, "Resets: " .. resets .. " | Master Resets: " .. mr)
        return 1
    end
    return 0
end)

Ranking de Jugadores en Línea

local function ShowTopPlayers(aIndex)
    local db = GetConnection("GameDB")
    db:ExecQuery("SELECT TOP 5 Name, Reset, MasterReset FROM Character ORDER BY MasterReset DESC, Reset DESC")

    GCNoticeSend(aIndex, 1, "--- Top 5 Players ---")
    local rank = 1

    while db:Fetch() do
        local name = db:GetAsString("Name")
        local resets = db:GetAsInteger("Reset")
        local mr = db:GetAsInteger("MasterReset")

        GCNoticeSend(aIndex, 1, "#" .. rank .. " " .. name .. " - MR:" .. mr .. " R:" .. resets)
        rank = rank + 1
    end

    db:Close()
end

Escribir Datos

local function SaveCustomData(playerName, eventScore)
    local db = GetConnection("GameDB")

    local query = string.format(
        "IF EXISTS (SELECT 1 FROM CustomEventScores WHERE Name = '%s') "..
        "UPDATE CustomEventScores SET Score = %d WHERE Name = '%s' "..
        "ELSE INSERT INTO CustomEventScores (Name, Score) VALUES ('%s', %d)",
        playerName, eventScore, playerName, playerName, eventScore
    )

    db:ExecQuery(query)
    db:Close()
end

Inyección SQL

Los ejemplos anteriores usan concatenación de strings por simplicidad. En producción, usa BindParameterAsString para entrada proporcionada por el usuario para prevenir inyección SQL.

Usando Consultas Parametrizadas

local function SafeGetPlayer(playerName)
    local db = GetConnection("GameDB")

    db:BindParameterAsString(1, playerName)
    db:ExecQuery("SELECT Reset FROM Character WHERE Name = ?")

    local resets = 0
    if db:Fetch() then
        resets = db:GetAsInteger("Reset")
    end

    db:Close()
    return resets
end

Referencia de Métodos de QueryManager

Método Descripción
Connect(dsn, user, pass) Abrir conexión ODBC
ExecQuery(sql) Ejecutar consulta SQL
Fetch() Obtener siguiente fila de resultados (true/false)
Close() Cerrar consulta actual
GetAsInteger(col) Leer columna entera
GetAsFloat(col) Leer columna flotante
GetAsInteger64(col) Leer entero de 64 bits
GetAsString(col) Leer columna de texto
GetAsBinary(col) Leer datos binarios
BindParameterAsString(n, val) Vincular parámetro de texto
BindParameterAsBinary(n, val) Vincular parámetro binario