Veritabanı
createDatabaseTables açılışta sql/main.sql dosyanı kurar; WriteQueue veritabanı yazmalarını birbiri ardına çalıştırır.
import { createDatabaseTables, WriteQueue } from "@aicore-fivem/lib/server";
import { mysql } from "@aicore-fivem/mysql";Sorguların kendisi @aicore-fivem/mysql üzerinden gider (mysql.query, single, scalar, insert, update, prepare, transaction): bkz. Veritabanı. Bu sayfa onun etrafındaki iki lib yardımcısını anlatır.
Lua karşılıkları yok: Lua resource’ları ai-mysql’in oxmysql API’sini (MySQL.query.await, ...) kullanır ve tablolarını kendileri kurar.
createDatabaseTables
Resource’unun SQL dosyasından eksik tabloları oluşturur ve eksik sütunları ekler. Açılışta, tablolara ihtiyaç duyan ilk sorgudan önce bir kez çağır. Önce veritabanı bağlantısını bekler.
Taraf: Server · Bekler: evet (Promise)
createDatabaseTables(resource: string, file: string): Promise<void>Parametreler
Prop
Type
Neyi uygular
- Yalnızca
CREATE TABLE IF NOT EXISTSifadeleri; başka herhangi bir ifade bir uyarıyla atlanır. İfadeler satır sonundaki;ile biter;--ve/* */yorumları yok sayılır. - Var olmayan bir tablo tam ifadeyle (sütunlar ve anahtarlar) oluşturulur.
- Var olan bir tabloya eksik her sütun
ALTER TABLE ... ADD COLUMNile eklenir. - Hiçbir zaman bir sütunu silmez, yeniden adlandırmaz ya da değiştirmez ve zaten var olan bir tabloya asla anahtar veya index eklemez: index’lerini ilk sürümden önce planla.
Dönüş değeri
Promise<void>: her ifade uygulandığında çözülür. Dosya yoksa (<resource>/<file> not found) ya da bir sorgu başarısız olursa reddedilir.
Örnek
CREATE TABLE IF NOT EXISTS `ai_myshop_purchases` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`char_id` INT UNSIGNED NOT NULL,
`item` VARCHAR(64) NOT NULL,
`price` INT UNSIGNED NOT NULL,
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `char_id` (`char_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;import { createDatabaseTables } from "@aicore-fivem/lib/server";
import { createLogger } from "@aicore-fivem/lib/shared";
import { mysql } from "@aicore-fivem/mysql";
const resource = GetCurrentResourceName();
const log = createLogger(resource);
/** Okumalar ve yazmalar bunu bekler. */
export const tablesReady: Promise<void> = createDatabaseTables(resource, "sql/main.sql").catch((error: unknown) =>
log.error("database setup failed", error),
);
export async function addPurchase(charId: number, item: string, price: number) {
await tablesReady;
await mysql.insert("INSERT INTO ai_myshop_purchases (char_id, item, price) VALUES (?, ?, ?)", [charId, item, price]);
}Tablolarının başına resource’un adını koy (ai_<name>_...) ve şablonun sql/main.sql dosyasındaki gibi her tabloyu ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ile bitir.
WriteQueue
Veritabanı yazmalarını, onları eklediğin sırayla birbiri ardına çalıştırır. Kalıp şu: doğru olan server belleğidir, tablo onu sırayla takip eder. Başarısız bir yazma hata handler’ına bildirilir ve ondan sonrakileri durdurmaz.
Taraf: Server · Bekler: hayır (idle() bir Promise döndürür)
new WriteQueue(onError: (label: string, error: unknown) => void)
push(label: string, task: () => Promise<unknown>): void
idle(): Promise<void>Prop
Type
Dönüş değeri push: void. idle(): o ana kadar sıraya alınan her yazma bittiğinde çözülen bir Promise (resource durmadan önce ya da onlara ihtiyaç duyan bir okumadan önce onu bekle).
Örnek
import { WriteQueue, onCharacter, PlayerMap } from "@aicore-fivem/lib/server";
import { createLogger } from "@aicore-fivem/lib/shared";
import { mysql } from "@aicore-fivem/mysql";
const log = createLogger(GetCurrentResourceName());
const writes = new WriteQueue((label, error) => log.error(`database write failed (${label})`, error));
const xp = new PlayerMap<{ charId: number; points: number }>();
export function addXp(source: number, amount: number) {
const entry = xp.get(source);
if (!entry) return;
entry.points += amount; // önce bellek
const { charId, points } = entry;
writes.push(`xp:${charId}`, () => mysql.update("UPDATE ai_myjob_xp SET points = ? WHERE char_id = ?", [points, charId]));
}
onCharacter({
loaded: (source, character) => xp.set(source, { charId: character.id, points: 0 }),
});Admin paneli
AdminPanel ve DataFile: script’inin ayarlarını ai-core’un admin paneline koy, onları oku, düzenlemelere tepki ver ve panel içeriğini data/*.json dosyalarına kaydet.
Lib: shared ve fivem
@aicore-fivem/lib/shared ve /fivem: iki tarafta da çalışan yardımcılar, her girişin ne için olduğu ve tüm konu sayfaları.