Files
fivem/PORTING.md

4.4 KiB

FiveM Port — Feature Porting Guide

Status

Layer Status Notes
TypeORM entities (207) Copied verbatim Zero changes needed
Express REST API Copied verbatim Zero changes needed
Shared constants Copied verbatim
Core log/DB/Redis/Mongo Copied verbatim
mp server shim Done Covers events, players, vehicles, config
mp client shim Done Covers events, game, gui, browsers→NUI
RPC system Done Replaces mp.events.addProc
Player wrapper Done Wraps FiveM net ID into PlayerMp-compatible object
Vehicle wrapper Done Wraps FiveM entity handle
CommandSystem Done Uses RegisterCommand() per command
Server features (101) 🔲 Not started See porting order below
Client features (~80) 🔲 Not started See porting order below

How to port a server feature

  1. Copy the feature folder from game-server/src/features/<name>/ to fivem-server/src/server/features/<name>/
  2. Fix imports — update relative paths (e.g. ../../entities/../../entities/, ../../core/ stays the same)
  3. Search for mp.colshapes — FiveM has no server colshapes. Replace with the polygon position-tracking system.
  4. Search for mp.objects.new / mp.peds.new — use FiveM CreateObject / CreatePed natives.
  5. Search for player.call( — this works unchanged via PlayerWrapper.call().
  6. Uncomment the import in src/server/index.ts and add to featuresParallel or featuresSeries.

How to port a client feature

  1. Copy the feature folder from game-client/src/<name>/ to fivem-server/src/client/features/<name>/
  2. Fix imports
  3. Replace mp.events.addProc with rpc.registerClientProc from ../core/rpc
  4. Replace mp.browsers.new(url).execute(js) with nui.send(type, data) (PostMessage to Vue)
  5. Replace mp.game.invoke(hash, ...args) with direct native calls where the name is known, or keep mp.game.invoke (the shim passes through to Citizen.invokeNative)
  6. Uncomment the require in src/client/index.ts

Suggested porting order (server features)

Start with features that have minimal RageMP API surface and no colshape dependency:

  1. shared — pure data sync
  2. time — simple, no colshapes
  3. weather — simple
  4. chat — core comms, needed by everything
  5. login — needed before players can do anything
  6. session — depends on login
  7. player — needed by commands
  8. permissions — needed by guards
  9. money — needed by jobs/most features
  10. inventory — high-value, many features depend on it
  11. vehicle — large but critical
  12. job/* — already on feature/jobsystem branch, good to port early

Defer until late (complex colshape or streaming dependencies):

  • properties (heavy colshape use → needs polygon system)
  • furniture (server objects)
  • drugs (colshapes + objects)
  • graffiti (colshapes)

RageMP → FiveM cheatsheet

RageMP (server) FiveM (server)
mp.events.add('playerJoin', (p) => ...) Auto-mapped by shim → playerConnecting
mp.events.add('playerQuit', (p) => ...) Auto-mapped by shim → playerDropped
mp.events.add('myEvent', (p, data) => ...) Shim registers net event; player injected from source
player.call('event', [a, b]) TriggerClientEvent('event', netId, a, b)
player.notify(msg) TriggerClientEvent('_mp:notify', netId, msg)
player.setVariable(k, v) FiveM StateBag: Player(id).state.set(k, v, true)
mp.vehicles.new(model, pos, opts) vehicleRegistry.create(model, pos, opts)
mp.events.addProc('name', fn) rpc.register('name', fn)
mp.colshapes.newSphere(...) Use polygon position tracking system
mp.players.broadcast(msg) TriggerClientEvent('_mp:chatMessage', -1, msg)
RageMP (client) FiveM (client)
mp.events.add('render', fn) Shim adds to tick loop
mp.events.callRemote('event', ...args) TriggerServerEvent('event', ...args)
mp.events.addProc('name', fn) rpc.registerClientProc('name', fn)
mp.players.local.setComponentVariation(...) SetPedComponentVariation(PlayerPedId(), ...)
mp.game.invoke('0xHASH', ...args) Citizen.invokeNative('0xHASH', ...args)
mp.browsers.new(url) FiveM NUI (declared in fxmanifest.lua, one page)
mp.gui.chat.push(msg) TriggerEvent('chat:addMessage', { args: [msg] })