Both default skins spell the chin width key chin_13. skinchanger only
knows chin_1 through chin_4, so the value never reaches the ped and the
key is stored as junk in users.skin.
It also breaks the ped. SetFace reads every feature through
Normalise(weight, 10), which divides, so a missing chin_3 raises
"attempt to perform arithmetic on a nil value" at feature index 17.
Everything after that in ApplySkin is skipped: the remaining features,
the eye colour, the head overlays, the components and the props.
The column is varchar(22), which is a leftover from Steam identifiers.
esx_vehicleshop writes a player identifier into it, and on a
multicharacter server those are 46 characters long, so renting a vehicle
out fails.
The stock vehicle is deleted from cardealer_vehicles before the insert
runs, so the dealer loses the car and the customer never gets a rental
contract. Neither side is told anything, because the handler dies on the
insert.
esx_vehicleshop's own esx_vehicleshop.sql already declares varchar(60).
The column is varchar(40) but esx_billing writes an identifier into it, and
those are 46 characters once multicharacter is on, so the insert fails with
1406 and the handler dies before notifying either player. The other two
identifier columns in the same table are already varchar(60).
xLib.name was "xLib", which is not a resource, so the import metatable fed it to LoadResourceFile and resolved nothing. It failed silently on Legacy and hard-errored on Enhanced (Resource 'xLib' not found). Point it at the real resource name.
xLib.isEnhanced() returns whether the game runs GTA V Enhanced (server: gamename convar, client: IsGameEnhancedVersion native). es_extended reads it once and requires OneSync Infinity on Legacy only, since Enhanced runs OneSync natively.
Adds xLib.pubsub for server-driven topic multicast: a producer resource
subscribes players to a topic server-side and publishes data that is pushed
only to the subscribed players. Clients listen with xLib.pubsub.on and never
subscribe or publish themselves.
The subscription registry is a single shared instance in the esx_lib server VM,
reached cross-resource through exports; the client side is a per-VM listener
over one net event. Subscriptions are cleaned up on playerDropped, so a reused
serverId never inherits them, and on the owning resource stopping.
Also adds xLib.triggerClientEvent, which packs the payload once when sending to
many players; publish uses it so a broadcast to N subscribers serialises once.
Adds a generic xLib.cache (ped, vehicle, seat, weapon, coords) modelled on
ox_lib cache and framework agnostic, and rewires es_extended to source ped and
weapon from it which removes the per-frame ped poll. The vehicle enter/exit
state machine and every esx: event are kept unchanged through a thin glue.
Moved getPlayersInArea / getClosestPlayer / getPedsInArea / getObjectsInArea /
getVehiclesInArea / getClosestPed / getClosestObject / getClosestVehicle to
xLib; es_extended re-exposes them through server compat shims.
Flagged: getNearbyPlayers iterates ESX.Players (es_extended server state),
which is not portable across the lib boundary - the lib relies on that global
being present at call time.
Integrated fix during the move:
- spawnVehicle uses the computed isNetworked for the network-id/migrate guard,
fixing the original that branched on the raw networked argument
modSmokeEnabled preserved as-is in get/setVehicleProperties (flagged: the set
path toggles mod 20 without applying a smoke color, matching legacy behavior).
Non-portable substitution documented:
- ESX.PlayerData.ped -> PlayerPedId() (ESX.PlayerData is not available in the lib VM)
Integrated fixes during the move:
- monotonic handle counter (handleCount) instead of count+1; no handle
collision after a point is removed
- unified single proximity loop: per-frame inside() plus a 500ms enter/leave
scan, adaptive Wait(next(insidePoints) and 0 or 500), replacing the previous
two separate loops
- emptiness detected via next() instead of # on a sparse-keyed table
Non-portable substitutions documented:
- ESX.PlayerData.ped -> PlayerPedId() (ESX.PlayerData is not available in the
lib VM)
- GetGameTimer() used to gate the 500ms scan within the single loop