Cámara y temporización
ScriptCamera, TickLoop, AreaFollower y ServerClock - cámaras con script, tareas por frame que solo se ejecutan cuando hacen falta, informar al servidor del área del jugador y el reloj del servidor en el cliente.
Una cámara con script para exposiciones y escenas, una tarea por frame que activas solo mientras hace falta, la mitad de cliente del streaming por áreas del servidor y el reloj del servidor para cuentas atrás. El trabajo periódico en general es every(ms, fn) (consulta Lib: compartido y fivem); nunca setInterval ni un setTick a secas.
ScriptCamera
new ScriptCamera
Una cámara con script: la vista de exposición de una tienda, un editor, una escena, unos prismáticos. start la crea y la muestra, los demás métodos la mueven y la cambian, stop vuelve suavemente a la cámara del juego y la destruye. Una cámara que sigue en marcha cuando tu recurso se detiene se devuelve al momento, así que el jugador nunca se queda atrapado en ella.
Lado: Cliente · Espera: no
new ScriptCamera(type?: string)Sin equivalente en Lua: los recursos Lua usan CreateCam, RenderScriptCams y DestroyCam.
Parámetros
Prop
Type
CameraView
Hacia dónde mira una cámara, usado por start, move y glideTo:
Prop
Type
Miembros
Prop
Type
Ejemplo
import { ScriptCamera } from "@aicore-fivem/lib/client";
const camera = new ScriptCamera();
const CAR = { x: -44.4, y: -1097.1, z: 26.4 };
export function openShowroom(): void {
camera.start({ x: -40.2, y: -1100.5, z: 27.6 }, { pointAt: CAR, fov: 50 }, 800);
}
export function frontView(): void {
camera.glideTo({ x: -47.5, y: -1093.8, z: 27.2 }, { pointAt: CAR, fov: 45 }, 1200);
}
export function closeShowroom(): void {
camera.stop(800);
}camera.start
Crea la cámara (cuando aún no existe), la coloca en un punto y la convierte en la vista, con una transición suave desde la cámara del juego.
Lado: Cliente · Espera: no
camera.start(at: Vec3, view?: CameraView, easeMs?: number): voidParámetros
Prop
Type
Devuelve
void. Consulta el ejemplo de la clase.
camera.move
Mueve la cámara, al momento o deslizándose hasta allí (el juego interpola). No hace nada mientras está detenida.
Lado: Cliente · Espera: no
camera.move(at: Vec3, view?: CameraView, ms?: number): voidParámetros
Prop
Type
Devuelve
void.
Ejemplo
camera.move({ x: -42.0, y: -1099.0, z: 28.5 }, { pointAt: CAR }, 600);camera.glideTo
Hace una transición a un nuevo plano: una segunda cámara en el nuevo lugar toma el relevo de esta, y la antigua se destruye después de la transición. La vibración y el desenfoque se mantienen. Inicia la cámara cuando está detenida (o cuando ms es 0).
Lado: Cliente · Espera: no
camera.glideTo(at: Vec3, view: CameraView, ms: number): voidParámetros
Prop
Type
Devuelve
void. Consulta el ejemplo de la clase.
camera.attach
Hace que la cámara siga a una entidad con un desplazamiento en el espacio propio de la entidad.
Lado: Cliente · Espera: no
camera.attach(entity: number, offset: Vec3, relative?: boolean): voidParámetros
Prop
Type
Devuelve
void.
Ejemplo
import { cache, ScriptCamera } from "@aicore-fivem/lib/client";
const chase = new ScriptCamera();
if (cache.vehicle !== false) {
chase.start({ x: 0, y: 0, z: 0 });
chase.attach(cache.vehicle, { x: 0, y: -6, z: 2 });
}camera.pointAt
Hace que la cámara siga mirando un punto.
Lado: Cliente · Espera: no
camera.pointAt(target: Vec3): voidParámetros
Prop
Type
Devuelve
void.
camera.setFov
Cambia el campo de visión (zoom).
Lado: Cliente · Espera: no
camera.setFov(fov: number): voidParámetros
Prop
Type
Devuelve
void.
Ejemplo
// Prismáticos: zoom con la rueda del ratón.
let fov = 40;
export function zoom(step: number): void {
fov = Math.min(70, Math.max(5, fov + step));
camera.setFov(fov);
}camera.shake
Añade la vibración de cámara del juego. Una amplitud de 0 la detiene.
Lado: Cliente · Espera: no
camera.shake(type: string, amplitude: number): voidParámetros
Prop
Type
Devuelve
void.
Ejemplo
camera.shake("HAND_SHAKE", 0.3);camera.blur
Profundidad de campo: nítido entre dos distancias, desenfocado fuera. Pasa null para ninguna. Necesita un native por frame, que solo se ejecuta mientras hay un desenfoque fijado.
Lado: Cliente · Espera: no
camera.blur(dof: CameraBlur | null): voidParámetros
Prop
Type
Devuelve
void.
Ejemplo
camera.blur({ near: 2, far: 8, strength: 0.8 });camera.stop
Devuelve la vista a la cámara del juego (con una transición de easeMs) y destruye la cámara. La vibración y el desenfoque también terminan. No hace nada mientras está detenida.
Lado: Cliente · Espera: no
camera.stop(easeMs?: number): voidParámetros
Prop
Type
Devuelve
void. Consulta el ejemplo de la clase.
TickLoop
new TickLoop
Una tarea por frame (every(0, fn) en el único planificador de tu recurso) que está apagada hasta que la enciendes. Úsala para todo lo que deba ejecutarse en cada frame solo a veces: dibujar un marcador mientras estás cerca, una vista previa de colocación, desactivar el disparo mientras apuntas a un amigo.
Lado: Cliente · Espera: no
new TickLoop(onFrame: () => void, name?: string)Sin equivalente en Lua: aiLib.every(0, fn, { active = false, name = name }) y job:set(active).
Parámetros
Prop
Type
Miembros
Prop
Type
Ejemplo
import { TickLoop, Zones } from "@aicore-fivem/lib/client";
const SPOT = { x: 215.8, y: -810.1, z: 30.7 };
const light = new TickLoop(() => {
DrawLightWithRange(SPOT.x, SPOT.y, SPOT.z + 2, 61, 247, 158, 8, 4);
}, "garageLight");
const zones = new Zones();
zones.add("garage", {
shape: { type: "sphere", center: SPOT, radius: 25 },
onEnter: () => light.set(true),
onExit: () => light.set(false),
});Cada tarea de tu recurso se ejecuta desde un único setTick que solo existe mientras hay una tarea encendida. Crea el bucle una vez al principio del archivo y conmútalo, en lugar de crear uno nuevo en cada inicio.
AreaFollower
new AreaFollower
La mitad de cliente de un AreaStream de servidor (Streaming por áreas): indica al servidor en qué celda de la cuadrícula está el jugador cada vez que cambia (se comprueba cada 2 segundos mientras está iniciado), para que el servidor envíe solo los objetos del mundo (objetos tirados, plantas, props colocados) alrededor del jugador. Crea uno al principio del archivo.
Lado: Cliente · Espera: no
new AreaFollower(event: string, cellSize?: number)Sin equivalente en Lua.
Parámetros
Prop
Type
Miembros
Prop
Type
Ejemplo
import { AreaFollower, onServerEvent } from "@aicore-fivem/lib/client";
const follower = new AreaFollower("myplants:cell");
follower.start();
const plants = new Map<number, unknown>();
// El stream envía (reset, puts, removes): un snapshot con reset en true y después solo cambios.
onServerEvent(
"myplants:area",
{
args: ([reset, puts, removes]) =>
typeof reset === "boolean" && Array.isArray(puts) && Array.isArray(removes)
? ([reset, puts, removes] as const)
: null,
},
(reset, puts, removes) => {
if (reset) plants.clear();
for (const plant of puts as Array<{ id?: unknown } | null>)
if (typeof plant?.id === "number") plants.set(plant.id, plant);
for (const id of removes) if (typeof id === "number") plants.delete(id);
},
);El servidor comprueba una celda informada contra la posición real del jugador (followReported solo acepta celdas a una celda como máximo del ped), así que un tramposo no puede pedir un área lejana.
ServerClock
new ServerClock
El reloj del servidor en un cliente. Los relojes del cliente y del servidor pueden diferir, así que una cuenta atrás hacia una hora del servidor (el cooldown de un robo, el final de una subasta) debe convertirse primero a hora local. Llama a sync con el Date.now() del servidor cada vez que llegue un snapshot o un mensaje de inicio.
Lado: Cliente (desde @aicore-fivem/lib/shared) · Espera: no
new ServerClock()Sin equivalente en Lua.
Miembros
Prop
Type
Ejemplo
import { every, onServerEvent } from "@aicore-fivem/lib/client";
import { ServerClock } from "@aicore-fivem/lib/shared";
const clock = new ServerClock();
let endsAt = 0; // hora local
onServerEvent(
"myauction:state",
{ args: ([now, ends]) => (typeof now === "number" && typeof ends === "number" ? [now, ends] : null) },
(now, ends) => {
clock.sync(now);
endsAt = clock.toLocal(ends);
},
);
every(1000, () => {
const left = Math.max(0, Math.round((endsAt - Date.now()) / 1000));
SendNUIMessage({ action: "countdown", data: left });
});El servidor envía la hora de fin una vez; el cliente cuenta hacia atrás con su propio reloj. Nunca envíes el tiempo restante cada segundo.
Sondeos y carga
raycast, groundZ, locationName, vehicleLabel, waypoint, pedHeadshot, onShot y los cargadores request - preguntar al juego sobre el mundo y cargar recursos del juego.
Pertenencia y datos del jugador
hasJob, inGang, onDutyIn, allows, onMembershipChange, getPlayerData, onPlayerData y seedPlayerData - el personaje, el dinero, los trabajos, el servicio y las bandas del jugador local tal como los envía ai-core.