5MCustoms

NUI-Oberflächen

Die Oberflächen sind Next.js-Anwendungen, die als statischer Export gebaut werden. FiveM lädt sie von der Festplatte, es gibt keinen Server und keinen Host-Root.

Konfiguration

// nui/next.config.mjs
export default {
  output: 'export',
  distDir: '../dist/nui',
  assetPrefix: '.',
  trailingSlash: true,
  images: { unoptimized: true },
  transpilePackages: ['@5mc/ui', '@5mc/types'],
};

assetPrefix: '.' ist entscheidend: absolute Pfade würden ins Leere zeigen, weil die Seite unter einer nui://-Adresse läuft. images.unoptimized muss gesetzt sein, weil der Bild-Optimierer einen laufenden Server bräuchte.

Brücke zum Client

import { isNui, nuiFetch, onNuiMessage } from '@5mc/ui';

// Anfrage an den Client-Teil des Moduls
const daten = await nuiFetch<Daten>('meinmodul:laden', { id }, mockDaten);

// Nachricht vom Client entgegennehmen
onNuiMessage<{ offen: boolean }>('meinmodul:sichtbar', ({ offen }) => {
  setOffen(offen);
});

nuiFetch erkennt, ob es im Spiel läuft. Außerhalb liefert es die Mock-Daten aus dem dritten Argument. Dadurch kannst du die komplette Oberfläche im Browser entwickeln:

cd resources/mein_modul/nui
npm run dev

Marke und Sprache

Der Client-Teil ruft einmal installNuiEnv() auf. Danach kennt die Oberfläche Markenname, Logo, Farbe und Sprache:

import { EnvProvider, useBrand, BrandLogo } from '@5mc/ui';

function Kopf() {
  const brand = useBrand();
  return (
    <header>
      <BrandLogo height={40} />
      <span>{brand.name}</span>
    </header>
  );
}

Zum Formatieren stehen useNumberFormat und useMoneyFormat bereit, damit Beträge in beiden Sprachen richtig aussehen.

Bauen

node tools/build-resource.mjs resources/mein_modul

Der Build erzeugt Server- und Client-Bundle und ruft anschließend den Next-Export auf. Das Ergebnis liegt unter dist/nui und wird über das Feld nui in module.config.mjs ins Manifest eingetragen.

Zwei Fallen

Pfad-Schreibweise unter Windows. Arbeite aus dem exakt geschriebenen Pfad, also C:\Users\…\Documents\… mit großem D. Aus einer abweichenden Schreibweise bricht Next mit einer Meldung über Groß- und Kleinschreibung ab.

Paket-Layout. Der Workspace nutzt bewusst ein flaches Paketlayout statt Symlinks. Mit Symlinks bündelte der Build Server-Interna ins Client-Paket, und jede Oberfläche starb mit einem Fehler über einen nicht eingehängten Layout-Router.