feat: admin/chef/player permission model + leaderless teams + setleader
Commands: - Drop all short aliases (c/i/t/j/vis/disband/...) — long names only. - Every /core team <action> now has a crcore.team.<action> permission. - Three-tier model: * Admin (perm only): create, delete, setleader, score * Chef (perm + chef-check in execute): add, remove, transfer, visibility, setspawn * Player (perm): join, leave, info, list, top - delete now takes <team> as argument (admin); no more chef-disband shortcut. New /core team setleader <team> <player>: - Admin assigns or replaces a team's leader. - More permissive than transfer: target may not yet be a member (auto-add), and works on leaderless teams. Leaderless teams: - Team.leaderId is now nullable. - getLeaderId() and getLeader() return Optional<...>. - hasLeader() and isLeader(UUID) helpers added. - New constructors Team(id, name, tag, color [, visibility]) for leaderless. - TeamService.createTeam overloads without leaderId. - TeamService.setLeader(teamId, playerId): assigns/replaces leader (auto-adds as member if needed). Fires TeamLeadershipTransferEvent with optional old. - TeamLeadershipTransferEvent.getOldLeaderId() returns Optional<UUID>. - SqliteTeamRepository: leader_id column no longer NOT NULL. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -323,6 +323,66 @@ Format léger : une décision = un titre + contexte + choix + raison.
|
||||
même fichier SQLite (par défaut `<dataFolder>/crcore.db`) ; le préfixe
|
||||
isole proprement.
|
||||
|
||||
## 2026-06-09 — Refonte permissions + modèle admin/chef/joueur
|
||||
|
||||
- **Choix** : chaque sous-commande `/core team <action>` a sa propre permission
|
||||
`crcore.team.<action>`. Trois niveaux fonctionnels :
|
||||
- **Admin** (permission seule, cible une team par argument) : `create`,
|
||||
`delete`, `setleader`, `score`.
|
||||
- **Chef** (permission + check chef dans `execute()`) : `add`, `remove`,
|
||||
`transfer`, `visibility`, `setspawn`.
|
||||
- **Joueur** (permission seule, défaut « tout le monde » côté LuckPerms si
|
||||
voulu) : `join`, `leave`, `info`, `list`, `top`.
|
||||
- **Aliases courts supprimés** : `c` (create), `i` (info), `t` (team), `j`
|
||||
(join), `vis` (visibility), `disband`/`dissolve` (delete), `kick`/`expel`
|
||||
(remove), etc. Plus que les noms longs. Raison : réduire la friction
|
||||
d'apprentissage et la confusion (les game plugins ont leurs propres noms,
|
||||
l'aliasing devient un bruit).
|
||||
- **`delete` devient admin** : `/core team delete <team>` (au lieu de
|
||||
l'ancien `/core team delete` qui ciblait l'équipe du chef). Cohérent avec
|
||||
`create` qui est aussi admin.
|
||||
|
||||
## 2026-06-09 — Team peut être leaderless
|
||||
|
||||
- **Choix** : `Team.leaderId` devient nullable. `getLeaderId()` renvoie
|
||||
`Optional<UUID>`, `getLeader()` renvoie `Optional<TeamMember>`. Nouveau
|
||||
`hasLeader()` et `isLeader(UUID)` pour les checks.
|
||||
- **Raison** : le modèle admin requiert qu'on puisse créer une équipe sans
|
||||
chef et l'assigner ensuite via {@code setLeader}. Avant, créer une équipe
|
||||
imposait de connaître l'UUID du chef.
|
||||
- **Constructeurs ajoutés** :
|
||||
- `new Team(id, name, tag, color)` — leaderless, PRIVATE
|
||||
- `new Team(id, name, tag, color, visibility)` — leaderless avec visibilité
|
||||
- Les constructeurs avec leaderId acceptent maintenant `null`.
|
||||
- **`Team.setLeader(playerId)`** : assigne un chef à n'importe quel moment.
|
||||
Si la team a déjà un chef, il est démis en MEMBER. Si le nouveau n'est
|
||||
pas membre, il est auto-ajouté.
|
||||
- **`Team.transferLeadership(playerId)`** : conserve sa sémantique stricte
|
||||
(chef→chef, membre déjà existant). Lève `IllegalStateException` si la team
|
||||
est leaderless. Utilisé par la commande `/core team transfer` (chef).
|
||||
- **`TeamLeadershipTransferEvent.getOldLeaderId()`** renvoie maintenant
|
||||
`Optional<UUID>` (vide si la team était leaderless avant l'opération).
|
||||
- **Schéma SQLite** : la colonne `crcore_teams.leader_id` n'a plus la
|
||||
contrainte `NOT NULL`. Migration automatique sur nouvelle base — pour les
|
||||
bases existantes, ALTER TABLE manuel ou suppression du fichier
|
||||
(les bases d'event sont jetables).
|
||||
|
||||
## 2026-06-09 — Nouvelle commande `/core team setleader`
|
||||
|
||||
- **Choix** : ajout de `TeamSetLeaderSubCommand` (`/core team setleader
|
||||
<team> <player>`). Permission `crcore.team.setleader`. Délègue à
|
||||
`TeamService.setLeader(...)`.
|
||||
- **Différence avec `/core team transfer`** :
|
||||
- `transfer` : action **chef**, cible son équipe, le nouveau chef doit déjà
|
||||
être membre.
|
||||
- `setleader` : action **admin**, cible n'importe quelle équipe, le nouveau
|
||||
chef peut être non-membre (auto-ajouté).
|
||||
- **Use cases couverts** :
|
||||
- Admin assigne un chef à une équipe leaderless fraîchement créée.
|
||||
- Admin remplace le chef d'une équipe (le membre target est déjà dans
|
||||
l'équipe ou pas — peu importe).
|
||||
- Admin "promote member up to leader" (cas explicitement demandé).
|
||||
|
||||
## 2026-06-09 — Bascule Java 16 → Java 11 (révision)
|
||||
|
||||
- **Révision** de la décision "Java 16" du 2026-06-08.
|
||||
|
||||
Reference in New Issue
Block a user