Zum Inhalt springen
GTA5OS
GTA5OS

Framework

Plugin-System

Wie ein GTA5OS-Plugin aufgebaut ist – Manifest, Lebenszyklus, Services, Berechtigungen und UI-Routen.

Auf dieser Seite
  1. Das Manifest
  2. Lebenszyklus
  3. Services
  4. Berechtigungen
  5. Daten und Migrationen
  6. UI-Routen
  7. Beispiel: ein Plugin ohne Rechte, Commands und Routen

Fast jede Funktion jenseits des Kerns ist ein Plugin: ein eigenes Paket unter packages/gta5os-<name>/, das nur gegen die öffentliche Core-API arbeitet. Der Core kennt kein Plugin; ein Plugin darf nichts verwenden, was der Core nicht ausdrücklich exportiert.

Das Manifest

Jedes Plugin beschreibt sich in einem Manifest. Das Zielbild aus der Architektur sieht so aus:

id: gta5os.inventory
name: Inventory
version: 0.1.0
dependencies:
  - gta5os.core
permissions:
  - inventory.manage
commands:
  - id: inventory.give
ui:
  routes:
    - /inventory
migrations:
  - 001_inventory_init.sql

Der Core prüft das Manifest mit einem Zod-Schema und kann es aus einem Objekt oder einer JSON-Datei laden. Ein Verstoß führt zu einem PluginManifestError, nicht zu stillem Fehlverhalten.

Lebenszyklus

Die Plugin-Runtime ruft vier Hooks auf:

Hook Aufgabe
onRegister(ctx) Statische Registrierung von Commands, Items, Berechtigungen und UI
onStart(ctx) Dienste starten, Event-Handler binden
onPlayerLoaded(player) Spielerbezogene Initialisierung
onStop(ctx) Sauber abmelden, leeren, Messwerte abschließen

Die Runtime prüft vor dem Start die Abhängigkeiten. Commands, Berechtigungen und UI-Routen darf ein Plugin nur registrieren, wenn sie im Manifest stehen; der Lebenszyklus wird protokolliert.

Services

Dienste werden über die Service-Registry verbunden. Tokens sind typisiert, die Registry bietet register, resolve, tryResolve und has. Eine doppelte Registrierung oder ein fehlender Dienst wirft einen Fehler, statt still zu scheitern.

Wer einen neuen Service im Core ergänzt, geht so vor:

  1. Ordner src/<domain>/ mit <domain>-service.ts anlegen.
  2. Eine eigene Fehlerklasse <Domain>Error definieren statt generischer Error.
  3. Werden Berechtigungen gebraucht: eine Konstante <DOMAIN>_PERMISSIONS und register<Domain>Permissions(registry) exportieren und den Aufruf an der gebündelten Stelle der Resource ergänzen.
  4. Die öffentliche API in src/index.ts exportieren. Das ist die einzige Paket-Oberfläche; was dort nicht steht, ist für andere Pakete nicht erreichbar.
  5. Smoke-Szenarien ergänzen.
  6. Hängt eine Tabelle an einer Charakter-ID, wird sie in die Charakter-Kaskade eingetragen, damit beim Löschen eines Charakters nichts verwaist.

Berechtigungen

  • Berechtigungen sind namespaced: plugin.aktion.
  • Es gibt Rollen mit Wildcards, direkte Grants und Denies; ein ausdrückliches Deny widerruft sofort, auch gegen einen Wildcard-Grant.
  • Geprüft wird serverseitig mit assertCan. Spielerrechte sind von höheren Rechten getrennt.
  • Rechte kommen oft nicht aus Rollen, sondern aus dem Job: Job-Capabilities koppeln Funktionen an eine Fraktion oder einen Beruf.

Daten und Migrationen

Plugins speichern über den DataStore-Vertrag des Core und besitzen ihr eigenes Schema. Migrationen laufen kontrolliert über den Core. Gameplay-Code greift nie direkt auf die Datenbank zu, sondern über Repositories; Geld, Inventar und Fahrzeuge werden in Transaktionen geändert.

UI-Routen

Die Oberfläche kennt pro Plugin-Fenster eine Route. Zwei Dinge gehören dazu:

  • Der Core-Service Route-Registry der UI-Shell nimmt die im Manifest deklarierten Routen entgegen.
  • Im Browser-Teil der Shell sind für eine neue Route drei Stellen nötig: die Route-Datei mit render<Name>Route(...), ein Eintrag in der Router-Liste (Pfad, Titel) und ein Eintrag bei den Renderern der Shell. Dazu kommt das öffnende Command oder die Tastenbelegung in der Resource.

Wird eine der drei Stellen vergessen, existiert die Datei zwar, die Route rendert aber nichts oder ist nicht erreichbar. Jede Route braucht außerdem Demo-Daten für die Browser-Vorschau, damit sie sich ohne Spielclient ansehen lässt.

Routen werden bei jedem Öffnen komplett neu gerendert. Die Shell meldet die Handler der vorigen Instanz selbst ab; Timer und eigene Listener muss die Route aber selbst beenden.

Beispiel: ein Plugin ohne Rechte, Commands und Routen

Das Kompatibilitäts-Plugin gta5os.compat.esxqb hat bewusst weder Berechtigungen noch Commands oder UI-Routen. Es bildet ESX- und QBCore-artige Aufrufe (Geld, Konten, Inventar) auf die Core-Dienste ab, ohne eigene Datenbankzugriffe und ohne Änderung am Core. Reale ESX-Resources lassen sich so mit einem dünnen Lua-Shim weiterverwenden.

Tippe mindestens zwei Buchstaben.