Base de données
@aicore-fivem/mysql, tables typées et ai-mysql pour les scripts tiers.
AI Core a son propre moteur de base de données, @aicore-fivem/mysql. Chaque ressource ai-* qui utilise la base de données fait tourner un petit pool dans son propre processus (pas de passage par un export à chaque requête) ; ai-mysql remplace oxmysql, mysql-async et ghmattimysql pour que les scripts tiers gardent leur API.
Tables
Une ressource garde ses tables dans sql/main.sql et les installe au démarrage :
createDatabaseTables(ResourceName, "sql/main.sql");Elle crée les tables manquantes et ajoute les colonnes manquantes ; elle ne supprime ni ne modifie jamais celles qui existent. Chaque table est préfixée par la ressource (ai_<name>_...), a une clé primaire et utilise utf8mb4_unicode_ci.
Requêtes
Le build génère des types de lignes (resource/server/tables.ts) à partir du SQL. Les requêtes simples les utilisent :
export const db = tables<Tables, TableInserts>();
const rows = await db.select("ai_garages_vehicles", ["id", "plate"], { owner }, { limit: 50 });Les jointures, plages, upserts et instructions en masse restent en SQL brut avec des placeholders :
await mysql.query("UPDATE ai_x SET count = count - ? WHERE id = ? AND count >= ?", [n, id, n]);Règles
- Des placeholders pour chaque valeur ; les identifiants uniquement à partir d’une liste fixe.
- L’argent est un entier, les dates sont en
DATETIMEUTC, les indicateurs sont enTINYINT(1). - Les données des joueurs sont lues une fois au chargement et gardées en mémoire ; les valeurs fréquentes sont écrites par un flush périodique, les valeurs critiques (argent, objets) en une seule instruction conditionnelle ou transaction.
- Les écritures en masse font une instruction par lot, jamais une par ligne.
- Chaque ressource qui utilise la base de données a besoin de
add_convar_permission <resource> read mysql_connection_stringdansenv.cfg.