Nebula Store

Dokumentation

Offizielle Installations- und Konfigurationsanleitung für das Nebula Shop-System — bestehend aus nebula_core, nebula_notify und nebula_shop.

01 — Produkte

Was ist enthalten?

Das Nebula Shop-System besteht aus drei einzelnen Ressourcen, die zusammenarbeiten. Jede hat eine klar definierte Aufgabe.

Core
nebula_core
Datenbank, Preis-Engine, Sicherheit, Framework-Adapter
UI
nebula_notify
Notification-System & TextUI (Exports für alle Scripts)
Shop
nebula_shop
Shop UI, Marker, Blips, Kauflogik, NUI Interface
Auto-Detection: Das System erkennt dein Framework (ESX / QBCore / ox_core) und dein Inventory vollautomatisch. Keine manuelle Framework-Einstellung nötig.

02 — Setup

Voraussetzungen

Folgende Ressourcen müssen auf deinem Server laufen, bevor die Nebula Scripts gestartet werden.

RessourceZweckPflicht
oxmysqlDatenbankanbindung (wird direkt in fxmanifest eingebunden)Ja
es_extendedESX Framework — Geld, Inventar, PlayerESX oder QBCore
qb-coreQBCore Framework — Alternative zu ESXESX oder QBCore
ox_coreox_core Framework — weitere AlternativeOptional
ox_inventoryInventarsystem (wird bevorzugt erkannt)Optional
qs-inventoryAlternative zu ox_inventoryOptional
qb-inventoryQBCore InventarsystemOptional
codem-inventoryWeiteres unterstütztes InventarsystemOptional
Das Script erkennt Framework und Inventory automatisch anhand der laufenden Ressourcen. Priority: ox_inventory › qb-inventory › qs-inventory für Inventory und ESX › QBCore › ox_core für Framework.
03 — Reihenfolge

Startreihenfolge

Die Ressourcen haben feste Dependencies. nebula_shop deklariert in seiner fxmanifest.lua explizit beide anderen als Abhängigkeiten.

oxmysql
es_extended / qb-core
nebula_core
nebula_notify
nebula_shop
server.cfg
# Framework (nur das, was du verwendest)
ensure oxmysql
ensure es_extended          # oder qb-core

# Optional: ox_inventory, qs-inventory, etc.
ensure ox_inventory

# Nebula — genau in dieser Reihenfolge!
ensure nebula_core
ensure nebula_notify
ensure nebula_shop

Installation

nebula_core

Das Herzstück des Systems. Verwaltet die Datenbank, die dynamische Preis-Engine, Sicherheitsfilter und stellt Exports für alle anderen Nebula-Scripts bereit.

Installation

1
Ordner platzieren
Den Ordner nebula_core in dein /resources/ Verzeichnis verschieben. Empfohlen: Unterordner [nebula].
Struktur
/resources/[nebula]/nebula_core/
├── config.lua
├── fxmanifest.lua
├── migration_fix_shopid.sql
├── server/
│   ├── adapters.lua    ← Framework/Inventory Auto-Detection
│   ├── db.lua          ← Database layer
│   ├── logger.lua      ← Discord Webhook Logging
│   ├── main.lua        ← Purchase logic & security
│   ├── pricing.lua     ← Dynamic pricing engine
│   └── utils.lua
└── shared/
    └── api.lua
2
Datenbanktabellen anlegen
Das Script erstellt beim ersten Start automatisch alle benötigten Tabellen. Falls Probleme auftreten, führe die SQL-Migration manuell aus.
SQL
-- File: nebula_core/migration_fix_shopid.sql
-- Run once if you get shop_id errors:
ALTER TABLE ns_price_state
  MODIFY COLUMN shop_id INT NOT NULL DEFAULT 0;
Die Tabellen ns_shops, ns_items, ns_shop_items, ns_price_state und ns_transactions werden automatisch beim Start erstellt.
3
server.cfg eintragen
server.cfg
ensure nebula_core
Installation

nebula_notify

Das Notification-System für alle Nebula Scripts. Stellt drei Exports bereit: Notify, TextUI und HideTextUI. Wird von nebula_shop automatisch verwendet.

Installation

1
Ordner platzieren
Den Ordner nebula_notify in /resources/[nebula]/ verschieben.
2
server.cfg eintragen
server.cfg
ensure nebula_notify

Verfügbare Exports

ExportParameterBeschreibung
Notifymessage, type, durationZeigt eine Notification. type: 'success' | 'error' | 'info'. duration in ms (Standard: 3500)
TextUImessageZeigt den Interaktionshinweis beim Nähern an einem Marker
HideTextUIVersteckt die TextUI wieder
Lua
-- Send notification
exports['nebula_notify']:Notify('Purchase successful!', 'success', 3500)
exports['nebula_notify']:Notify('Not enough money.', 'error', 4000)

-- TextUI interaction hint
exports['nebula_notify']:TextUI('~INPUT_CONTEXT~ Open Shop')
exports['nebula_notify']:HideTextUI()
Installation

nebula_shop

Verwaltet alle Shops mit Markern, Blips und der NUI-Oberfläche. Beim Serverstart werden alle Shops aus der config.lua automatisch in die Datenbank synchronisiert.

Installation

1
Ordner platzieren
Den Ordner nebula_shop in /resources/[nebula]/ verschieben.
Struktur
/resources/[nebula]/nebula_shop/
├── config.lua          ← Define all shops & items here
├── fxmanifest.lua
├── client/
│   └── main.lua        ← Markers, blips, proximity detection
├── server/
│   └── main.lua        ← Config sync, shop data, purchase handling
└── web/
    ├── index.html
    ├── app.js          ← Shop NUI interface
    ├── style.css
    └── items/          ← Item images (.png/.jpg/.webp)
2
Item-Bilder hinzufügen (optional)
Lege Item-Bilder im Ordner web/items/ ab. Dateiname = Item-Name (z.B. bread.png). Unterstützte Formate: .png, .jpg, .webp.
3
Shops in config.lua konfigurieren
Alle Shops und Items werden in der config.lua definiert. Beim Serverstart synchronisiert der Server sie automatisch in die Datenbank.
4
server.cfg eintragen & Server neustarten
server.cfg
ensure nebula_shop
Nach dem Start siehst du in der Konsole: [NebulaShop] Config sync complete. Shops=X — dann läuft alles korrekt.

Ingame-Steuerung

AktionStandardConfig-Variable
Shop öffnenE (Key 38)NebulaShop.OpenKey
Marker anzeigen ab15.0NebulaShop.DrawDistance
Interaktionsradius2.0NebulaShop.InteractDistance

Konfiguration

nebula_core — config.lua

Steuert die Preis-Engine, Sicherheitseinstellungen und das Discord-Logging.

nebula_core/config.lua
NebulaCore = {}

-- Debug output in server console (set false in production!)
NebulaCore.Debug = true

NebulaCore.Price = {
  Enabled = true,          -- Enable dynamic pricing?
  Scope   = 'global',      -- 'global' = shared price across shops
                              -- 'shop'   = each shop has its own price
  UpdateIntervalSeconds = 60,  -- How often prices are recalculated
  MaxStepPercent  = 0.15,    -- Max 15% price change per update
  RandomRange     = 0.08,    -- ±8% random market fluctuation
  DemandWeight    = 0.35,    -- Influence of purchase demand (last hour)
  DefaultTrend    = 1.0
}

NebulaCore.Security = {
  MaxPurchasesPer10s = 50,  -- Rate limiting: max purchases in 10 seconds
  MaxQtyPerTxn       = 200, -- Max quantity per single purchase
  LockTimeoutMs      = 500  -- Minimum pause between purchases (ms)
}

NebulaCore.Logging = {
  DiscordWebhook = '',      -- Discord webhook URL for purchase logs
  LogPurchases   = true,
  LogSuspicious  = true
}
VariableTypBeschreibung
NebulaCore.DebugbooleanPreis-Updates und Events in der Serverkonsole ausgeben
Price.Scopestring'global': ein globaler Preis für alle Shops. 'shop': eigene Preise pro Shop
Price.UpdateIntervalSecondsnumberSekunden zwischen automatischen Preis-Updates
Price.MaxStepPercentnumberMaximale Preisänderung pro Update (0.15 = max ±15%)
Price.RandomRangenumberZufällige Marktschwankung auch ohne Käufe (0.08 = ±8%)
Price.DemandWeightnumberWie stark Käufe den Preis erhöhen (0.35 = 35% Einfluss)
Security.MaxPurchasesPer10snumberRate-Limiting: maximale Käufe innerhalb von 10 Sekunden
Security.MaxQtyPerTxnnumberMaximale Stückzahl in einem einzelnen Kauf
Logging.DiscordWebhookstringDiscord Webhook URL — leer lassen um Logging zu deaktivieren
Konfiguration

nebula_shop — config.lua

Hier werden alle Shops mit Koordinaten, Markern, Blips und Items definiert. Beim Serverstart werden diese automatisch in die Datenbank synchronisiert — kein manuelles SQL nötig.

nebula_shop/config.lua
NebulaShop = {}

NebulaShop.OpenKey          = 38    -- E key to open shop
NebulaShop.DrawDistance     = 15.0  -- Marker visible from this distance
NebulaShop.InteractDistance = 2.0   -- Interaction hint at this distance

NebulaShop.Shops = {
  {
    key    = '247_grove',        -- Unique key (must be unique!)
    name   = '24/7 (Grove)',
    type   = 'shop',
    coords = vector3(25.7, -1346.6, 29.5),
    marker = { enabled = true, type = 2, scale = 0.65 },
    blip   = { enabled = true, sprite = 52, scale = 0.75, colour = 2, label = '24/7' },
    items  = {
      { name = 'bread', label = 'Bread', base_price = 50, min_price = 30, max_price = 120, tax = 0.05 },
      { name = 'water', label = 'Water', base_price = 35, min_price = 20, max_price = 100, tax = 0.05 },
    }
  },

  -- Black market example (no blip, hidden location)
  {
    key    = 'black_market_grove',
    name   = 'Black Market',
    type   = 'shop',
    coords = vector3(318.6, -197.5, 53.5),
    marker = { enabled = true, type = 2, scale = 0.5 },
    blip   = { enabled = false },  -- No blip on the map!
    items  = {
      { name = 'weed_brick', label = 'Weed', base_price = 800, min_price = 500, max_price = 1800 },
    }
  },
}

Item-Felder erklärt

FeldTypBeschreibung
namestringItem-Name — muss exakt mit deiner items.lua übereinstimmen
labelstringAnzeigename im Shop UI
base_pricenumberAusgangspreis für die Preis-Engine
min_pricenumberUntere Preisgrenze — Preis fällt nie darunter
max_pricenumberObere Preisgrenze — Preis steigt nie darüber
taxnumberSteuer-Multiplikator (0.05 = 5% Aufschlag, optional)
💡
Shops können per Konsolenbefehl ohne Neustart neu synchronisiert werden: ns_resync_shops (nur aus der Serverkonsole).
Konfiguration

Dynamische Preise

Die Preis-Engine in nebula_core berechnet Preise in Echtzeit basierend auf Nachfrage und Marktschwankungen.

Wie funktioniert die Berechnung?

📊
Formel:
target = base_price × demandFactor × randomFactor

Dann wird der Preis sanft in Richtung des Zielpreises verschoben (max. MaxStepPercent pro Update) und innerhalb von min_price und max_price gehalten.
FaktorBeschreibung
demandFactorSteigt mit der Anzahl der Käufe in der letzten Stunde. Bei 500+ Käufen: +35% (DemandWeight)
randomFactorZufällige Schwankung ±RandomRange% — bewegt Preise auch ohne Käufe
smoothStepVerhindert abrupte Preissprünge — max. MaxStepPercent Änderung pro Update
Scope: globalAlle Shops teilen denselben Preis für ein Item
Scope: shopJeder Shop berechnet seinen eigenen Preis unabhängig
Setze NebulaCore.Debug = false im Produktionsbetrieb. Im Debug-Modus wird jedes Preis-Update in der Serverkonsole ausgegeben.
API

Exports & API

nebula_core stellt Exports bereit, über die andere Ressourcen auf die Datenbank und Preis-Engine zugreifen können.

Lua — nebula_core exports
-- Get current price of an item
local price = exports['nebula_core']:getPrice('bread', shopId)

-- Ensure/create a shop (returns shopId)
local shopId = exports['nebula_core']:dbEnsureShop({ name = 'My Shop', ... })

-- Register/update an item in the database
exports['nebula_core']:dbUpsertItem({ name = 'bread', label = 'Bread', base_price = 50, ... })

-- Assign item to a shop
exports['nebula_core']:dbUpsertShopItem(shopId, 'bread', { stock_mode = 'infinite' })

-- Get all items of a shop
local items = exports['nebula_core']:dbGetShopItems(shopId)

-- Calculate price via pricing engine
local price = exports['nebula_core']:pricingGetPrice('bread', shopId)
Support

FAQ

Welches Framework wird unterstützt?
Das Script erkennt automatisch: ESX, QBCore und ox_core. Ebenso wird das Inventory automatisch erkannt. Es muss nichts manuell konfiguriert werden.
Script startet nicht — was tun?
1. Prüfe ob oxmysql VOR nebula_core startet. 2. Prüfe ob dein Framework läuft. 3. Aktiviere NebulaCore.Debug = true für mehr Konsolenausgaben. 4. Stelle sicher dass die Reihenfolge in server.cfg korrekt ist.
Shop erscheint nicht ingame
Prüfe die Konsolenausgabe auf [NebulaShop] Config sync complete. Der key muss absolut einmalig sein. Mit ns_resync_shops in der Serverkonsole kann die Sync erzwungen werden.
Preise ändern sich nicht
Stelle sicher dass NebulaCore.Price.Enabled = true gesetzt ist. Updates passieren alle UpdateIntervalSeconds Sekunden (Standard: 60s). Mit Debug = true siehst du jeden Update in der Konsole.
Discord Logging einrichten
In nebula_core/config.lua unter NebulaCore.Logging.DiscordWebhook die Webhook-URL eintragen. Discord → Kanal-Einstellungen → Integrationen → Webhook erstellen → URL kopieren.
Wie füge ich einen neuen Shop hinzu?
Neuen Shop-Block in nebula_shop/config.lua unter NebulaShop.Shops eintragen. Einzigartigen key vergeben, coords und items setzen. Dann ns_resync_shops in der Serverkonsole ausführen.
Wie erreiche ich den Support?
Discord beitreten und im #support Channel ein Ticket öffnen. Problem detailliert beschreiben und Screenshot der Fehlermeldung beifügen.