# SpaceShipProject

Plugin Paper / Spigot **1.21+** qui permet à chaque joueur d'avoir un (ou plusieurs) spaceship personnel.
Le vaisseau est chargé directement dans le ciel de la map actuelle ; il sert d'île volante privée que le
joueur peut décorer, fortifier puis ranger dans une "télécommande" en forme de **Recovery Compass**.

> Inspiré du fonctionnement des îles de Skyllia, mais sans monde dédié : tout reste sur la map du joueur,
> en plein ciel.

---

## Sommaire

- [Fonctionnalités](#fonctionnalités)
- [Pré-requis](#pré-requis)
- [Installation](#installation)
- [Compilation](#compilation)
- [Configuration](#configuration)
- [Utilisation](#utilisation)
  - [Télécommande (Recovery Compass)](#télécommande-recovery-compass)
  - [GUI principal](#gui-principal)
  - [Saut Spatial](#saut-spatial)
- [Commandes joueur (`/spaceship`, `/ss`, `/ship`)](#commandes-joueur-spaceship-ss-ship)
- [Commandes admin (`/spaceshipadmin`, `/ssa`)](#commandes-admin-spaceshipadmin-ssa)
- [Économie (Vault / EssentialsEconomy)](#économie-vault--essentialseconomy)
- [Système de niveaux et de tailles](#système-de-niveaux-et-de-tailles)
- [Stockage et base de données](#stockage-et-base-de-données)
- [Modèles de spaceship](#modèles-de-spaceship)
- [Permissions](#permissions)
- [FAQ](#faq)

---

## Fonctionnalités

- Spaceships personnels matérialisés en plein ciel **sur la même map** que le joueur.
- Télécommande **Recovery Compass** par spaceship (clic gauche / droit / shift+droit).
- **Système de niveaux** : chaque level-up agrandit physiquement le vaisseau (x/z en alternance,
  +1 y tous les 4 niveaux). Les nouvelles limites sont indiquées par des **Verdant Froglight**
  aux 8 coins au premier chargement après l'upgrade.
- **Saut spatial** : déplacement instantané du spaceship le long d'un axe, avec un coût en money
  proportionnel à la distance.
- **Sauvegarde complète** : chaque dépose stocke les blocs **et le contenu des coffres / barils /
  fournaises / shulker boxes / etc.** dans la base de données.
- **Protection** : seul le propriétaire (ou un admin) peut casser/poser des blocs dans un
  spaceship chargé. Les autres joueurs sont les bienvenus comme passagers.
- **Vault / EssentialsEconomy** : tous les coûts (invocation, upgrade, saut spatial) sont payés
  via Vault. Aucun système monétaire interne — le solde du joueur est la source unique.
- **Auto-déchargement à la déconnexion** : tous les spaceships du joueur sont sauvegardés et
  retirés du monde quand il se déconnecte.
- **Respawn sur le vaisseau** : si le joueur meurt sur un de ses spaceships chargés, il y respawn.
- **Modèles éditables** : un admin peut définir un plan par défaut (chargé en jeu, édité comme
  des blocs normaux puis sauvegardé) qui sert de base à chaque nouveau spaceship.
- **GUI** complet pour gérer le ship : charger/décharger, téléport, set spawn, renommer, upgrade,
  supprimer, saut spatial.

---

## Pré-requis

- **Java 21+**
- **Paper / Purpur / Folia (compat partielle) 1.21.x**
- **Vault** (obligatoire pour l'économie)
- Un fournisseur d'économie compatible Vault (recommandé : **EssentialsEconomy** via EssentialsX)

> Sans Vault, le plugin charge mais désactive toutes les actions payantes.

---

## Installation

1. Copier `SpaceShipProject-1.0-SNAPSHOT.jar` dans le dossier `plugins/` du serveur.
2. S'assurer que `Vault` (+ un provider, ex. EssentialsX/EssentialsEconomy) est présent.
3. Démarrer le serveur. Le dossier `plugins/SpaceShipProject/` sera créé avec `config.yml`,
   `models/` et `spaceships.db`.

---

## Compilation

Depuis la racine du dépôt `mcplugin/` :

```bash
./build.sh SpaceShipProject
```

Le JAR final est dans `SpaceShipProject/target/SpaceShipProject-1.0-SNAPSHOT.jar`.

Pré-requis : Maven 3.6+, JDK 21. Le script gère automatiquement `JAVA_HOME` sur Arch Linux.

---

## Configuration

Fichier `plugins/SpaceShipProject/config.yml` :

```yaml
max-ships-per-player: 5

default-size:    # taille initiale (level 1)
  x: 4
  y: 4
  z: 6

max-size:        # plafond atteignable
  x: 16
  y: 8
  z: 16

costs:
  summon: 100         # cout pour charger un spaceship
  unload: 0           # cout pour decharger
  upgrade-base: 1000  # cout d'amelioration = upgrade-base * niveau actuel
  space-jump-per-block: 1

space-jump:
  blocks-per-level: 100   # distance max = blocks-per-level * niveau
  min-blocks: 1
  max-blocks-hard-cap: 5000

summon-offset-y: 30      # hauteur du ship au-dessus du joueur a l'invocation

default-platform-material: SMOOTH_QUARTZ
default-edge-material: QUARTZ_PILLAR
default-glass-material: WHITE_STAINED_GLASS

default-ship-name: "Spaceship #%n%"

safety:
  check-collision: true
  min-y-above-player: 10

messages:
  prefix: "&8[&bSpaceShip&8] &7"
  # ... (voir le fichier complet)
```

Toutes les clés peuvent être modifiées à chaud via :

```
/ssa setconfig <chemin> <valeur>
/ssa getconfig <chemin>
/ssa reload
```

---

## Utilisation

### Télécommande (Recovery Compass)

Chaque spaceship a sa propre télécommande. L'item est un **Recovery Compass** marqué par PDC.
La lore montre l'ID, le nom, le niveau et la taille du ship.

| Action sur la télécommande | Effet |
|---|---|
| **Clic gauche** (au sol, ship non chargé) | Invoque le spaceship au-dessus du joueur (coût : `costs.summon`) |
| **Clic gauche** (au sol, ship chargé)     | Décharge le ship et sauvegarde toutes les modifications |
| **Clic gauche** (sur le ship)             | Refuse (utiliser clic droit pour redescendre d'abord) |
| **Clic droit** (au sol, ship non chargé)  | Invoque puis téléporte directement sur le ship |
| **Clic droit** (au sol, ship chargé)      | Téléporte sur le spawn du ship |
| **Clic droit** (sur le ship)              | Redescend au sol, à la position initiale |
| **Shift + clic droit**                    | Ouvre le GUI de paramètres |

### GUI principal

Ouvert via **shift + clic droit** sur la télécommande. 36 slots :

```
. . . .  I  . . . .       I = info (niveau, taille, statut, solde Vault)
. . . .  .  . . . .
. T E . S .  . . .        T = toggle charge/decharge
                          E = teleport up/down
                          S = set spawn (sur le ship)
                          J = Saut Spatial (sur le ship)
                          U = Ameliorer (level-up)
. . . .  R  . . . D       R = renommer (par chat)
                          D = supprimer (shift-clic pour confirmer)
```

### Saut Spatial

Disponible **uniquement quand le joueur est sur son spaceship**.

1. Ouvrir le GUI principal, cliquer sur **Saut Spatial**.
2. Choisir un axe : `X-`, `X+`, `Y-`, `Y+`, `Z-`, `Z+`.
3. Ajuster la distance avec les boutons (`-50 -10 -1 / +1 +10 +50`, shift = ×10).
4. Confirmer.

- Distance max = `space-jump.blocks-per-level × niveau` (par défaut 100 / niveau).
- Coût = `costs.space-jump-per-block × distance` (par défaut 1 money / bloc).
- Le ship est capturé, déchargé à l'ancienne position, rechargé à la nouvelle, et le joueur est
  téléporté sur son spawn.

---

## Commandes joueur (`/spaceship`, `/ss`, `/ship`)

| Commande | Description | Permission |
|---|---|---|
| `/ss help` | Aide | `spaceship.use` |
| `/ss create` | Crée un nouveau spaceship + donne sa télécommande | `spaceship.create` |
| `/ss give <joueur> <id>` | Redonne la télécommande perdue à un joueur (no-op si déjà présente, dédoublonne) | `spaceship.give` |
| `/ss remote <id>` | Redonne sa propre télécommande | `spaceship.give` |
| `/ss list [joueur]` | Liste compacte des ships | `spaceship.use` |
| `/ss info [joueur]` | Infos détaillées (niveau, taille actuelle/suivante, saut max, etc.) | `spaceship.use` / `spaceship.info.other` |
| `/ss delete <id>` | Supprime un ship et retire sa télécommande de l'inventaire | `spaceship.delete` |
| `/ss reload` | Recharge la config | `spaceship.reload` |

---

## Commandes admin (`/spaceshipadmin`, `/ssa`)

| Commande | Description |
|---|---|
| `/ssa reload` | Recharge config + modèles |
| `/ssa list [joueur]` | Liste tous les ships, ou ceux d'un joueur, ou les ships actuellement chargés |
| `/ssa delete <id>` | Supprime n'importe quel ship |
| `/ssa addmoney <joueur> <montant>` | Dépose de la money via Vault sur le solde du joueur |
| `/ssa setlevel <joueur> <id> <level>` | Force le niveau d'un ship (la taille s'ajuste au prochain chargement) |
| `/ssa setname <joueur> <id> <nom...>` | Renomme un ship |
| `/ssa setconfig <chemin> <valeur>` | Modifie une clé du `config.yml` (auto-reload) |
| `/ssa getconfig <chemin>` | Lit une clé |
| `/ssa loadmodel [nom]` | Matérialise un modèle dans le ciel pour l'éditer (par défaut `default`) |
| `/ssa savemodel` | Capture la session en cours et l'écrit dans `models/<nom>.json` |
| `/ssa cancelmodel` | Annule la session et nettoie la zone |

Toutes ces commandes requièrent `spaceship.admin`.

---

## Économie (Vault / EssentialsEconomy)

Le plugin n'a **aucune** monnaie interne. Tout passe par **Vault** :

- Charger un spaceship → débite `costs.summon` au propriétaire.
- Améliorer un spaceship → débite `costs.upgrade-base × niveau actuel`.
- Saut spatial → débite `distance × costs.space-jump-per-block`.

La permission `spaceship.bypass.cost` permet de tester sans payer (par défaut OP).

Si Vault est absent / sans provider, le plugin log un warning et toutes les actions payantes
sont bloquées (`Vault indisponible`).

---

## Système de niveaux et de tailles

Au niveau 1, la taille est celle de `default-size` (par défaut **4 × 4 × 6**, x/y/z).
Chaque niveau gagné applique :

- **+1 sur X** (level-ups impairs : L1→L2, L3→L4, ...)
- **+1 sur Z** (level-ups pairs : L2→L3, L4→L5, ...)
- **+1 sur Y** tous les **4 level-ups** (L4→L5, L8→L9, ...)

…jusqu'au plafond `max-size` (par défaut **16 × 8 × 16**, atteint vers le niveau 27).

| Level | Taille (x,y,z) |
|------|----------------|
| 1    | 4 × 4 × 6 |
| 2    | 5 × 4 × 6 |
| 3    | 5 × 4 × 7 |
| 4    | 6 × 4 × 7 |
| 5    | 6 × 5 × 8 |
| ...  | ... |
| 27+  | 16 × 8 × 16 |

Quand un ship est chargé pour la première fois après un upgrade, les nouvelles limites sont
matérialisées par des blocs **Verdant Froglight** aux 8 coins. Le joueur peut ensuite les
casser et décorer ses nouveaux murs librement — au prochain chargement, ces froglights ne
réapparaissent pas (sauf nouvel upgrade).

---

## Stockage et base de données

SQLite local : `plugins/SpaceShipProject/spaceships.db`.

Trois tables :

```sql
players(
    uuid TEXT PRIMARY KEY, name TEXT, settings TEXT,
    created_at TIMESTAMP, updated_at TIMESTAMP
)

spaceships(
    id INTEGER PK,
    owner_uuid TEXT,
    name TEXT,
    size_x, size_y, size_z INTEGER,
    spawn_x, spawn_y, spawn_z INTEGER,
    schematic TEXT,             -- JSON (palette + RLE + containers)
    settings TEXT,              -- JSON libre
    level INTEGER DEFAULT 1,
    money INTEGER DEFAULT 0,    -- obsolète (Vault), conservé pour migration
    last_loaded_level INTEGER,  -- pour le marquage Verdant Froglight
    created_at TIMESTAMP, updated_at TIMESTAMP
)

spaceships_loaded(
    spaceship_id INTEGER PK,
    world TEXT,
    origin_x, origin_y, origin_z INTEGER,
    loaded_at TIMESTAMP
)
```

Le champ `schematic` est un JSON :

```json
{
  "size": [sx, sy, sz],
  "spawn": [ox, oy, oz],
  "palette": ["minecraft:air", "minecraft:smooth_quartz", ...],
  "blocks": [[paletteIdx, runLength], ...],
  "containers": [
    {"x":1,"y":2,"z":3,"items":[{"slot":0,"data":"base64..."}, ...]}
  ]
}
```

Les `items` sont sérialisés via `ItemStack#serializeAsBytes()` : enchantements, NBT, custom
data, etc. sont entièrement préservés.

---

## Modèles de spaceship

Stockés dans `plugins/SpaceShipProject/models/<name>.json` (format identique au champ
`schematic`).

Workflow admin :

```text
/ssa loadmodel           # place le modele actuel devant l'admin (sinon genere une plateforme)
# ... edite librement les blocs (admin = bypass de protection) ...
/ssa savemodel           # capture la zone -> models/default.json, nettoie le ciel
```

Le prochain `/ss create` utilisera ce nouveau plan comme base. On peut créer plusieurs modèles
nommés (`/ssa loadmodel arena`, etc.).

Si `models/default.json` n'existe pas, le plugin génère une plateforme procédurale (sol +
piliers aux coins, vitres latérales).

---

## Permissions

```yaml
spaceship.use:            true   # base : utiliser sa propre boussole
spaceship.create:         true   # /ss create
spaceship.give:           true   # /ss give (sa propre télécommande)
spaceship.info.other:     op     # /ss info <autre joueur>
spaceship.delete:         true   # supprimer un de ses ships
spaceship.reload:         op
spaceship.admin:          op     # bypass de propriété + accès à /ssa
spaceship.bypass.cost:    op     # ne paie pas summon / upgrade / saut
```

---

## FAQ

**Que se passe-t-il si je me déconnecte alors que mon ship est chargé ?**
Le plugin capture l'état complet (y compris coffres) et décharge le ship. Vous êtes téléporté
au sol au préalable pour ne pas réapparaître en plein vol à la reconnexion.

**Et si je meurs sur mon ship ?**
Vous respawnez directement sur le spawn du ship si celui-ci est encore chargé. Sinon, respawn
normal.

**Le ship peut-il chevaucher des constructions du joueur ?**
Non : le plugin vérifie qu'aucun bloc solide n'occupe la zone avant l'invocation
(`safety.check-collision`). Si oui, l'invocation échoue avec un message d'erreur.

**Puis-je inviter d'autres joueurs sur mon ship ?**
Oui — ils peuvent y monter (téléport-relay si tu leur indiques la position). Cependant, ils ne
peuvent **pas modifier les blocs** : seuls le propriétaire et les admins peuvent casser/poser.

**Comment réinitialiser un ship à zéro ?**
Le supprimer (`/ss delete <id>`) puis en recréer un (`/ss create`). La télécommande de l'ancien
est retirée automatiquement.

**Que se passe-t-il quand le ship atteint la taille maximale ?**
Le bouton "Améliorer" devient inactif. Vous gardez votre ship à taille max.

---

## License

Plugin développé pour un usage privé. Pas de licence formelle, à utiliser librement.
