Bolsas de estado de FiveM: Entity(entity).state, GlobalState y manejadores
Cómo funcionan las bolsas de estado de FiveM: Entity(entity).state, Player(source).state, LocalPlayer.state, GlobalState, :set, manejadores de cambios, y cuándo preferirlas a los eventos
Quieres compartir un pequeño dato entre el servidor y cada cliente, por ejemplo que un vehículo está bloqueado, que un jugador está esposado, o el clima actual, y sigues escribiendo eventos que se disparan en cada cambio y se dessincronizan para los jugadores que se unen después. Las bolsas de estado son la respuesta integrada.
Este artículo cubre los tipos de bolsas de estado, cómo escribir y leer, cómo reaccionar a cambios, y cuándo un evento sigue siendo la mejor opción.
¿Qué es una bolsa de estado?
Una bolsa de estado es un almacén tipo tabla de claves y valores adjunto a algo. El tiempo de ejecución lo sincroniza por ti, incluso para los jugadores que se conectan después de que se estableció el valor. FiveM te da tres tipos:
| Bolsa | Lee y escribe con | Vive en |
|---|---|---|
| Una entidad | Entity(entity).state |
La entidad (ped, vehículo, objeto) |
| Un jugador | Player(source).state en el servidor, LocalPlayer.state en el cliente |
El jugador |
| El servidor | GlobalState |
Todo el servidor |
En todos ellos lees un valor como un campo normal:
local locked = Entity(vehicle).state.lockedEscribiendo desde el servidor
En el servidor, establecer un valor lo replica a los clientes que pueden ver esa bolsa:
-- server
local veh = CreateVehicle(`adder`, 215.0, -810.0, 30.7, 90.0, true, true)
Entity(veh).state.locked = true
Player(source).state.cuffed = true
GlobalState.weather = 'RAIN'Puedes usar el estilo de campo o la llamada explícita, que también te permite elegir si el valor se replica:
Entity(veh).state:set('locked', true, true):set(key, value, replicated) toma la clave, el valor y un booleano. Con true el valor se envía al otro lado, con false se queda en el lado que lo escribió.
Consejo: los valores pueden ser números, cadenas, booleanos y tablas. Una tabla se copia cuando la estableces, por lo que cambiar un campo en la tabla que lees no hace nada. Establece la tabla completa nuevamente para actualizarla.
Escribiendo desde el cliente
Un cliente puede escribir en su propio jugador y en entidades que controla, pero una asignación simple permanece local:
-- client
LocalPlayer.state:set('inService', true, true) -- replicated to the server
LocalPlayer.state.hasMask = true -- local onlyEl servidor puede leer Player(source).state.inService después de eso. Trátalo como no confiable: un cliente modificado puede escribir cualquier valor que quiera. Usa estado escrito por cliente por conveniencia, como indicadores de interfaz de usuario, y mantén cualquier cosa con una ventaja adjunta (dinero, trabajo, permisos) en el servidor.
GlobalState es lo opuesto: el servidor lo escribe, cada cliente lo lee, y los clientes no pueden cambiarlo para otros.
-- client
local weather = GlobalState.weatherReaccionando a cambios
En lugar de sondear un valor en un bucle, registra un manejador que se ejecute cuando cambie una clave. Esta es la razón principal para usar bolsas de estado en el cliente:
-- AddStateBagChangeHandler(keyFilter, bagFilter, handler)
AddStateBagChangeHandler('locked', nil, function(bagName, key, value, reserved, replicated)
local entity = GetEntityFromStateBagName(bagName)
if entity == 0 then return end
SetVehicleDoorsLocked(entity, value and 2 or 1)
end)keyFilteres la clave que te importa, onilpara cada clave.bagFilterlimita la bolsa, por ejemplo una bolsa de jugador específica, onilpara todas.bagNamese parece aentity:1234,player:5oglobal.GetEntityFromStateBagNameconvierte una bolsa de entidad en un identificador, yGetPlayerFromStateBagNamehace lo mismo para una bolsa de jugador.
En el cliente, la entidad puede no existir aún cuando se dispara el manejador, por ejemplo para un vehículo que aún se está transmitiendo. GetEntityFromStateBagName puede devolver 0 en ese caso, así que verifica si lo hace. Leer el estado nuevamente cuando la entidad se transmite es el hábito seguro.
La misma función existe en el servidor, donde es útil para reaccionar a un cliente que escribe un valor replicado.
Bolsas de estado o eventos
| Usa una bolsa de estado cuando | Usa un evento cuando |
|---|---|
| El valor describe el estado actual de algo (bloqueado, esposado, de servicio) | Algo sucedió una vez (una compra, un golpe, una pulsación de botón) |
| Los jugadores que se unen después deben ver el valor | Solo los jugadores presentes ahora necesitan saber |
| Muchos jugadores necesitan leerlo en cualquier momento | Un jugador necesita que se le diga algo |
| De lo contrario, sondarías en un bucle | Necesitas pasar un resultado o una carga útil única |
Una buena regla: los eventos son para acciones, las bolsas de estado son para estado. Si un jugador que se une a mitad de camino necesitaría que se le dijera lo mismo nuevamente, es estado. Ver eventos del cliente y el servidor para el otro lado.
Errores comunes
- Usarlo para datos grandes o que cambian rápidamente. Cada cambio se envía a través de la red. No escribas una posición en una bolsa de estado cada fotograma.
- Confiar en las escrituras del cliente. Valida cualquier cosa que un cliente establezca antes de actuar en ella en el servidor.
- Esperar que el manejador se ejecute antes de que exista la entidad. Verifica el identificador y lee el estado nuevamente cuando aparezca la entidad.
- Mutar una tabla en su lugar. Leer
state.items, agregarle y no establecerlo nuevamente no cambia nada. - Olvidar el reinicio. El estado en una entidad desaparece con la entidad, pero el estado en un jugador o
GlobalStatese queda hasta que lo limpies, así que establécelo ennilcuando hayas terminado.
Player(source).state.cuffed = nilLista de verificación
| Síntoma | Solución |
|---|---|
| El cliente establece un valor pero el servidor nunca lo ve | Usa :set(key, value, true) para que se replique |
El manejador se ejecuta pero el identificador de la entidad es 0 |
La entidad aún no se ha transmitido: verifica y lee el estado nuevamente más tarde |
| Los recién llegados se pierden el valor | Usa una bolsa de estado en lugar de un evento |
| El cambio de tabla no se sincroniza | Establece la tabla completa nuevamente con :set |
No se puede cambiar GlobalState desde el cliente |
Solo el servidor la escribe: envía un evento y deja que el servidor la establezca |
| El valor antiguo permanece después de que el trabajo esté terminado | Establece la clave en nil |
Respuestas rápidas
¿Qué es una bolsa de estado en FiveM?
Un almacén de clave y valor adjunto a una entidad, un jugador o todo el servidor. Los valores que estableces se sincronizan al otro lado por el juego, por lo que no necesitas disparar un evento para cada cambio.
¿Puede un cliente cambiar una bolsa de estado y que el servidor la vea?
Solo si el valor se establece con replicación activada, por ejemplo LocalPlayer.state:set('key', value, true). Una asignación simple en el cliente permanece local, y el servidor nunca debería confiar en ella para nada que importe.
¿Las bolsas de estado necesitan OneSync?
Las bolsas de estado de entidad dependen de OneSync, que los servidores actuales utilizan por defecto. El estado del jugador y GlobalState son los casos más fáciles para comenzar.
Scripts que evitan este problema
Parrots as PetsCatorce pájaros que van en tu hombro, vuelan contigo y vuelven cuando los llamas.Ver script →
Advanced BoostingBoosting de vehículos desde una tablet: contratos de clase D a S+, crews y cola en vivo.Ver script →
Hookah SystemCachimbas y muebles de lounge colocables, con más de 50 sabores y efectos.Ver script →