AI Core
API başvurusuLib: server

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.

TypeScript
import { AdminPanel, DataFile } from "@aicore-fivem/lib/server";

Her ai-* script’i, sunucu sahibinin ayarladığı ayarları bir config dosyasında değil, ai-core’un admin panelinde tutar. Veriyi ve formu resource/server/schema.ts içinde tanımlarsın (PanelSchema: dosyalar, sekmeler, kartlar, widget’lar; bkz. Script oluşturmak), ondan tek bir AdminPanel oluşturursun ve değerleri onun üzerinden okursun. Sahibin tarafı (paneli açmak, düzenlemek, yetkiler) Admin paneli sayfasındadır.

Lua karşılığı yok: admin paneli yalnızca TypeScript’tir.

AdminPanel

Resource’unun panel içeriği. Her data/<file>.json dosyasını açılışta bir kez yükler, bellekte tutar, her panel düzenlemesini şemaya göre kontrol eder, dosyayı kaydeder (atomik, art arda gelen düzenlemeler tek seferde yazılır) ve senin kodunu, açık panelleri ve sync: "all" dosyaları için her client’ı haberdar eder. Ayrıca bir editörün elle yapılan düzenlemeyi kontrol edebilmesi için data/schemas/<file>.schema.json dosyasını yazar.

Taraf: Server · Bekler: hayır

Signature
new AdminPanel(schema: PanelSchema)

Prop

Type

Tam olarak bir tane oluştur, modül seviyesinde, genellikle resource/server/content.ts içinde: export const panel = new AdminPanel(schema);. Ayar dosyaları yüklenirken eksik bölümlerini defaults’tan alır. ai-core paneli oluşturulduktan bir tick sonra listeler.

AdminPanel.get

Bir dosyanın güncel içeriği.

Signature
get<T = Record<string, unknown>>(file: string): T

Dönüş değeri: ayar nesnesi (bir settings dosyası) ya da { key: record } (bir records dosyası); bilinmeyen bir dosya için {}. Salt okunur: dönen nesneyi asla değiştirme, commit kullan.

const settings = panel.get<{ prices: { repair: number } }>("settings");

AdminPanel.view

Senin okuyucunla ayrıştırılan ve her değişiklikte güncel tutulan bir ayar dosyası (onChange handler’ları çalışmadan önce ayrıştırılır).

Signature
view<T>(file: string, read: (raw: unknown) => T): { readonly value: T }

Dönüş değeri: value’su her zaman en son ayrıştırılmış içerik olan bir nesne. .value’yu her seferinde oku; bir kez kopyalayıp saklama.

import { int, record } from "@aicore-fivem/lib/shared";

const settings = panel.view("settings", (raw) => ({
  repairPrice: int(record(record(raw).prices).repair, 250),
}));
// daha sonra: settings.value.repairPrice

AdminPanel.records

Kayıt kayıt ayrıştırılan bir records dosyası. Bir değişiklik yalnızca değişen kaydı yeniden okur.

Signature
records<T>(file: string, readOne: (key: string, raw: Record<string, unknown>) => T | null): ReadonlyMap<string, T>

Dönüş değeri: kayıt anahtarından ayrıştırılmış değerine canlı bir map. readOne null döndürürse kayıt dışarıda kalır.

const shops = panel.records("shops", (key, raw) =>
  typeof raw.label === "string" ? { key, label: raw.label } : null,
);
for (const shop of shops.values()) console.log(shop.label);

AdminPanel.onChange

Bir dosya, bir panel düzenlemesiyle ya da senin kendi commit’inle değiştikten sonra handler’ını çalıştırır.

Signature
onChange(file: string, handler: (key: string | undefined, value: unknown) => void): void

Prop

Type

panel.onChange("shops", (key, value) => {
  if (value === null) console.log(`shop ${key} deleted`);
});

AdminPanel.rule

Bir düzenleme saklanmadan önce çalışan, alanlar arası bir kontrol. Şema tek tek değerleri kontrol eder; bir kural değerlerin birbirine nasıl uyduğunu kontrol eder.

Signature
rule(file: string, rule: (key: string | undefined, next: Record<string, unknown>) => string | null): void

Dönüş değeri (kuralından): kabul etmek için null ya da reddetmek için bir lang anahtarı (admin’e gösterilir). Dosya başına bir kural; ikinci bir çağrı onun yerine geçer.

panel.rule("settings", (_key, next) => {
  const prices = next.prices as { min: number; max: number };
  return prices.min > prices.max ? "ERR_MIN_ABOVE_MAX" : null;
});

AdminPanel.onAction

Bir admin bir action widget’ına (bir buton: gönder, sıfırla, at) bastığında çalışır. Buton için hiçbir şey saklanmaz.

Signature
onAction(id: string, handler: (admin: number, record: Record<string, unknown>, key: string | undefined) => string | null): void

Prop

Type

import { notify } from "@aicore-fivem/lib/server";

panel.onAction("testAlert", (admin) => {
  notify(admin, "Test alert sent", "success");
  return null;
});

AdminPanel.commit

Script’inin kendisinin yaptığı bir değişikliği (panelin gösterdiği oyun durumu) doğrulama olmadan saklar. Bir memory dosyası onu yalnızca bellekte tutar.

Signature
commit(file: string, key: string | undefined, value: unknown): void

Prop

Type

panel.commit("vaults", "bank_1", { ...panel.get<Record<string, object>>("vaults").bank_1, robbedAt: Date.now() });

AdminPanel.commitAfter

Güncel değişiklik panele ulaştıktan sonra commit. Bir admin gönderdikten sonra kendini sıfırlayan bir form için kullan.

Signature
commitAfter(file: string, key: string | undefined, value: unknown): void
panel.onAction("sendBroadcast", (admin, form) => {
  if (typeof form.message !== "string" || form.message === "") return "ERR_EMPTY_MESSAGE";
  for (const player of getPlayers()) notify(Number(player), form.message, "info", 10_000);
  panel.commitAfter("broadcast", undefined, { message: "" }); // formu boşalt
  return null;
});

Aynı dosya için commit ya da commitAfter’ı asla o dosyanın kendi onChange handler’ı içinden çağırma: commit onChange’i yeniden tetikler, sonsuza kadar.

AdminPanel.editor

Signature
editor: number

Düzenlemesi ya da aksiyonu uygulanan admin’in server id’si; rule, onChange ve onAction handler’ları içinde okunabilir; senin kendi commit’in için 0. Yalnızca lib tarafından ayarlanır.

panel.onChange("settings", () => {
  if (panel.editor) console.log(`settings changed by ${panel.editor}`);
});

ai-core’un kullandıkları

snapshot(), dataSnapshot(), summary() ve apply(admin, patch), ai-core’un panelin kaydettiği export’lar (AdminPanelSnapshot, AdminPanelData, AdminPanelSummary, AdminPanelApply) üzerinden çağırdıklarıdır. Script’in onları çağırmaz.

Örnek

resource/server/content.ts
import { AdminPanel, aiLog } from "@aicore-fivem/lib/server";
import { int, record } from "@aicore-fivem/lib/shared";
import { schema } from "./schema";

export const panel = new AdminPanel(schema);

export const settings = panel.view("settings", (raw) => ({
  repairPrice: int(record(record(raw).prices).repair, 250),
}));

panel.onChange("settings", () => {
  aiLog("admin", `repair price is now ${settings.value.repairPrice}`, { source: panel.editor || undefined });
});

data/*.json dosyasını asla kendin okuma ve ona asla yazma: dosyanın sahibi paneldir. Dünyanın client’larda ihtiyaç duyduğu veriler (yerler, blip’ler, oyuncuların gördüğü fiyatlar) client’ta AdminWorld ile okunan bir sync: "all" dosyasıdır; geri kalan her şey server’da kalır.

DataFile

Resource’unun güvenli yazmalı tek bir data/<name>.json dosyası. AdminPanel her dosya için onu kullanır; onu doğrudan yalnızca panel dışındaki içerik için kullan. Tek okuyan ve yazan server’dır: açılışta bir kez okur ve doğruyu bellekte tutar. Bir yazma, sonra gerçek dosyanın yerine geçen geçici bir dosyaya gider (bir çökme asla yarım dosya bırakmaz), önceki dosya .bak olarak saklanır ve bozuk bir dosya açılışta .bak’a geri döner.

Taraf: Server · Bekler: hayır

Lua karşılığı yok.

Signature
new DataFile(resource: string, name: string, log: Logger)

Prop

Type

DataFile.read

Signature
read(): unknown

Dönüş değeri: $schema anahtarı olmadan ayrıştırılmış dosya, dosya bozuksa .bak ya da ikisi de yoksa null. Sonucu kullanmadan önce ayrıştır.

DataFile.write

Signature
write(value: unknown): void

value’yu saklar; son çağrı kazanır. Art arda gelen çağrıların ilkinden 250 ms sonra, önceki yazmalarla sıralı olarak diske yazılır. Başarısız bir yazma loglanır.

DataFile.schemaRef

Signature
schemaRef: string | null

Ayarlandığında (./schemas/<name>.schema.json), dosyanın ilk anahtarı olarak "$schema" şeklinde yazılır; asla verinin parçası değildir.

DataFile.hasSchemaRef

Signature
hasSchemaRef(): boolean

Dönüş değeri: diskteki dosyanın şemasını belirtip belirtmediği.

Örnek

import { DataFile } from "@aicore-fivem/lib/server";
import { createLogger, isRecord } from "@aicore-fivem/lib/shared";

const resource = GetCurrentResourceName();
const file = new DataFile(resource, "routes", createLogger(resource));

const raw = file.read();
const routes: Record<string, unknown> = isRecord(raw) ? raw : {};

function saveRoute(id: string, route: unknown) {
  routes[id] = route;
  file.write(routes);
}

Oyuncu verisi asla bir data dosyasına girmez: veritabanına aittir (Veritabanı). Sırlar (webhook’lar, API anahtarları) git’e girmeyen data/secrets.json dosyasına gider.

Bu sayfada