4.4 KiB
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
- Copy the feature folder from
game-server/src/features/<name>/tofivem-server/src/server/features/<name>/ - Fix imports — update relative paths (e.g.
../../entities/→../../entities/,../../core/stays the same) - Search for
mp.colshapes— FiveM has no server colshapes. Replace with the polygon position-tracking system. - Search for
mp.objects.new/mp.peds.new— use FiveMCreateObject/CreatePednatives. - Search for
player.call(— this works unchanged viaPlayerWrapper.call(). - Uncomment the import in
src/server/index.tsand add tofeaturesParallelorfeaturesSeries.
How to port a client feature
- Copy the feature folder from
game-client/src/<name>/tofivem-server/src/client/features/<name>/ - Fix imports
- Replace
mp.events.addProcwithrpc.registerClientProcfrom../core/rpc - Replace
mp.browsers.new(url).execute(js)withnui.send(type, data)(PostMessage to Vue) - Replace
mp.game.invoke(hash, ...args)with direct native calls where the name is known, or keepmp.game.invoke(the shim passes through toCitizen.invokeNative) - 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:
shared— pure data synctime— simple, no colshapesweather— simplechat— core comms, needed by everythinglogin— needed before players can do anythingsession— depends on loginplayer— needed by commandspermissions— needed by guardsmoney— needed by jobs/most featuresinventory— high-value, many features depend on itvehicle— large but criticaljob/*— 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] }) |