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:
@@ -367,6 +367,52 @@ Format léger : une décision = un titre + contexte + choix + raison.
|
||||
bases existantes, ALTER TABLE manuel ou suppression du fichier
|
||||
(les bases d'event sont jetables).
|
||||
|
||||
## 2026-06-09 — Toutes les commandes "chef" deviennent admin (révision)
|
||||
|
||||
- **Révision** de la décision "Refonte permissions + modèle admin/chef/joueur"
|
||||
prise plus tôt aujourd'hui.
|
||||
- **Choix** : le rôle chef n'apporte plus aucun privilège de commande pour
|
||||
l'instant. Toutes les opérations de gestion d'équipe (`add`, `remove`,
|
||||
`transfer`, `visibility`, `setspawn`) deviennent **admin** :
|
||||
- Signature avec `<team>` en argument (au lieu d'implicite "ma team").
|
||||
- Permission `crcore.team.<action>` requise.
|
||||
- Plus de check `isLeader(...)` dans `execute()`.
|
||||
- **Raison** : le user a explicitement décidé que pour l'instant le chef
|
||||
n'a pas plus de privilèges qu'un joueur lambda côté commandes. Le rôle
|
||||
`LEADER` reste dans le modèle de données (utile pour les game plugins qui
|
||||
pourraient l'exploiter via l'API, ou pour de futures commandes), mais il
|
||||
ne gate plus rien au niveau du framework de commandes.
|
||||
- **Conséquences** :
|
||||
- `TeamRemoveSubCommand` : refuse de retirer le chef (l'admin doit
|
||||
`setleader` d'abord). Pas un check chef, juste une garde de cohérence.
|
||||
- `TeamTransferSubCommand` : devient l'équivalent admin "strict" de
|
||||
`setleader` (membre existant uniquement). Les deux cohabitent ; doc dit
|
||||
quand préférer l'un ou l'autre.
|
||||
- `TeamSetSpawnSubCommand` : reste `playerOnly` car nécessite la
|
||||
`Location` de l'exécutant — mais c'est désormais l'admin qui se place
|
||||
à l'endroit voulu et tape `/core team setspawn <team>`.
|
||||
|
||||
## 2026-06-09 — Intégration PlaceholderAPI (optionnelle, auto-détectée)
|
||||
|
||||
- **Choix** : `CRCore.enable()` détecte la présence du plugin PlaceholderAPI
|
||||
via `pluginManager.getPlugin("PlaceholderAPI")` et enregistre
|
||||
automatiquement `CRCorePlaceholderExpansion` si présent. Aucune action
|
||||
requise côté plugin de jeu.
|
||||
- **Dépendance Maven** : `me.clip:placeholderapi:2.11.6` en scope
|
||||
`provided` (depuis `https://repo.extendedclip.com/...`). Le jar PAPI
|
||||
n'est PAS embarqué — c'est un plugin runtime indépendant.
|
||||
- **Indirection de chargement** : la méthode privée
|
||||
`doRegisterPlaceholderHook()` isole la référence à
|
||||
`CRCorePlaceholderExpansion`. Si PAPI est absent, la méthode n'est jamais
|
||||
appelée et le bytecode référençant `me.clip.placeholderapi.*` n'est pas
|
||||
vérifié → pas de `NoClassDefFoundError`.
|
||||
- **Placeholders exposés** :
|
||||
- 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%`
|
||||
- **Override** : `CRCore.registerPlaceholderHook()` est `protected` — une
|
||||
sous-classe peut ajouter des placeholders ou skipper la hook.
|
||||
|
||||
## 2026-06-09 — Nouvelle commande `/core team setleader`
|
||||
|
||||
- **Choix** : ajout de `TeamSetLeaderSubCommand` (`/core team setleader
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@startuml builtin-commands-diagram
|
||||
title CR-Core — Default /core team commands (admin / chef / joueur)
|
||||
title CR-Core — Default /core team commands (admin / joueur)
|
||||
|
||||
skinparam classAttributeIconSize 0
|
||||
hide empty members
|
||||
@@ -11,16 +11,13 @@ package "fr.luc.crcore.command" {
|
||||
|
||||
package "fr.luc.crcore.command.builtin" {
|
||||
|
||||
class CoreCommand {
|
||||
+ CoreCommand(teamSvc, playerSvc)
|
||||
}
|
||||
class CoreCommand
|
||||
CoreCommand --|> BaseCommand
|
||||
|
||||
package "fr.luc.crcore.command.builtin.team" {
|
||||
|
||||
class TeamGroupSubCommand {
|
||||
+ TeamGroupSubCommand(service)
|
||||
# registerDefaults(): void
|
||||
}
|
||||
TeamGroupSubCommand --|> SubCommand
|
||||
|
||||
@@ -28,7 +25,7 @@ package "fr.luc.crcore.command.builtin" {
|
||||
+ {static} teamByName(service): ArgumentType<Team>
|
||||
}
|
||||
|
||||
' === ADMIN commands (permission seule) ===
|
||||
' ─── ADMIN commands (permission seule, team par argument) ───
|
||||
package "admin" <<Rectangle>> {
|
||||
class TeamCreateSubCommand {
|
||||
perm: crcore.team.create
|
||||
@@ -46,32 +43,30 @@ package "fr.luc.crcore.command.builtin" {
|
||||
perm: crcore.team.score
|
||||
args: <team> <name> <add|set> <value>
|
||||
}
|
||||
}
|
||||
|
||||
' === CHEF commands (permission + check chef) ===
|
||||
package "chef" <<Rectangle>> {
|
||||
class TeamAddSubCommand {
|
||||
perm: crcore.team.add
|
||||
args: <player>
|
||||
args: <team> <player>
|
||||
}
|
||||
class TeamRemoveSubCommand {
|
||||
perm: crcore.team.remove
|
||||
args: <player>
|
||||
args: <team> <player>
|
||||
}
|
||||
class TeamTransferSubCommand {
|
||||
perm: crcore.team.transfer
|
||||
args: <player>
|
||||
args: <team> <player>
|
||||
}
|
||||
class TeamVisibilitySubCommand {
|
||||
perm: crcore.team.visibility
|
||||
args: <vis>
|
||||
args: <team> <vis>
|
||||
}
|
||||
class TeamSetSpawnSubCommand {
|
||||
perm: crcore.team.setspawn
|
||||
args: <team>
|
||||
playerOnly
|
||||
}
|
||||
}
|
||||
|
||||
' === PLAYER commands ===
|
||||
' ─── PLAYER commands ───
|
||||
package "player" <<Rectangle>> {
|
||||
class TeamJoinSubCommand {
|
||||
perm: crcore.team.join
|
||||
@@ -114,6 +109,11 @@ package "fr.luc.crcore.command.builtin" {
|
||||
}
|
||||
|
||||
note bottom of TeamGroupSubCommand
|
||||
Le rôle LEADER reste dans le modèle Team
|
||||
(utilisable par les game plugins via l'API)
|
||||
mais n'accorde aucun privilège de commande
|
||||
dans le set par défaut.
|
||||
|
||||
Override d'une feuille :
|
||||
core.getCoreCommand()
|
||||
.findSubCommand("team")
|
||||
|
||||
+73
-15
@@ -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.
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
- **Type** : librairie Java (`jar`) — pas un plugin Bukkit
|
||||
- **artifactId Maven** : `CR-Core`
|
||||
- **Build** : Maven, Java 11
|
||||
- **Intégrations optionnelles** : PlaceholderAPI (auto-détectée si installée)
|
||||
- **API serveur (provided)** : Paper 1.16.5
|
||||
- **SQLite (compile)** : `org.xerial:sqlite-jdbc:3.45.3.0`
|
||||
- **Package racine** : `fr.luc.crcore`
|
||||
|
||||
Reference in New Issue
Block a user