MySQLOO : connecter ton serveur Garry's Mod à MySQL

MySQLOO : connecter ton serveur Garry's Mod à MySQL

Installer mysqloo (module Lua MySQL pour GMod), connecter ton serveur Wisp VeryCloud à une BDD MySQL/MariaDB, et écrire les premières queries pour ton gamemode (DarkRP, TTT, custom).

Introduction

mysqloo est le module de référence pour interagir avec MySQL depuis du Lua GMod. Async, performant, supporté par DarkRP, ULib, beaucoup d'addons. Si tu fais autre chose qu'un serveur sandbox, tu vas en avoir besoin.

Prérequis

  • Un serveur GMod chez VeryCloud
  • Une BDD MySQL/MariaDB accessible (via Plesk VeryCloud, autre VPS, ou service managé)
  • Accès Files dans Wisp

Étape 1 : Choisir la version de mysqloo

mysqloo a plusieurs builds selon la plateforme. Le projet officiel est sur GitHub.

Sur un serveur Wisp VeryCloud (Linux x64), tu veux le fichier gmsv_mysqloo_linux64.dll (oui, l'extension reste .dll même sous Linux, c'est la convention GMod).

Étape 2 : Uploader le binaire

Dans Wisp → Files :

  1. Va dans /garrysmod/lua/bin/
  2. Si le dossier n'existe pas, crée-le
  3. Upload gmsv_mysqloo_linux64.dll

Restart le serveur.

Étape 3 : Vérifier le chargement

Au boot, en console :

require("mysqloo")

Si aucune erreur n'apparaît, c'est chargé. Sinon, vérifie l'architecture (32 vs 64 bits) et le bon nom de fichier.

💡 Si tu tournes en 32 bits (rare en 2026), c'est gmsv_mysqloo_linux.dll (sans le 64).

Étape 4 : Préparer la BDD côté MySQL

Crée la BDD et l'utilisateur dédié (depuis phpMyAdmin / Plesk / CLI) :

CREATE DATABASE gmod_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

CREATE USER 'gmod_user'@'IP_DU_SERVEUR_GMOD' IDENTIFIED BY 'mdp_solide_16_chars_min';

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, INDEX, ALTER, DROP
  ON gmod_db.*
  TO 'gmod_user'@'IP_DU_SERVEUR_GMOD';

FLUSH PRIVILEGES;

⚠️ Ne mets JAMAIS % pour l'host. Précise l'IP du serveur GMod (récupérable dans Wisp → Network). Si tu héberges la BDD chez VeryCloud aussi, c'est ton IP de service.

Étape 5 : Premier script Lua avec mysqloo

Crée /garrysmod/lua/autorun/server/db_init.lua :

require("mysqloo")

local DB_HOST = "ton.mysql.host"
local DB_USER = "gmod_user"
local DB_PASS = "mdp_solide_16_chars_min"
local DB_NAME = "gmod_db"
local DB_PORT = 3306

DB = mysqloo.connect(DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT)

function DB:onConnected()
    print("[DB] Connexion MySQL OK")
end

function DB:onConnectionFailed(err)
    print("[DB] Connexion echec : " .. err)
end

DB:connect()

Restart le serveur. Tu dois voir [DB] Connexion MySQL OK en console.

Étape 6 : Première query

local q = DB:query("CREATE TABLE IF NOT EXISTS players (\
    steamid VARCHAR(20) PRIMARY KEY,\
    name VARCHAR(64),\
    money INT DEFAULT 500,\
    last_login DATETIME\
)")

function q:onSuccess()
    print("[DB] Table players cree")
end

function q:onError(err)
    print("[DB] Erreur creation table : " .. err)
end

q:start()

Toutes les queries mysqloo sont async : tu déclares les callbacks onSuccess et onError, puis :start().

Étape 7 : Pattern pour les opérations courantes

SELECT :

local function GetPlayerMoney(ply, cb)
    local q = DB:query(string.format(
        "SELECT money FROM players WHERE steamid = %s",
        DB:escape(ply:SteamID())  -- prevention SQLi
    ))
    function q:onSuccess(data)
        cb(tonumber(data[1] and data[1].money) or 0)
    end
    function q:onError(err)
        print("[DB] GetPlayerMoney error : " .. err)
        cb(0)
    end
    q:start()
end

INSERT / UPDATE avec prepared statement :

local stmt = DB:prepare("UPDATE players SET money = ? WHERE steamid = ?")
stmt:setNumber(1, 1000)
stmt:setString(2, ply:SteamID())
function stmt:onSuccess()
    print("[DB] Update OK")
end
function stmt:onError(err)
    print("[DB] Update error : " .. err)
end
stmt:start()

Toujours préférer les prepared statements : performance + protection SQL injection.

Étape 8 : Reconnexion auto

mysqloo gère mal les déconnexions silencieuses (timeout MySQL après inactivité). Pattern de reconnexion :

function DB:onConnectionFailed(err)
    print("[DB] Connexion perdue, retry dans 5s...")
    timer.Simple(5, function()
        DB:connect()
    end)
end

Ou mieux : ping périodique pour garder la connexion alive :

timer.Create("DB_Ping", 60, 0, function()
    local q = DB:query("SELECT 1")
    function q:onError(err)
        print("[DB] Ping failed, reconnexion...")
        DB:connect()
    end
    q:start()
end)

Étape 9 : Intégration avec DarkRP

DarkRP utilise MySQLite par-dessus mysqloo (ou SQLite). Configure dans /garrysmod/addons/darkrpmodification/lua/darkrp_config/mysql.lua (voir tuto DarkRP).

Les autres addons DarkRP-compatibles utiliseront automatiquement ta connexion DB.

Étape 10 : Sécurité

Quelques règles de base :

  • Compte MySQL dédié (un par application/serveur)
  • IP source restreinte (jamais %)
  • Mot de passe long, jamais commit en clair sur Git
  • TLS pour MySQL si la connexion sort du datacenter (paramètre ssl=true dans le driver)
  • Backup régulier de la BDD (mysqldump cron + offsite)

Dépannage

Module not found: mysqloo

  • Fichier mal placé (doit être dans /garrysmod/lua/bin/)
  • Mauvaise archi (linux64 vs win64 vs linux32)

Access denied for user

  • Mot de passe incorrect
  • IP source pas dans les GRANT
  • Vérifier avec : SELECT user, host FROM mysql.user;

Can't connect to MySQL server

  • Port 3306 firewallé côté BDD
  • IP du serveur GMod a changé (re-grant)

Queries lentes / serveur freeze

  • Tu n'utilises pas mysqloo en async (vérifie :start() et les callbacks)
  • BDD trop loin géographiquement (latence)

Commandes utiles

-- Tester la connexion en live
lua_run print(DB:status() == mysqloo.DATABASE_CONNECTED)

-- Lister les tables
lua_run local q = DB:query("SHOW TABLES") q.onSuccess = function(self, data) PrintTable(data) end q:start()

-- Echapper une string utilisateur
DB:escape(text)

Conclusion

mysqloo = pierre angulaire de tout serveur GMod sérieux : économie persistante, stats joueurs, bans, logs. Setup en 30 min avec une BDD préparée à côté. Toujours en async, toujours avec prepared statements pour les inputs utilisateur. Une fois en place, tous tes addons (DarkRP, ULib MySQL, custom) en bénéficient.

Pour aller plus loin : pool de connexions multiples pour la perf, MySQLite (abstraction SQLite/MySQL), monitoring de la latence DB côté gamemode.

Ressources

Rejoignez notre serveur communautaire Discord

Pour toute question, suggestion ou simplement pour discuter avec la communauté, rejoignez-nous sur Discord !

900+Membres