feat: chef commands moved to admin + PlaceholderAPI integration

Chef → admin: the chef role no longer grants any command privilege.
All team-management subcommands now take <team> as an argument and are
gated by their crcore.team.<action> permission only:
- add <team> <player>
- remove <team> <player>
- transfer <team> <player>
- visibility <team> <PUBLIC|PRIVATE>
- setspawn <team> (still player-only — needs admin's location)

The LEADER role is kept in the data model (Team / TeamMember) and remains
usable by game plugins via the API, but does not unlock any default
command. Future work can re-introduce chef-specific commands if needed.

PlaceholderAPI: auto-detected at CRCore.enable(). If the PAPI plugin is
present on the server, CRCorePlaceholderExpansion registers automatically;
otherwise the lib runs without it (no NoClassDefFoundError thanks to the
indirection through doRegisterPlaceholderHook).

Placeholders exposed:
- Team: %crcore_team%, %crcore_team_name/tag/color/color_chat/size/
  visibility/leader_name/total_score%, %crcore_team_score_<name>%
- Player: %crcore_player_score_<name>%, %crcore_player_score_total%

Dependency: me.clip:placeholderapi:2.11.6, scope provided. New repo:
https://repo.extendedclip.com/content/repositories/placeholderapi/.

docs/features.md, decisions.md and the builtin-commands diagram updated to
reflect the simpler admin/player two-tier model and the PAPI section.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Antone Barbaud
2026-06-09 15:05:02 +02:00
parent 002fefdc02
commit 8b7cad3fce
12 changed files with 376 additions and 108 deletions
+73 -15
View File
@@ -335,8 +335,14 @@ Voir [setup.md](setup.md#utilisation-depuis-un-plugin-de-jeu).
sous-classe ou via `replaceSubCommand`.
**Pas d'aliases courts** : les commandes ont leur nom long uniquement
(`/core team create` et pas `/core team c`). Les aliases ont été retirés
pour réduire la friction de découverte et la confusion.
(`/core team create` et pas `/core team c`).
**Modèle simplifié à 2 rôles** : toutes les opérations de gestion d'équipe
sont **admin** (perm requise + team passée en argument). Les opérations
joueur (`join`, `leave`, `info`, `list`, `top`) sont gated par permission
mais ne nécessitent pas le rôle chef. Le rôle `LEADER` reste présent dans
le modèle de données (utilisable par les game plugins via l'API) mais
n'accorde aucun privilège de commande pour l'instant.
### Arborescence
@@ -347,12 +353,12 @@ pour réduire la friction de découverte et la confusion.
├── delete <team> [admin] dissoudre une équipe
├── setleader <team> <player> [admin] (re)assigner le chef
├── score <team> <name> <add|set> <value> [admin] modifier un score
├── add <player> [chef] ajouter à son équipe
├── remove <player> [chef] retirer de son équipe
├── transfer <player> [chef] transférer leadership
├── visibility <PUBLIC|PRIVATE> [chef] changer visibilité
├── setspawn [chef] définir le spawn
├── join <team> [joueur] rejoindre PUBLIC
├── add <team> <player> [admin] ajouter un joueur
├── remove <team> <player> [admin] retirer un joueur
├── transfer <team> <player> [admin] transfert chef→membre existant
├── visibility <team> <PUBLIC|PRIVATE> [admin] changer visibilité
├── setspawn <team> [admin] spawn à la position de l'admin
├── join <team> [joueur] rejoindre une PUBLIC
├── leave [joueur] quitter son équipe
├── info [team] [joueur] infos
├── list [joueur] toutes les équipes
@@ -361,13 +367,12 @@ pour réduire la friction de découverte et la confusion.
### Permissions
Chaque sous-commande a une permission `crcore.team.<action>`. Modèle à 3 niveaux :
Chaque sous-commande a une permission `crcore.team.<action>` :
| Niveau | Commandes | Comportement |
|---|---|---|
| **Admin** | `create`, `delete`, `setleader`, `score` | Permission seule (pas de check chef). Cible une team via argument. |
| **Chef** | `add`, `remove`, `transfer`, `visibility`, `setspawn` | Permission **ET** check chef de sa propre équipe en plus. Cible la team de l'exécutant. |
| **Joueur** | `join`, `leave`, `info`, `list`, `top` | Permission seule (à granter par défaut côté LuckPerms si on veut que tout le monde y ait accès). |
| Niveau | Commandes |
|---|---|
| **Admin** | `create`, `delete`, `setleader`, `score`, `add`, `remove`, `transfer`, `visibility`, `setspawn` |
| **Joueur** | `join`, `leave`, `info`, `list`, `top` |
| Sous-commande | Permission |
|---|---|
@@ -512,7 +517,60 @@ db.table("my_kills")
---
## 7. Bootstrap `CRCore`
## 7. Intégration PlaceholderAPI (optionnelle)
**Statut** : implémentée. Auto-détectée par `CRCore.enable()` — si le plugin
**PlaceholderAPI** est installé sur le serveur, les placeholders `%crcore_*%`
sont enregistrés automatiquement. Si PAPI est absent, la lib reste
fonctionnelle, juste sans placeholders.
### Placeholders Team
Renvoient vides si le joueur n'est dans aucune équipe.
| Placeholder | Renvoie | Exemple |
|---|---|---|
| `%crcore_team%` | récap formaté coloré | `§c[#WOLF] Wolves` |
| `%crcore_team_name%` | nom de l'équipe | `Wolves` |
| `%crcore_team_tag%` | tag court | `WOLF` |
| `%crcore_team_color%` | nom de la couleur | `Red` |
| `%crcore_team_color_chat%` | code couleur ChatColor | `§c` |
| `%crcore_team_size%` | nombre de membres | `5` |
| `%crcore_team_visibility%` | `PUBLIC` ou `PRIVATE` | `PRIVATE` |
| `%crcore_team_leader_name%` | nom du chef (vide si leaderless) | `Alice` |
| `%crcore_team_total_score%` | somme des scores de l'équipe | `42` |
| `%crcore_team_score_<name>%` | score nommé de l'équipe | `%crcore_team_score_kills%``12` |
### Placeholders Player
| Placeholder | Renvoie |
|---|---|
| `%crcore_player_score_<name>%` | score nommé du joueur (0 si pas set) |
| `%crcore_player_score_total%` | somme de tous les scores du joueur |
### Usage côté plugin de jeu / config
Pas d'action à faire côté plugin de jeu — la hook s'enregistre toute seule.
Les placeholders sont disponibles partout où PAPI les résout (scoreboard,
tablist, chat, hologrammes via DecentHolograms, etc.) :
```yaml
# Exemple de scoreboard config (FeatherBoard / Scoreboard plugin)
lines:
- "&aÉquipe : %crcore_team%"
- "&aChef : %crcore_team_leader_name%"
- "&aKills : %crcore_player_score_kills% (total équipe %crcore_team_score_kills%)"
```
### Override
`CRCore.registerPlaceholderHook()` est `protected`. Override dans une
sous-classe de `CRCore` pour ajouter ses propres placeholders ou désactiver
la hook.
---
## 8. Bootstrap `CRCore`
**Statut** : implémenté. Point d'entrée unique pour les plugins de jeu.