Port the behavior, not just the function names
A resource port needs a feature-by-feature comparison of execution context, ownership and failure behavior. The official platform migration reference mixes general guidance with Legacy-era Mono and Mumble descriptions. Apply the more specific Enhanced migration contract when targeting Enhanced; do not promise that both tracks share those runtime details.
Entity creation: server record versus client simulation
A server RPC native forwards work to a suitable client. Creation can fail when no nearby client can perform it or that client disconnects. Bound any wait, check the returned handle and check existence before attempting subsequent operations. A timeout is an error path, not proof that a second creation request is safe to issue indefinitely.
Server setters such as CreateVehicleServerSetter, server CreatePed and CreateObjectNoOffset create server-side entity records without requiring immediate nearby simulation. The older CreateAutomobile path is deprecated. Choose the documented native for the entity type and runtime; never infer its argument order from a similarly named client native.
An entity can initially be orphaned: it is registered but has no client simulating it. The documented owner query can return -1. A server getter may read its stored state while an owner-dependent RPC setter cannot run. Consequently, “nonzero server handle” and “visible, simulated and configured in the game” are different acceptance checks.
For appearance or other owner-dependent setup, keep the desired settings in server-owned state, replicate an initialization request and let the current owner apply the client operation. Re-check existence and ownership before each application. Make that application idempotent, bounded and safe to repeat after owner changes. A state-bag value is not the state-bag proxy: use Entity(entity).state:set(...) to update it, not :set on a boolean returned by GetStateBagValue.
The upstream warning describes an ownership race after a handler returns but before appearance state reaches the server. Verify important resulting state server-side and use a bounded recovery path. Do not clear the desired configuration permanently solely because one client said it applied it. See state bags and network IDs.
Translate platform abstractions explicitly
| Source-platform concept | FiveM implementation boundary |
|---|---|
| Colshapes / zones | Enhanced has colshape natives. Legacy requires region tests or a suitable zone resource. A shape detects a candidate interaction; the server still validates authorization and position. |
| Script-level dynamic objects | There is no universal non-game dynamic-entity abstraction. Implement streaming and behavior around native game entities or your own data structures. |
| Typed checkpoint/entity wrappers | Use the relevant game natives and local handles. A wrapper object from another SDK is not serializable FiveM entity identity. |
| Dimensions / instances | Use routing buckets where appropriate; they have a memory and ownership cost. Buckets are not a universal replacement for interiors. |
| Server-owned physics authority | Client ownership/forwarding still matters. Server-authoritative business rules do not mean every physical setter executes without a client. |
| Synchronized metadata | Use state bags with explicit replication, suitable ownership and shallow keys. They are not a database or permission system. |
| High-level application RPC | Build bounded request/reply conventions on network events or select a reviewed library. This differs from the platform’s internal server RPC natives. |
disableOutgoingSync | No direct equivalent is documented. Camera/spectating designs may solve the actual viewing requirement without teleporting an entity and expecting hidden synchronization. |
| Reconnect | A reconnect fully disconnects and resets game state. During development, prefer controlled ensure resourceName restarts when that is the operation being tested. |
| Player display names | The built-in name is user-controlled in the FiveM menu. Store a separate validated character/display name when the application needs one. |
Control requests, streaming and pools
The source records sv_filterRequestControl modes as follows. Read server configuration before combining them with a framework or entity-lockdown policy.
| Mode | Intended filtering distinction |
|---|---|
0 | No filtering in the source’s default description. |
1 | Reject requests for player-owned vehicles after the settle interval; early handoff remains possible. |
2 | Apply that protection without the unsettled-entity exception. |
3 | Block requests for controlled or settled entities. |
4 | Block all control requests. |
These settings are not a substitute for server-side authorization. Test legitimate vehicle entry, scripted ownership changes and resource restarts as well as rejected control attempts.
A large server can still exceed client game-pool capacity in a dense area. The absence of a simple global server entity cap does not imply unlimited usable entities. Inspect local density, ownership and relevant pool usage; the upstream references to SetEntityDistanceCullingRadius are not a blanket recommendation to deploy deprecated culling tuning. OneSync documents the limitations and the more targeted diagnostics.
increase_pool_size is a startup configuration operation, not a runtime allocation API. Clients can restart when their pools must match the server configuration. Record the actual pool name, baseline and supported increase, then test connection and dense scenes. A high advertised player capacity is not a performance guarantee; current slot entitlements must be checked separately.
Languages, modules and filesystem dependencies
Separate client JavaScript, server JavaScript and browser NUI bundles. Node APIs belong to the server runtime, not automatically to the client or browser. Produce the module format the selected resource runtime supports; the upstream’s general CommonJS guidance is not permission to import any Node package on the client. Use JavaScript runtime helpers and async interoperability.
Legacy C# uses Mono-oriented assemblies; Enhanced uses the .NET contract in the migration reference. Compile and test each intended target rather than assuming an old Entity Framework or native-library dependency loads unchanged. C# native wrappers also have language-specific namespaces and naming conventions; “the same engine native exists” does not mean identical source syntax in all three languages.
Filesystem and process access are sandboxed. Some dependencies probe container or OS files during startup. Identify the probe and use supported configuration before considering a narrowly reviewed compatibility adaptation. A global patch to fs.promises.access can affect unrelated code and conceal a real deployment error; it is not part of a default migration recipe.
Identities, storage and admission
Keep local entity handles, network entity IDs, client player indices and server session IDs separate. Do not send a local handle to another runtime and assume it resolves there. Validate conversion results and out-of-scope cases. A player ped is an entity; its local handle is not the player’s server ID.
Read verified identifiers on the server. The platform migration source prefers license2 when both license and license2 are present; handle missing identifiers explicitly and apply a consistent account-linking policy. GetNumPlayerIdentifiers / GetPlayerIdentifier and GetNumPlayerTokens / GetPlayerToken serve different purposes. Do not broadcast identifiers or hardware-related tokens, use them as public profile keys, or confuse a reusable session ID with a durable account.
KVP storage supports strings, integers and floats on client and server. Use the matching getter/setter type, explicit defaults and a versioned data format. Client KVP is not authoritative account storage. Back up persisted data; Legacy-to-Enhanced KVP conversion is a separate migration gate, not an assumed compatible file copy.
Map source-platform roles to deliberately scoped ACE permissions, not a universal administrator grant. txAdmin is optional administration tooling, not a replacement for application permissions or a mandatory resource dependency. Voice integration must follow the selected track’s voice reference.
Port acceptance matrix
For each feature, record its old contract, new client/server owner, serialization format, authorization rule, bounded failure path and rollback. Test no nearby players, owner disconnect, owner change, an entity leaving scope, repeated requests, invalid network IDs, session reuse, resource restart and database failure. Keep monetary or inventory mutations entirely server-authoritative and idempotent.
This document supplies the mapping and test obligations. It does not claim an arbitrary resource has been ported, prove in-game simulation from website tests, or treat an upstream example as correct without reviewing its runtime context. Continue with secure events, event delivery and resource lifecycle.