diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9c21630 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,175 @@ +# CLAUDE.md — Instructions pour l'assistant + +## Source de vérité + +**Le dossier `docs/` est la source unique de vérité du projet.** + +- Toute spécification, règle, décision technique, commande ou contrainte doit + être lue depuis `docs/` et écrite dans `docs/`. +- Avant d'implémenter, vérifier ce qui est consigné dans `docs/`. +- Toute nouvelle information donnée par l'utilisateur va dans le fichier adapté : + - `docs/features.md` — domaines fonctionnels (chaque feature a sa section + numérotée : team, player, modération, broadcasts, messages, GUI, + team-config, database, command framework, bootstrap) + - `docs/decisions.md` — décisions techniques / architecturales (ADR léger, + une décision = un titre + contexte + choix + raison) + - `docs/setup.md` — build, intégration dans un plugin de jeu, arborescence, + snippets d'usage, publication Maven (Gitea Packages) + - `docs/README.md` — vue d'ensemble, index des features, index des diagrammes + - `docs/diagrams/*.puml` — diagrammes PlantUML organisés en + `util/` + `features//` + transverses à la racine +- En cas de conflit code ↔ `docs/`, `docs/` fait foi. + +## Nature du projet + +**CR-Core** est une **librairie Java/Maven** consommée par des plugins Bukkit +("plugins de jeu"). Pas de `plugin.yml` côté core — c'est le plugin de jeu qui +en a un et qui instancie `CRCore` dans son `onEnable()`. + +- **Nom** : CR-Core (artifactId Maven : `CR-Core`) +- **Type** : librairie (`jar`) +- **Cible runtime** : serveur Paper/Spigot 1.16.5 +- **Build** : Maven, **Java 11** (pas de records / pattern matching / switch + expressions — déjà downgradé une fois, ne pas réintroduire) +- **Package racine** : `fr.luc.crcore` +- **SQLite** : `org.xerial:sqlite-jdbc` (compile scope) +- **PlaceholderAPI** : `me.clip:placeholderapi` 2.11.6 (provided) +- **Publication** : Gitea Packages Maven sur + `https://gitea.luc-rival.fr/api/packages/admin/maven` (repo HTTPS + `https://gitea.luc-rival.fr/admin/Cites_Plugins.git`) + +## Architecture en couches + +Le code est séparé en trois couches qui se reflètent dans les packages : + +``` +fr.luc.crcore/ +├── CRCore + CRCoreConfig ← entrée + config builder +├── builtin/ ← commandes top-level +│ ├── CoreCommand (/core) +│ └── CoreReloadSubCommand (/core reload) +├── util/ ← TOUJOURS actif (infrastructure) +│ ├── common/ (Identifiable, Named, ScoreHolder, …) +│ ├── command/ (framework : BaseCommand, SubCommand, …) +│ ├── database/ (wrapper SQLite : Database, TableBuilder) +│ ├── message/ (MessagesService, YAML impl) +│ ├── broadcast/ (BroadcastService, listener cross-feature) +│ ├── gui/ (AbstractInventoryGui, GuiListener) +│ └── placeholder/ (CRCorePlaceholderExpansion PAPI) +└── features/ ← OPT-IN via CRCoreConfig.setupX() + ├── team/ (setupTeams()) + │ ├── event/ exception/ impl/ + │ ├── config/ (TeamSetting, TeamConfigService + GUI) + │ └── command/ (14 Team*SubCommand sous /core team) + ├── player/ (setupPlayers()) + │ └── event/ exception/ impl/ + └── moderation/ (setupModeration() — skeleton) + ├── event/ exception/ impl/ + ├── command/ (/core admin) + └── tool/ (5 ModeratorTool squelette) +``` + +**Règle d'or** : un util ne dépend jamais d'une feature. Une feature peut +dépendre d'utils. Les features se référencent uniquement via leurs interfaces +publiques (jamais via `impl/`). + +## Setup modulaire (opt-in) + +Les features sont opt-in via `CRCoreConfig` : + +```java +new CRCore(this, new CRCoreConfig() + .setupTeams() + .setupPlayers() + .setupPlaceholders() + .setupModeration()) // ou setupAll() pour tout activer + .enable(); +``` + +- Par défaut : **aucune feature** n'est active, seule la couche util. +- Getter d'une feature désactivée → `IllegalStateException` avec message + qui pointe sur le `setupX()` manquant. +- Sous-commande d'une feature désactivée → simplement pas enregistrée + (ex. `/core team` n'existe pas si `setupTeams()` non appelé). + +## Modèle de fichiers générés au runtime + +Au premier `enable()`, CR-Core crée dans le dataFolder du plugin de jeu : + +| Fichier (`-…`) | Contenu | Couche | +|---|---|---| +| `messages.yml` | Templates des messages (commandes + broadcasts) | util | +| `broadcasts.yml` | Routes : quel event → quelles audiences | util | +| `team-config.yml` | Defaults globaux des paramètres d'équipe | feature team | + +Pattern commun : defaults bundlés dans le jar (`crcore-*.yml`), fichier user +copié au premier boot (le plugin de jeu peut bundler son propre template +sous le même nom pour le supplanter). Couches en mémoire = defaults + user. + +`/core reload` (perm `crcore.reload`) recharge les trois à chaud. + +## Principe : simple par défaut, overridable partout + +Chaque service expose des **hooks `protected`** que les plugins de jeu +peuvent overrider : + +- factories (`newTeam`, `newRanking`, `newProfile`) +- validations (`validateName`, `validateJoinable`, …) +- post-hooks (`onAfterCreate`, `onMemberAdded`, `onScoreChanged`, + `onAfterEnter`, `onAfterExit`, …) + +Chaque commande built-in (`TeamCreateSubCommand`, etc.) est elle aussi +substituable par nom via `replaceSubCommand(...)`. + +Sur `CRCore`, override les `buildX()` pour fournir une impl alternative +(`buildTeamService`, `buildMessagesService`, `buildBroadcastService`, +`buildTeamConfigService`, `buildModerationService`, +`registerDefaultModeratorTools`). + +**Règles** : +- Pas de `final` sur les classes du noyau. +- Méthodes-clés en `protected` (pas `private`). +- Hooks `onBefore...` / `onAfter...` partout où ça a du sens. +- Factories pour permettre les sous-classes. + +## Workflow attendu + +1. Lire le contexte pertinent dans `docs/`. +2. Discuter / valider l'approche avec l'utilisateur si nécessaire. +3. Mettre à jour `docs/` (et le `.puml` concerné) avec la décision ou la spec. +4. Implémenter le code conformément à la doc. +5. Compiler (`mvn clean compile`) — BUILD SUCCESS obligatoire avant commit. +6. Déployer si la version le justifie (`mvn clean deploy` → Gitea Packages). +7. Commit + push (token Gitea fourni par l'utilisateur ; URL HTTPS). + +## Conventions de code + +- Code (classes, méthodes, attributs, variables) en **anglais standard**. +- Messages joueur et documentation en **français**. +- JavaDoc en français sur les classes publiques et les méthodes non triviales. +- Séparation stricte : + - `interface`, `enum`, `abstract class`, `class` concrète, `exception` — + chacun dans son fichier. + - Au sein d'un domaine : contrats publics (interfaces, entités, enums) au + top du package, `impl/` pour les implémentations swappables, + `exception/` pour les exceptions, `event/` pour les events Bukkit. +- Pas d'API Java 12+ (records, switch expressions, instanceof pattern + matching). Cible compile = Java 11. +- Pour les events Bukkit : `HandlerList` static, base abstraite par feature, + `getHandlerList()` static obligatoire. + +## Conventions Git + +- Commits descriptifs en anglais, message multi-lignes via heredoc. +- Co-author trailer : `Co-Authored-By: Claude Opus 4.7 `. +- Push sur `main` via URL HTTPS avec token (l'utilisateur fournit le token, + warning donné si stocké en clair). +- Le repo Gitea est `gitea.luc-rival.fr/admin/Cites_Plugins` (HTTPS). + +## Build / Maven + +- **JAVA_HOME** : `C:\Program Files\JetBrains\IntelliJ IDEA 2026.1.3\jbr` + (JetBrains Runtime utilisé comme JDK) +- **mvn** : `C:\Program Files\JetBrains\IntelliJ IDEA 2026.1.3\plugins\maven\lib\maven3\bin\mvn.cmd` +- Commande compile : `mvn clean compile -B` +- Commande deploy : `mvn clean deploy -B` (publie sur Gitea Packages) diff --git a/GEMINI.md b/GEMINI.md deleted file mode 100644 index 7a01e53..0000000 --- a/GEMINI.md +++ /dev/null @@ -1,78 +0,0 @@ -# GEMINI.md — Instructions pour l'assistant - -## Source de vérité - -**Le dossier `docs/` est la source unique de vérité du projet.** - -- Toute spécification, règle, décision technique, commande ou contrainte doit - être lue depuis `docs/` et écrite dans `docs/`. -- Avant d'implémenter, vérifier ce qui est consigné dans `docs/`. -- Toute nouvelle information donnée par l'utilisateur va dans le fichier adapté : - - `docs/features.md` — domaines fonctionnels (team, player, commandes built-in, events, database) - - `docs/decisions.md` — décisions techniques / architecturales - - `docs/setup.md` — installation, build, intégration côté plugin de jeu - - `docs/README.md` — vue d'ensemble et index - - `docs/diagrams/*.puml` — diagrammes (classe / séquence / activité) -- En cas de conflit code ↔ `docs/`, `docs/` fait foi. - -## Nature du projet - -**CR-Core** est une **librairie Java/Maven** consommée par des plugins Bukkit -("plugins de jeu"). Pas de `plugin.yml` côté core — c'est le plugin de jeu -qui en a un et qui instancie {@code CRCore} dans son {@code onEnable()}. - -- **Nom** : CR-Core (artifactId Maven : `CR-Core`) -- **Type** : librairie (`jar`) -- **Cible runtime** : serveur Paper/Spigot 1.16.5 -- **Build** : Maven, Java 16 -- **Package racine** : `fr.luc.crcore` -- **SQLite** : `org.xerial:sqlite-jdbc` (compile scope) - -## Domaines - -- `fr.luc.crcore.common` — abstractions partagées (`Identifiable`, `Named`, - `ScoreHolder`, `AbstractEntity`, `Repository`) -- `fr.luc.crcore.team` — équipes : visibilité (PUBLIC/PRIVATE), membres, - leader, scores nommés, classements, point de spawn. Sous-package `event/` - pour les évènements Bukkit. -- `fr.luc.crcore.player` — profils joueurs : scores nommés, classements - individuels. Sous-package `event/`. -- `fr.luc.crcore.command` — framework de commandes (nested sub-commands, - arguments typés, tab-complete). Sous-package `builtin/` pour les commandes - par défaut `/core team ...`. -- `fr.luc.crcore.database` — wrapper SQLite minimaliste (`Database`, - `TableBuilder`, `RowMapper`). -- `fr.luc.crcore.CRCore` — point d'entrée bootstrap (instancié en une ligne - par le plugin de jeu). - -## Principe : simple par défaut, overridable partout - -Chaque service expose des **hooks `protected`** que les plugins de jeu peuvent -overrider : -- factories (`newTeam`, `newRanking`, `newProfile`) -- validations (`validateName`, `validateJoinable`, …) -- post-hooks (`onAfterCreate`, `onMemberAdded`, `onScoreChanged`, …) - -Chaque commande built-in (`TeamCreateSubCommand`, etc.) est elle aussi -substituable par nom via `replaceSubCommand(...)`. - -**Règles** : -- Pas de `final` sur les classes du noyau. -- Méthodes-clés en `protected` (pas `private`). -- Hooks `onBefore...` / `onAfter...` partout où ça a du sens. -- Factories pour permettre les sous-classes. - -## Workflow attendu - -1. Lire le contexte pertinent dans `docs/`. -2. Discuter / valider l'approche avec l'utilisateur si nécessaire. -3. Mettre à jour `docs/` (et le `.puml` concerné) avec la décision ou la spec. -4. Implémenter le code conformément à la doc. - -## Conventions de code - -- Code (classes, méthodes, attributs, variables) en **anglais standard**. -- Messages joueur et documentation en **français**. -- JavaDoc en français sur les classes publiques et les méthodes non triviales. -- Séparation stricte : `interface`, `enum`, `abstract class`, `class` concrète, - `exception` — chacun dans son fichier. diff --git a/docs/setup.md b/docs/setup.md index a0de79c..88144f0 100644 --- a/docs/setup.md +++ b/docs/setup.md @@ -180,7 +180,7 @@ int kills = db.queryOne( ``` CitesPlugin/ # dossier IntelliJ (renommer plus tard si voulu) ├── pom.xml -├── GEMINI.md +├── CLAUDE.md ├── docs/ │ ├── README.md │ ├── setup.md