# Jobs

Jobs verwandeln Minecraft-Aktionen (abbauen, töten, angeln, craften, brauen, verzaubern, züchten ...) in Einkommen: Geld, Job-XP und eine eigene Punkte-Währung. Spieler leveln, schalten Titel, Belohnungen, Tagesquests und einen Job-Shop frei. Aller Fortschritt bleibt über Neustarts erhalten.

**Dateien:** `modules/jobs.yml` (Hauptconfig) und `modules/jobs/<jobId>.yml` (eine Datei pro Job, beim ersten Start mit 10 fertigen Jobs befüllt; eigene Änderungen werden bei Updates nie überschrieben, nur fehlende Schlüssel ergänzt).

## Commands

Alle `/jobs`-Unterbefehle brauchen `jobs.use` (Default true) plus die genannte Permission (alle Default true).

| Command | Syntax | Permission | Beschreibung |
|---|---|---|---|
| Menü | `/jobs` oder `/jobs menu` | `jobs.menu` | Hub-GUI: meine Jobs, Browse, Quests, Shop |
| Durchsuchen | `/jobs browse` | `jobs.browse` | Paginierte Job-Liste mit Fortschritt, Klick = Beitritt |
| Info | `/jobs info <job>` | `jobs.info` | Alle Aktionen, Ziele, Belohnungen, Titel eines Jobs |
| Beitreten | `/jobs join <job>` | `jobs.join` + `jobs.join.<job>` | Prüft Max-Jobs-Limit und Cooldown |
| Verlassen | `/jobs leave <job>` / `leaveall` | `jobs.leave` | Mit XP-Verlust, falls aktiviert |
| Statistik | `/jobs stats` | `jobs.stats` | Level/XP/Einnahmen je Job |
| Toplisten | `/jobs top <job>` / `gtop` | `jobs.top` | Top 10 pro Job bzw. global |
| Limit | `/jobs limit` | `jobs.limit` | Verbleibendes Zeitraum-Kontingent |
| Punkte | `/jobs points` | `jobs.points` | Job-Punkte-Stand |
| Quests | `/jobs quests` | `jobs.quests` | Tagesquest-GUI mit Fortschrittsbalken |
| Anzeige | `/jobs toggle [actionbar\|bossbar\|off]` | `jobs.toggle` | Einkommens-Anzeigemodus |
| Boosts | `/jobs boosts` | `jobs.boosts` | Aktive Boosts und Gesamt-Multiplikator |
| Shop | `/jobs shop` | `jobs.shop` | Job-Shop (zahlt mit Punkten) |

> **Tipp:** `jobs.join.<jobId>` wird pro Job automatisch mit Default true registriert. Einzelne Jobs sperrt man per LuckPerms mit `jobs.join.<jobId>: false`; das Browse-Menü prüft dieselbe Permission.

## Admin-Commands (/jobsa)

| Command | Syntax | Permission | Beschreibung |
|---|---|---|---|
| Reload | `/jobsa reload` | `jobs.admin.reload` | Lädt Jobs, Quests, Boosts, Shop neu |
| Status | `/jobsa status` | `jobs.admin.status` | Status der Block-Historien-Provider (Diagnose) |
| Join/Leave | `/jobsa join\|leave\|leaveall <spieler> [job]` | `jobs.admin.manage` | Ohne Limit-Prüfung, ohne XP-Verlust |
| Feuern | `/jobsa fire <spieler> <job>` | `jobs.admin.manage` | Mit garantiertem XP-Verlust |
| Level | `/jobsa promote\|demote <spieler> <job> [level]` | `jobs.admin.manage` | Level rauf/runter, XP wird auf 0 gesetzt |
| XP | `/jobsa grantxp\|removexp <spieler> <job> <menge>` | `jobs.admin.manage` | XP vergeben/entfernen |
| Boosts | `/jobsa boost <job\|all> <money\|xp\|all> <faktor> [dauer]` | `jobs.admin.boost` | Ohne Dauer permanent; `boostremove`, `boostlist` |
| Limits | `/jobsa resetlimit <spieler>` / `resetlimitall` | `jobs.admin.limit` | Zeitraum-Zähler zurücksetzen |
| Punkte | `/jobsa points <spieler> <set\|add\|remove> <menge>` | `jobs.admin.points` | Punktestand verwalten |
| Quest | `/jobsa skipquest <spieler> <job> <index>` | `jobs.admin.quest` | Quest ohne Belohnung abschließen |

## Weitere Permissions

| Permission | Default | Beschreibung |
|---|---|---|
| `jobs.max.<n>` / `jobs.max.unlimited` | `false` | Mehr gleichzeitige Jobs (höchster Wert gilt; unlimited = 50) |
| `jobs.maxlevel.<n>` | `false` | Höheres Max-Level, wenn n über dem Config-Wert liegt |
| `jobs.autojoin.<jobId>` | `false` | Automatischer Beitritt beim Server-Join |
| `jobs.boost.<faktor>` | `false` | Permission-Boost, z. B. `jobs.boost.1.25` (höchster gilt) |
| `jobs.bypass.xploss` | `false` | Kein XP-Verlust beim Verlassen |
| `jobs.bypass.placedblock` / `cropcheck` / `spamkill` / `spawner` / `afk` / `limit` / `dynamicpay` | `false` | Umgeht den jeweiligen Exploit-Schutz |

## Die 10 Standard-Jobs

| Job | Farbe | Haupt-Aktionen |
|---|---|---|
| `miner` | gold | `BREAK` (Erze, Gestein, Obsidian, Amethyst, Sculk, Ancient Debris) |
| `woodcutter` | dark_green | `BREAK` (alle Holz-Varianten), `STRIP_LOG` |
| `farmer` | yellow | `BREAK` (Feldfrüchte), `BREED`, `SHEAR`, `MILK` |
| `hunter` | red | `KILL` (30+ feindliche Mobs bis Enderdrache/Wither) |
| `fisherman` | aqua | `FISH` (Fische und Schatzfunde) |
| `crafter` | light_purple | `CRAFT` (Redstone, Ender-Kiste, Beacon, Shulker-Kiste ...) |
| `enchanter` | dark_purple | `ENCHANT` (Werkzeuge, Rüstung, Bücher, Elytra) |
| `brewer` | dark_aqua | `BREW`, `CRAFT` (Braustand, Kessel, Flaschen) |
| `weaponsmith` | gray | `CRAFT` (Waffen/Rüstung), `REPAIR`, `SMELT` |
| `explorer` | green | `EXPLORE` (distanzbasiert), `TAME`, `KILL` (nur Shulker) |

Jeder Job hat 6 Titel-Stufen (Level 1/10/25/50/75/100) und Level-Up-Belohnungen auf denselben Meilensteinen.

## Aktionsarten

| Aktionsart | Auslöser | Ziel | Schutz/Besonderheit |
|---|---|---|---|
| `BREAK` | Block abbauen | Material | Placed-Block-Check, Crop-Age, AFK-Erkennung |
| `KILL` | Kreatur töten | Kreatur | Spam-Kill-Schutz, Spawner-Reduktion, kein Selbstmord |
| `FISH` | Angeln | gefangenes Material | Zahlt auch Schätze |
| `CRAFT` | Craften | Ergebnis-Material | Shift-Klick zählt die echte Stückzahl |
| `SMELT` | Ofen entnehmen | Material | Zählt die entnommene Menge |
| `BREW` | Trank brauen | Trank-Material | Letzter Braustand-Nutzer = Brauer |
| `ENCHANT` | Verzaubern | Material | - |
| `REPAIR` | Amboss-Reparatur | Material | Beide Slots müssen belegt sein |
| `BREED` / `SHEAR` / `TAME` | Züchten/Scheren/Zähmen | Kreatur | - |
| `MILK` | Melken | Kreatur | Cooldown pro Tier |
| `EXPLORE` | Laufen | `ALL` | Zahlt alle `explore-distance` Blöcke, Teleports zählen nicht |
| `STRIP_LOG` | Holz entrinden | Original-Material | - |

`ALL` ist überall als Wildcard erlaubt. Nexo-/Carpentary-Ziele (`nexo:<id>`) haben Vorrang vor Vanilla-Materialien.

## Leveling und Skalierung

```
xpBenötigt(level)   = base * level + multiplier * level^exponent
effektivesEinkommen = baseMoney * (1 + (level - 1) * level-multiplier)
effektiveXp         = baseXp    * (1 + (level - 1) * level-multiplier * 0.5)
```

Die XP-Skalierung läuft bewusst mit halber Rate, damit hohe Level das Aufsteigen nicht exponentiell beschleunigen. Überschuss-XP geht bei Level-Ups nie verloren (Mehrfach-Aufstiege möglich); am Max-Level wird keine XP mehr gutgeschrieben.

**Pro Job überschreibbar:** Jede Job-Datei kann eine eigene `leveling`-Sektion haben; fehlende Werte (oder `-1`) nutzen die globale Formel. GUI, `/jobs stats` und Web-Interface rechnen automatisch mit der Formel des jeweiligen Jobs.

```yaml
# in modules/jobs/woodcutter.yml: dieser Job levelt langsamer, verdient mehr
leveling:
  xp-formula:
    base: 15.0
    multiplier: 6.0
    exponent: 2.2
  income-formula:
    level-multiplier: 0.05
    xp-level-multiplier: 0.02
```

**Max-Level-Reihenfolge:** Job-eigenes `max-level` (0 = global) → `global-max-level` → Permission `jobs.maxlevel.<n>` (nur wenn höher).

## Auszahlung

Jede Aktion wird für JEDEN aktiven Job abgerechnet, der sie bezahlt (Stacking gewollt): Level-Skalierung und Boosts wirken auf Geld und XP, danach kappen aktive Zeitraum-Limits. **Punkte sind immer roh:** keine Level-Skalierung, keine Boosts, kein Dynamic Pay, keine Limits. Die Anzeige wird gebündelt (`batch-interval`) als Actionbar oder Bossbar ausgegeben.

**Quests:** Pro Job und Tag werden `quests-per-job` Quests aus den echten Aktion/Ziel-Paaren des Jobs generiert. Belohnung = Basiswert × Menge × `reward-multiplier` (ohne Level-Skalierung), wird bei Abschluss sofort automatisch ausgezahlt. Reset täglich zur konfigurierten Uhrzeit.

**Boosts:** Drei Quellen (Admin per `/jobsa boost`, Scheduled nach Uhrzeit/Wochentag, Permission `jobs.boost.<n>`, dort gewinnt der höchste). `stacking-mode: multiply` multipliziert alle, `add` addiert die Bonus-Anteile; Deckel ist `max-multiplier`. Admin-Boosts überleben Reload und Neustart.

## Exploit-Schutz

Selbst platzierte Blöcke zahlen nichts (Historien-Check über CoreProtect), unreife Feldfrüchte zahlen nichts, Spam-Kills am selben Mob stoppen die Zahlung, Spawner-Mobs zahlen nur den konfigurierten Bruchteil, Selbstmord zählt nicht, Shift-Klick-Crafting zählt die echte Menge, Melken hat einen Cooldown pro Tier und Teleports geben keine EXPLORE-Distanz. Bezahlte Abbauten werden optional als `#jobs-<spieler>` in CoreProtect geloggt.

> **Achtung:** Ohne CoreProtect deaktiviert sich das Jobs-Modul standardmäßig selbst (`require-history-provider: true`), sichtbar nur als Log-Warnung. Wer ohne Historien-Quelle spielt, setzt den Schalter bewusst auf false; dann entscheidet `placed-block-failure` (deny = sicher, allow = zahlt trotzdem). Die AFK-Erkennung greift nur bei `BREAK`.

## Konfiguration (modules/jobs.yml)

```yaml
# Schaltet das Jobs-Modul ein oder aus.
enabled: true

jobs:
  # Gleichzeitige Jobs pro Spieler. Höchste jobs.max.<n>-Permission
  # gewinnt, jobs.max.unlimited = 50.
  max-jobs: 3
  # Spieler mit jobs.autojoin.<jobId> treten beim Join automatisch bei.
  autojoin-enabled: false
  # Level-Deckel für Jobs ohne eigenes max-level.
  global-max-level: 100
  command-cooldowns:
    # Anti-Spam für /jobs join und leave, Sekunden.
    join: 3
    leave: 3
  chat-title:
    # Job-Titel vor dem Chat-Namen (nach dem Team-Prefix).
    # highest = Job mit höchstem Level, first = alphabetisch erster.
    enabled: false
    mode: highest
    format: "<job_color>[<job_title>] "
  actions:
    # Blöcke pro EXPLORE-Zahlung.
    explore-distance: 100.0
    # Sekunden zwischen bezahlten Melk-Aktionen pro Tier.
    milk-cooldown: 5
  xp-loss:
    # XP-Verlust beim freiwilligen Verlassen. /jobsa fire wendet ihn
    # immer an, jobs.bypass.xploss verhindert ihn.
    enabled: true
    percentage: 0.3
  leveling:
    xp-formula:
      # Benötigte XP = base * level + multiplier * level^exponent.
      base: 10.0
      multiplier: 4.0
      exponent: 2.0
    income-formula:
      # +3% Einkommen pro Level; XP skaliert mit halber Rate.
      level-multiplier: 0.03
    level-up:
      chat-enabled: true
      title-enabled: true
      sound-enabled: true
      sound: "entity.player.levelup"
      sound-volume: 1.0
      sound-pitch: 1.0
      title-fade-in: 10
      title-stay: 40
      title-fade-out: 20
    broadcast:
      # Level-Ups ab min-level serverweit melden.
      enabled: false
      min-level: 10
  limits:
    # Rollierendes Zeitfenster mit Geld-/XP-Obergrenze pro Spieler.
    enabled: false
    max-earnings: 10000.0
    max-xp: 50000.0
    period-duration: 3600
  income-display:
    # Ticks zwischen gebündelten Anzeigen bzw. Bossbar-Dauer.
    batch-interval: 40
    bossbar-duration: 60
  boosts:
    # multiply = Boosts multiplizieren sich, add = Boni addieren sich.
    stacking-mode: multiply
    max-multiplier: 10.0
    scheduled:
      weekday-dawn:
        job: farmer
        category: all
        multiplier: 1.25
        start: "05:00"
        end: "08:00"
        days: [MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY]
  quests:
    enabled: true
    quests-per-job: 4
    min-amount: 12
    max-amount: 160
    reward-multiplier:
      money: 2.2
      xp: 2.1
      points: 1.7
    # Täglicher Reset (löscht alle Quest-Daten und generiert neu).
    reset-hour: 0
    reset-minute: 0
    creative-style:
      # Flavor-Namen mit <target>-Platzhalter, pro Job oder default.
      enabled: true
      templates:
        default:
          - "Guild contract: <target>"
          - "Rush order: <target>"
        miner:
          - "Crystal vein: <target>"
  dynamic-pay:
    # Angebots-/Nachfrage-Anpassung nach Aktions-Häufigkeit.
    enabled: false
    sensitivity: 0.5
    min-multiplier: 0.5
    max-multiplier: 1.5
  integrations:
    coreprotect:
      # Loggt bezahlte Abbauten als #jobs-<spieler>.
      jobs-tracking: true
      # Zeitfenster der Block-Historie für den Placed-Block-Check.
      lookup-time-seconds: 2592000
    nexo:
      jobs-enabled: true
    carpentary:
      jobs-enabled: true
    betterhud:
      job-info:
        enabled: true
        popup-name: ""
        popup-duration: 60
  shop:
    # Items kosten Job-Punkte; required-job/-level begrenzen den Kauf.
    enabled: true
    title: "<gold>Job Shop"
    items:
      miner_lantern_kit:
        material: TORCH
        amount: 64
        display-name: "<gold>Miner Lantern Kit"
        lore:
          - "<gray>Cheap light for long tunnels."
        cost: 35.0
        required-job: miner
        required-level: 3
  exploit-protection:
    placed-block-check: true
    # true = ohne Historien-Quelle (CoreProtect) deaktiviert sich das
    # Modul selbst.
    require-history-provider: true
    # auto, coreprotect, debug oder disabled.
    placed-block-provider: auto
    # Ohne eindeutige Antwort: deny = nicht zahlen (sicher), allow = zahlen.
    placed-block-failure: deny
    crop-age-check: true
    spam-kill:
      enabled: true
      window: 30
      max-kills: 5
    spawner-mobs:
      enabled: true
      money-multiplier: 0.0
      xp-multiplier: 0.0
    afk-detection:
      # Mehr als action-threshold Aktionen in radius Blöcken innerhalb
      # von window Sekunden: Zahlung wird mit multiplier reduziert.
      enabled: false
      radius: 5
      action-threshold: 50
      window: 120
      multiplier: 0.0
```

## Eigene Jobs (modules/jobs/<jobId>.yml)

```yaml
# name ist Pflicht, sonst wird die Datei verworfen. Ungültige Ziele oder
# negative Werte werden übersprungen und geloggt. Nach Änderungen:
# /jobsa reload. Limits: 500 Aktionen, 100 Titel, 200 Belohnungs-Stufen.
name: "Miner"
color: "gold"
short-name: "MIN"
icon: "IRON_PICKAXE"
description: "Mine ores and stones for profit"
# 0 = global-max-level nutzen.
max-level: 0

actions:
  # BREAK/CRAFT/SMELT/STRIP_LOG/FISH/ENCHANT/REPAIR erwarten Materialien,
  # KILL/BREED/SHEAR/TAME/MILK Kreaturen, ALL ist überall erlaubt.
  BREAK:
    DIAMOND_ORE:
      money: 4.0
      xp: 8.0
      points: 0.4
    ANCIENT_DEBRIS:
      money: 10.0
      xp: 20.0
      points: 1.0

titles:
  "1": "Apprentice Miner"
  "25": "Expert Miner"
  "100": "Mythic Deep Delver"

level-up-rewards:
  # Konsolen-Befehle mit {player}, {job}, {jobname}. Befehle mit
  # unerlaubten Zeichen werden verworfen und geloggt.
  "25":
    - "give {player} diamond 3"
  "100":
    - "give {player} netherite_upgrade_smithing_template 1"
```
