# Setup technique
## Stack
- **Type** : librairie Java (`jar`) — pas un plugin Bukkit
- **artifactId Maven** : `CR-Core`
- **Build** : Maven
- **Java** : 16
- **API serveur (provided)** : Paper 1.16.5
(`com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT`)
- **Package racine** : `fr.luc.crcore`
## Dépôts Maven
- `papermc` — https://repo.papermc.io/repository/maven-public/
- `spigot-repo` — https://hub.spigotmc.org/nexus/content/repositories/snapshots/
- `sonatype` — https://oss.sonatype.org/content/groups/public/
## Build & install local
```bash
mvn clean install
```
Cela publie `fr.luc:CR-Core:1.0-SNAPSHOT` dans le repo Maven local `~/.m2/`,
prêt à être consommé par les plugins de jeu.
## Utilisation depuis un plugin de jeu
Dans le `pom.xml` du plugin de jeu :
```xml
fr.luc
CR-Core
1.0-SNAPSHOT
compile
```
> Scope `compile` (et non `provided`) **si** le plugin de jeu shade CR-Core dans
> son propre jar (recommandé pour de la pure librairie). Pensez à utiliser un
> `` dans le `maven-shade-plugin` du plugin de jeu pour éviter les
> conflits si plusieurs plugins shadent CR-Core sur le même serveur.
Côté code du plugin de jeu :
```java
public final class MyGamePlugin extends JavaPlugin {
private TeamService teamService;
@Override
public void onEnable() {
// Instancie le service team (chaque plugin a son propre registre)
this.teamService = new TeamServiceImpl(new InMemoryTeamRepository());
// Enregistre une commande basée sur le framework de CR-Core
getCommand("team").setExecutor(new TeamCommand(teamService));
getCommand("team").setTabCompleter(new TeamCommand(teamService));
}
}
```
Exemple minimal de commande :
```java
public class TeamCommand extends BaseCommand {
public TeamCommand(TeamService service) {
super("team", "teams", "t");
description("Manage teams");
addSubCommand(new TeamCreateSub(service));
addSubCommand(new TeamInfoSub(service));
}
}
public class TeamCreateSub extends SubCommand {
private final TeamService service;
public TeamCreateSub(TeamService service) {
super("create", "c", "new");
this.service = service;
description("Create a new team");
permission("mygame.team.create");
playerOnly();
argument("name", ArgumentTypes.STRING);
argument("tag", ArgumentTypes.STRING);
argument("color", ArgumentTypes.enumOf(TeamColor.class));
}
@Override
public CommandResult execute(CommandContext ctx) {
Player player = ctx.requirePlayer();
String name = ctx.get("name");
String tag = ctx.get("tag");
TeamColor color = ctx.get("color");
try {
Team team = service.createTeam(name, tag, color, player.getUniqueId());
return CommandResult.success("Équipe " + team.getName() + " créée !");
} catch (TeamException ex) {
return CommandResult.failure(ex.getMessage());
}
}
}
```
Et dans le `plugin.yml` du plugin de jeu :
```yaml
name: MyGame
main: fr.luc.mygame.MyGamePlugin
version: 1.0
api-version: 1.16
commands:
team:
description: Manage teams
aliases: [teams, t]
```
## Override
Toute classe du noyau peut être étendue :
```java
public class LoggingTeamService extends TeamServiceImpl {
public LoggingTeamService(TeamRepository repo) { super(repo); }
@Override
protected void onAfterCreate(Team team) {
getPlugin().getLogger().info("Team created: " + team.getName());
}
@Override
protected Team newTeam(UUID id, String name, String tag, TeamColor color, UUID leaderId) {
return new MyCustomTeam(id, name, tag, color, leaderId);
}
}
```
## Arborescence du projet
```
CitesPlugin/ # dossier IntelliJ (renommer plus tard si voulu)
├── pom.xml
├── GEMINI.md
├── docs/ # source de vérité
│ ├── README.md
│ ├── setup.md
│ ├── features.md
│ ├── decisions.md
│ └── diagrams/
│ ├── team-class-diagram.puml
│ ├── team-create-sequence.puml
│ ├── team-create-activity.puml
│ └── command-class-diagram.puml
└── src/main/java/fr/luc/crcore/
├── common/ # abstractions partagées
│ ├── Identifiable.java # interface
│ ├── Named.java # interface
│ ├── ScoreHolder.java # interface (impl. par Team et PlayerProfile)
│ ├── AbstractEntity.java # abstract class
│ └── Repository.java # interface
├── command/ # framework de commandes
│ ├── Command.java # interface
│ ├── AbstractCommand.java # base partagée
│ ├── BaseCommand.java # commande top-level (Bukkit-aware)
│ ├── SubCommand.java # sous-commande
│ ├── CommandContext.java
│ ├── CommandResult.java
│ ├── CommandException.java
│ ├── ArgumentType.java
│ ├── ArgumentTypes.java # STRING, INTEGER, BOOLEAN, ONLINE_PLAYER, enumOf, choice
│ └── ArgumentDef.java # package-private
├── team/ # domaine team
│ ├── Team.java
│ ├── TeamMember.java
│ ├── TeamRole.java # enum
│ ├── TeamColor.java # enum
│ ├── TeamVisibility.java # enum (PUBLIC / PRIVATE)
│ ├── TeamRanking.java # record (rank, team, score)
│ ├── TeamRepository.java # interface
│ ├── InMemoryTeamRepository.java # impl
│ ├── TeamService.java # interface
│ ├── TeamServiceImpl.java # impl avec hooks overridables
│ ├── TeamException.java
│ ├── TeamAlreadyExistsException.java
│ ├── TeamNotFoundException.java
│ └── TeamAccessException.java # auto-join refusé
└── player/ # domaine player
├── PlayerProfile.java # entité, scores par joueur
├── PlayerRanking.java # record (rank, profile, score)
├── PlayerProfileRepository.java # interface
├── InMemoryPlayerProfileRepository.java
├── PlayerProfileService.java # interface
├── PlayerProfileServiceImpl.java # impl avec hooks overridables
├── PlayerException.java
└── PlayerProfileNotFoundException.java
```
> **Note IntelliJ** : le dossier physique s'appelle encore `CitesPlugin/`. Pour
> le renommer en `CR-Core/`, fermer IntelliJ, renommer, rouvrir. Le `pom.xml`
> et les packages sont déjà à jour, le nom du dossier n'a aucun impact sur le
> build.