Server ile konuşmak
Server’a sor ve cevabını bekle, çevrilmiş reddetmelerle server aksiyonları çalıştır, server event’lerini dinle ve server callback’lerine cevap ver.
Bir client script’i asla kendine güvenmez: server’a sorar ve kararı server verir. Bu yardımcılar o soruları ve cevapları taşır. Server tarafındaki yarılar Client girdisi sayfasındadır (onClientCallback, onClientEvent, triggerClientCallback).
| İstediğin | Kullan |
|---|---|
| Server’ın izin vermesi gereken bir şeyi çalıştırmak (satın almak, kiralamak, açmak) ve reddini göstermek | callAction |
| Server’dan veri istemek | triggerServerCallback |
| Server’ın gönderdiği bir şeyi duymak | onServerEvent |
| Server’ın bu client’a sorduğu bir soruya cevap vermek | onServerCallback |
triggerServerCallback
Server’a sorar ve cevabını bekler. Server onClientCallback(name, ...) ile cevap verir. Server’ın tuttuğu verileri (bir fiyat listesi, bir oyuncunun kendi kayıtları) okumak için kullan. Reddedilebilecek bir aksiyon için callAction kullan: reddi senin için gösterir.
Taraf: Client · Bekler: evet (TypeScript’te Promise, Lua’da thread’i yield eder)
triggerServerCallback(name: string, args?: unknown[], timeoutMs?: number): Promise<unknown>local result, err = aiLib.triggerServerCallback(name, args, timeout) -- bir thread içinde çağırParametreler
Prop
Type
Dönüş değeri
TypeScript: Promise<unknown>. Server handler’ının döndürdüğüyle çözülür (hiçbir şey döndürmediyse null). Değer kontrol edilmez: kullanmadan önce tipini test et. Server handler’ı hata fırlattıysa, server kapısı çağrıyı reddettiyse (hız sınırı, bir koruma, hatalı argümanlar, bir kilit) ya da timeoutMs içinde cevap gelmediyse promise reddedilir.
Lua: iki değer. result cevaptır; err başarıda nil, server reddettiyse ya da başarısız olduysa 'failed', zamanında cevap gelmediyse 'timeout'’tur. Hata durumunda result nil olur.
Örnek
import { createLocale, notify, triggerServerCallback } from "@aicore-fivem/lib/client";
const Locale = createLocale<typeof import("../../locales/en.json")>();
RegisterCommand(
"mycash",
async () => {
const cash = await triggerServerCallback("myscript:cash").catch(() => null);
if (typeof cash !== "number") return notify(Locale("ERROR"), "error");
notify(Locale("YOUR_CASH", cash), "info");
},
false,
);import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
onClientCallback("myscript:cash", (source) => core.GetMoney(source, "cash"));TypeScript’te reddetmeyi her zaman ele al (.catch(() => null) ya da try): reddedilen ya da zaman aşımına uğrayan bir çağrı reject olur. Server varsayılan olarak her callback’i oyuncu başına saniyede 20 çağrıyla sınırlar; bu yüzden onu asla bir döngüde ya da her karede çağırma. İletim biçimi iki dilde de aynıdır: bir Lua client’ı bir TypeScript server’ını çağırabilir ve tersi de geçerlidir.
callAction
Server’da bir aksiyon çalıştırır ve reddi senin için gösterir. Server handler’ı (onClientCallback) bir ActionResult ile cevap verir: çalıştıysa { ok: true, ...data }, reddettiyse fail("LANG_KEY"). Bir reddetmede, zaman aşımında ya da kapı reddinde callAction, hata anahtarını senin resource’unun dil dosyasında arar ve bir hata bildirimi olarak gösterir. Bir şeyi değiştiren her buton için kullan: satın al, sat, kirala, tamir et.
Taraf: Client · Bekler: evet (TypeScript’te Promise, Lua’da thread’i yield eder)
callAction(name: string, args: unknown[] | undefined, options: CallActionOptions): Promise<({ ok: true } & Record<string, unknown>) | null>local reply = aiLib.callAction(name, args, options) -- table ya da nil, bir thread içinde çağırParametreler
Prop
Type
CallActionOptions
Prop
Type
Dönüş değeri
Promise<({ ok: true } & Record<string, unknown>) | null>: aksiyon çalıştıysa ok cevabının tamamı (server’ın eklediği ek alanlarla birlikte); reddedildiyse, başarısız olduysa ya da zaman aşımına uğradıysa null (silent değilse bildirim zaten gösterilmiştir). Ek alanlar kontrol edilmez: okuduğun her birinin tipini test et. Lua cevap tablosunu ya da nil döndürür.
Örnek
import { callAction, createLocale, notify } from "@aicore-fivem/lib/client";
const Locale = createLocale<typeof import("../../locales/en.json")>();
export async function buy(itemId: string): Promise<void> {
const reply = await callAction("myshop:buy", [itemId], { fallback: "BUY_FAILED" });
if (!reply) return; // ret zaten ekranda
const paid = typeof reply.paid === "number" ? reply.paid : 0;
notify(Locale("BOUGHT", paid), "success");
}import { inventory, onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail, oneArg, readText } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
const PRICES: Record<string, number> = { water: 5, bread: 8 };
onClientCallback(
"myshop:buy",
{ args: oneArg((v) => readText(v, 32)) },
(source, item) => {
const price = PRICES[item];
if (price === undefined) return fail("UNKNOWN_ITEM");
if (!inventory.canCarryItem(source, item, 1)) return fail("NO_ROOM");
if (!core.RemoveMoney(source, "cash", price, "shop")) return fail("NO_MONEY");
inventory.addItem(source, item, 1);
return { ok: true, paid: price };
},
);Hata anahtarı callAction’ı çağıran resource’un dil dosyasında aranır; bu yüzden server’ın cevap verebileceği her anahtarı (NO_MONEY, NO_ROOM, UNKNOWN_ITEM) ve fallback anahtarını o resource’un locales/en.json dosyasına koy. Orada olmayan bir anahtar, anahtarın kendisi olarak gösterilir.
isActionOk
Bir cevabın ok bir ActionResult olup olmadığını söyler (ok tam olarak true). triggerServerCallback’i kendin çağırıp cevabı elle okuduğunda kullan.
Taraf: Client ve server (/shared’dan, /client tarafından yeniden export edilir) · Bekler: hayır
isActionOk(reply: unknown): reply is { ok: true } & Record<string, unknown>Lua karşılığı yok: type(reply) == 'table' and reply.ok == true test et.
Parametreler
Prop
Type
Dönüş değeri
boolean: reply ok’u true olan bir nesneyse (dizi değil) true. TypeScript’te ayrıca reply’ı { ok: true } & Record<string, unknown> tipine daraltır.
Örnek
import { isActionOk, replyError, triggerServerCallback } from "@aicore-fivem/lib/client";
export async function buyWater(): Promise<void> {
const reply = await triggerServerCallback("myshop:buy", ["water"]).catch(() => null);
if (isActionOk(reply)) console.log("bought");
else console.log("refused with", replyError(reply, "BUY_FAILED"));
}replyError
Reddedilmiş bir cevabın lang anahtarı: error alanı ya da cevap yoksa veya hata metni yoksa fallback. Hatayı kendi yönteminle (bir bildirim yerine bir NUI sayfasında) gösterdiğinde isActionOk ile birlikte kullan.
Taraf: Client ve server (/shared’dan, /client tarafından yeniden export edilir) · Bekler: hayır
replyError(reply: unknown, fallback: string): string | nullLua karşılığı yok.
Parametreler
Prop
Type
Dönüş değeri
string | null: cevap ok ise null; boş olmayan bir string ise cevabın error’u; aksi halde fallback.
Örnek
import { replyError, triggerServerCallback } from "@aicore-fivem/lib/client";
export async function buyFromPage(item: string): Promise<void> {
const reply = await triggerServerCallback("myshop:buy", [item]).catch(() => null);
const error = replyError(reply, "BUY_FAILED");
if (error) SendNUIMessage({ action: "error", data: error });
}onServerEvent
Server’ın emitNet ile (Lua’da TriggerClientEvent) gönderdiği bir net event’i dinler. Server’dan gelmeyen çağrılar (başka bir resource’un yerel emit’i) atılır; böylece bir hile menüsü onları taklit edemez. Her ai-* client’ı server’ı bu şekilde dinler, asla çıplak bir onNet ile değil. TypeScript’te argüman alan bir handler bir args ayrıştırıcısı belirtmelidir: ham değerleri kontrol eder ve null çağrıyı atar.
Taraf: Client · Bekler: hayır
onServerEvent(name: string, handler: () => unknown): void
onServerEvent<A extends readonly unknown[]>(name: string, options: { args: (raw: unknown[]) => A | null }, handler: (...args: A) => unknown): voidaiLib.onServerEvent(name, handler) -- handler(...) ham argümanları alırParametreler
Prop
Type
Dönüş değeri
void.
Örnek
import { onServerEvent, Points } from "@aicore-fivem/lib/client";
let renting = false;
const points = new Points();
// Argüman yok: kısa biçim.
onServerEvent("myscript:reset", () => points.clear());
// Tek bir boolean argüman: onu ayrıştır, null hatalı bir çağrıyı atar.
onServerEvent(
"myscript:state",
{ args: ([active]) => (typeof active === "boolean" ? [active] : null) },
(active) => {
renting = active;
points.refresh();
},
);Server event’i emitNet("myscript:state", source, true) (TypeScript) ya da TriggerClientEvent('myscript:state', source, true) (Lua) ile gönderir. Lua handler’ları ham argümanları alır: tiplerini kendin kontrol et.
fromServer
Şu an işlenen net event’in server’dan gelip gelmediği. onServerEvent bunu zaten kullanır; ona yalnızca değiştiremediğin çıplak bir onNet handler’ında ihtiyacın olur.
Taraf: Client · Bekler: hayır
fromServer(): booleanLua karşılığı yok: bir Lua net event handler’ında yerel emit’ler için source boştur.
Dönüş değeri
boolean: güncel event server’ın sayısal source’unu taşıyorsa true; herhangi bir resource’un yerel emit’i için false.
Örnek
import { fromServer } from "@aicore-fivem/lib/client";
onNet("legacy:event", (value: unknown) => {
if (!fromServer()) return; // server değil, yerel bir emit
console.log("server said", value);
});Onu handler’ın ilk await’inden önce oku: bir await’ten sonra güncel event gitmiştir ve cevap yanlıştır.
onServerCallback
Server’ın bu client’a triggerClientCallback(name, source, ...) ile sorduğu bir soruya cevap verir. Handler’ının döndürdüğü değer (ya da promise’inin çözüldüğü değer) geri gönderilir. Fırlatılan bir hata başarısızlık cevabı verir ve server’ın promise’i reddedilir.
Taraf: Client · Bekler: hayır (handler async olabilir)
onServerCallback(name: string, handler: (...args: unknown[]) => unknown): voidaiLib.onServerCallback(name, handler) -- handler’ın dönüş değeri cevaptırParametreler
Prop
Type
Dönüş değeri
void.
Örnek
import { onServerCallback, player } from "@aicore-fivem/lib/client";
// Server bu oyuncunun bir noktaya ne kadar uzakta durduğunu sorar.
onServerCallback("myscript:distance", (x, y, z) => {
if (typeof x !== "number" || typeof y !== "number" || typeof z !== "number") return null;
return player.distanceTo({ x, y, z });
});Lua’da false döndüren bir handler nil cevabını verir (server null alır): server’ın false’u "cevap yok"tan ayırması gerekiyorsa true / nil, bir sayı ya da bir tablo döndür. Cevap oyuncunun bilgisayarından gelir; bu yüzden bir hileci onu değiştirebilir. Client cevaplarını yalnızca client’ın bildiği şeyler için (ekranda ne olduğu, yerel bir entity) kullan ve asla para ya da eşya için kanıt olarak kullanma.
Lib: client
@aicore-fivem/lib/client ve aiLib’in client tarafı: ne oldukları, TypeScript ve Lua’da nasıl yüklendikleri ve tüm konu sayfaları.
Yerel oyuncu
Önbellekteki ped, araç, koltuk ve silah, player nesnesi (konum, ışınlanma, animasyonlar), ekran kararmaları, diğer oyuncuların ped’leri ve en yakın oyuncu.