Alan yayını
AreaStream: dünya nesneleri (yere atılan eşyalar, bitkiler, cesetler, prop’lar) yalnızca yakınındaki oyunculara, bir snapshot ve ardından yalnızca değişiklikler olarak gönderilir.
import { AreaStream } from "@aicore-fivem/lib/server";AreaStream
Dünya öğelerini (yere atılan eşyalar, bitkiler, yerleştirilmiş prop’lar, cesetler) hücrelerden oluşan bir ızgarada tutar ve her oyuncuya yalnızca etrafındaki hücrelerin öğelerini gönderir. Takip etmeye başlayan bir oyuncu kendi alanının bir snapshot’ını alır; ondan sonra yalnızca değişiklikleri alır: bir öğe eklendi, değişti, taşındı ya da kaldırıldı veya hareket ettikçe yeni hücreler menzile girdi. Bir öğenin kimde olduğu hücrelerden hesaplanır; bu yüzden oyuncu ve öğe başına hiçbir şey saklanmaz ve çok sayıda öğe ve oyuncuya ölçeklenir. Takipçiler oyundan çıktıklarında serbest bırakılır.
Her öğe türü için modül seviyesinde oluşturulan bir AreaStream kullan. Client’ta new AreaFollower(event, cellSize) (Lib: client), oyuncunun hücresi değiştiğinde (2 saniyede bir kontrol edilir) followReported için kendi event’i üzerinden (cx, cy) gönderir; client kodun yayının event’ini dinler ve öğeleri tutar.
Taraf: Server · Bekler: hayır
Lua karşılığı yok.
new AreaStream<T extends AreaItem, V = T>(options: AreaStreamOptions<T, V>)AreaItem
Her öğede olması gerekenler:
Prop
Type
AreaStreamOptions
Prop
Type
Öğeler
| Metot | Ne yapar | Dönüş değeri |
|---|---|---|
set(item: T, resend = true): void | Bir öğe ekler ya da günceller. Etrafındaki takipçiler bir put alır; öğe taşındığında onu kaybeden takipçiler bir remove alır. resend false iken yalnızca öğeye henüz sahip olmayan takipçiler put alır (client’ları değişikliklerini kendileri takip eden bir öğe için). | void |
delete(id): void | Bir öğeyi kaldırır; ona sahip olan takipçiler bir remove alır. | void |
load(items: Iterable<T>): void | Her biri için mesaj göndermeden çok sayıda öğeyi kaydeder (açılışta veritabanından yükleme), sonra her takipçiye alanını yeniden snapshot olarak gönderir. | void |
get(id): T | undefined | Tek bir öğe. | öğe ya da undefined |
values(): Generator<T> | Tüm öğeler. | bir generator |
size: number | Kaç öğe olduğu. | number |
cellOf(x, y): { cx, cy } | Bir noktanın bu yayının ızgarasındaki hücresi. | hücre koordinatları |
countAt(x, y): number | Bir noktanın hücresindeki öğeler (hücre başına bir sınır için). | number |
around(x, y, cells = 1): Generator<T> | Bir noktanın hücresindeki ve etrafındaki cells hücredeki öğeler (aralık ve birleştirme kontrolleri). | bir generator |
recipients(id): Set<number> | Client’ında şu an öğe bulunan oyuncular. | server id’lerinden bir set |
knows(source, id): boolean | Oyuncunun client’ında şu an öğenin olup olmadığı. | boolean |
Takipçiler
| Metot | Ne yapar | Dönüş değeri |
|---|---|---|
start(source, at = coordsOf(source)): void | Oyuncu bir noktada (varsayılan: ped’in server konumu) takip etmeye başlar ve bir snapshot alır. | void |
follow(source, cx, cy): void | Oyuncunun güncel hücresi: ilk çağrı snapshot ile takibi başlatır, bir değişiklik yalnızca farkı gönderir. | void |
followReported(source, cx, cy): boolean | Client’ın gönderdiği bir hücre için follow; ped’in server konumuna bir hücre uzaklıkta değilse reddedilir (client’ın hücresi bir geriden gelebilir). | kabul edilirse true |
followAll(): void | Her takipçinin server konumunu okur ve hücre değiştirenlere farkı gönderir. Client hücreleri bildirmiyorsa bir every zamanlayıcısından çağır. | void |
stop(source, tell = false): void | Oyuncu takibi bırakır (çıkış yapma, özel bir dünya). tell client’ını boşaltır. | void |
following(source): boolean | Oyuncunun takip edip etmediği. | boolean |
Örnek
import { AreaStream, onClientEvent, onCharacter, every } from "@aicore-fivem/lib/server";
import { readInt } from "@aicore-fivem/lib/shared";
interface Plant { id: number; x: number; y: number; z: number; growth: number; owner: number }
const plants = new AreaStream<Plant, { id: number; x: number; y: number; z: number; growth: number }>({
event: "my-plants:stream",
view: ({ id, x, y, z, growth }) => ({ id, x, y, z, growth }), // sahip server’da kalır
});
// Açılışta: plants.load(rowsFromDatabase);
onCharacter({
loaded: (source) => plants.start(source),
unloaded: (source) => plants.stop(source),
});
// Client’ın AreaFollower’ı hücresi değişince onu bildirir.
onClientEvent(
"my-plants:cell",
{
args: ([cx, cy]) => {
const x = readInt(cx, -1000, 1000);
const y = readInt(cy, -1000, 1000);
return x !== null && y !== null ? [x, y] : null;
},
},
(source, cx, cy) => {
plants.followReported(source, cx, cy);
},
);
// Büyüme değişiklikleri yalnızca her bitkinin yakınındaki oyunculara ulaşır.
every(60_000, () => {
for (const plant of plants.values()) if (plant.growth < 100) plants.set({ ...plant, growth: plant.growth + 1 });
});Bunun yanında asla kendi hücre index’ini, izleyici set’lerini ya da snapshot kodunu yazma. Oyundan çıkan bir oyuncunun alsoTo öğeleri bırakılır (aynı id’yi alan sonraki oyuncu onları asla almaz), ama öğenin kendisini (cesedin şimdi nerede yattığını) yine senin script’in günceller. Server’daki ve client’ın AreaFollower’ındaki cellSize aynı olmalıdır.
Loglar
aiLog ve aiLogChannels: logları ai-core üzerinden konsola, Discord’a, Fivemanage’a ya da FiveM Stats’e gönder; sunucu sahibi panelde neyi açtıysa oraya.
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.