pending-votes.scope (config.properties Velocity) = global (defaut, comportement historique) ou per-server. En per-server, un vote hors ligne incremente le compteur de chaque serveur de direct-vote.servers independamment (nouvelle table nb_votes_attente_serveur) ; /claim sur un serveur ne remet a 0 que ce serveur-la. Necessite server-name (config.yml) et storage.pending-votes-scope assortis cote Spigot. Ajoute LICENSE (MIT) et credit Sar_Tron (plugin.yml, @Plugin Velocity, pom parent, README) en vue de la publication publique. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
221 lines
13 KiB
Markdown
221 lines
13 KiB
Markdown
# VoteNetwork
|
||
|
||
Par **Sar_Tron**, sous licence [MIT](LICENSE).
|
||
|
||
Systeme de vote reseau en deux modules, pour une architecture **proxy Velocity + serveurs Spigot/Paper** (modes A, B, C, ...).
|
||
|
||
- `velocity/` — module proxy. Recoit `votenetwork vote <pseudo>` (console uniquement) et route le vote en direct ou le met en attente.
|
||
- `spigot/` — module serveur. Recoit le signal en direct via Plugin Messaging, gere `/claim`, le VoteParty local et le mode maintenance.
|
||
|
||
Compatible **Java 17**, compile contre l'API Spigot **1.18.2** (additive, donc compatible en avant vers 1.19 → 1.21.x et versions futures).
|
||
|
||
---
|
||
|
||
## Sommaire
|
||
|
||
- [Installation](#installation)
|
||
- [Build depuis les sources](#build-depuis-les-sources)
|
||
- [Configuration](#configuration)
|
||
- [Stockage : MySQL ou YAML](#stockage--mysql-ou-yaml)
|
||
- [Fonctionnement du vote](#fonctionnement-du-vote)
|
||
- [Commandes & permissions](#commandes--permissions)
|
||
- [VoteParty](#voteparty)
|
||
- [API publique (scoreboard / GUI)](#api-publique-scoreboard--gui)
|
||
- [Structure de la base de données](#structure-de-la-base-de-données)
|
||
|
||
---
|
||
|
||
## Installation
|
||
|
||
1. `velocity/target/VoteNetwork-Velocity.jar` → `plugins/` du proxy Velocity.
|
||
2. `spigot/target/VoteNetwork-Spigot.jar` → `plugins/` de **chaque** serveur Spigot/Paper (A, B, C, ...).
|
||
3. Démarrer une fois pour générer les fichiers de config, puis les éditer :
|
||
- Proxy : `plugins/votenetwork/config.properties`
|
||
- Serveur : `plugins/votenetwork/config.yml`
|
||
4. Redémarrer.
|
||
|
||
> **⚠️ Même base de données partout.** `mysql.host` / `mysql.port` / `mysql.database` / `mysql.user` / `mysql.password` doivent être **identiques** dans `config.properties` (Velocity) et dans **chaque** `config.yml` (tous les serveurs Spigot : A, B, C...). C'est cette base commune qui permet à un joueur de voter hors ligne, puis de récupérer ses votes avec `/claim` sur n'importe lequel de vos serveurs. Des bases différentes = `/claim` ne retrouvera jamais les votes stockés par Velocity. Voir aussi [Stockage : MySQL ou YAML](#stockage--mysql-ou-yaml).
|
||
|
||
## Build depuis les sources
|
||
|
||
```
|
||
mvn clean package
|
||
```
|
||
|
||
Jars produits dans `velocity/target/` et `spigot/target/`.
|
||
|
||
## Configuration
|
||
|
||
Chaque composant a son propre fichier, tous deux dans un dossier **`votenetwork`** :
|
||
|
||
| Composant | Fichier | Dossier |
|
||
|---|---|---|
|
||
| Velocity | `config.properties` | `plugins/votenetwork/` (racine du proxy) |
|
||
| Spigot | `config.yml` | `plugins/votenetwork/` (sur chaque serveur) |
|
||
|
||
Le `config.yml` Spigot regroupe tout ce qui est personnalisable :
|
||
|
||
```yaml
|
||
storage:
|
||
type: mysql # mysql ou yaml
|
||
|
||
mysql:
|
||
host: 127.0.0.1
|
||
port: 3306
|
||
database: votenetwork
|
||
user: root
|
||
password: changeme
|
||
pool-size: 5
|
||
|
||
rewards:
|
||
vote-commands: # executees pour CHAQUE vote (direct ou via /claim, une fois par vote)
|
||
- "goldencrates give %player% vote_key 1"
|
||
broadcast: # message annonce a tout le serveur a chaque vote / claim
|
||
enabled: false
|
||
message: "&a[Vote] &e%player% &fvient de voter, merci a lui !"
|
||
|
||
voteparty:
|
||
votes-requis: 100 # déclenche le VoteParty à ce cumul (par serveur)
|
||
commands: # executees UNE fois quand le VoteParty se déclenche
|
||
- "goldencrates broadcast_give vote_key 1"
|
||
broadcast:
|
||
enabled: true
|
||
progress-message: "&b[Vote] &f%current%&7/&f%required% &fvotes avant le prochain VoteParty !"
|
||
triggered-message: "&a[Vote] &fVoteParty declenche ! Profitez des recompenses !"
|
||
|
||
messages:
|
||
direct-vote: "&a[Vote] &fMerci pour ton vote !"
|
||
claim-success: "&a[Vote] &fVous avez recupere &e%amount% &fvote(s) en attente !"
|
||
claim-empty: "&c[Vote] &fVous n'avez aucun vote en attente."
|
||
maintenance: "&c[Vote] &fLe systeme de vote est actuellement en maintenance."
|
||
maintenance-enabled: "&c[Vote] &fMode maintenance active."
|
||
maintenance-disabled: "&a[Vote] &fMode maintenance desactive."
|
||
no-permission: "&cVous n'avez pas la permission d'utiliser cette commande."
|
||
```
|
||
|
||
- `%player%` dans `rewards.vote-commands` est remplacé par le pseudo du joueur.
|
||
- `%current%` / `%required%` dans les messages de progression VoteParty.
|
||
- `%amount%` dans le message de succès `/claim` et dans `rewards.broadcast.message`.
|
||
- Codes couleur `&` supportés partout.
|
||
- `rewards.broadcast` (désactivé par défaut) : annonce publique à chaque vote direct ou à chaque `/claim` (avec le nombre de votes récupérés).
|
||
|
||
## Stockage : MySQL ou YAML
|
||
|
||
Chaque composant choisit son stockage via `storage.type`, **mais ce choix doit être le même partout** (Velocity + tous les serveurs Spigot), avec les mêmes identifiants de connexion :
|
||
|
||
- **`mysql`** (recommandé, seul mode fiable pour un vrai réseau) : Velocity et tous les serveurs Spigot pointent sur **la même base** (même `host`/`database`/`user`/`password`). La table `nb_votes_attente` est créée automatiquement au démarrage si absente. Un vote stocké par Velocity (joueur hors ligne) est donc visible par `/claim` sur n'importe quel serveur.
|
||
- **`yaml`** : fichier local `pending-votes.yml` dans le dossier de **chaque** plugin (un par proxy, un par serveur). **Pas synchronisé automatiquement** entre eux. Si Velocity est en `yaml` et qu'un serveur Spigot vote pour lui-même en `mysql` (ou l'inverse), `/claim` ne trouvera jamais les votes stockés côté proxy. N'utilisez ce mode qu'en solo/test, ou si tous les dossiers de plugins partagent le même disque (montage réseau, symlink) — sinon utilisez `mysql` partout.
|
||
|
||
Testez la connexion/l'accès au stockage configuré côté Spigot avec :
|
||
|
||
```
|
||
/vote testdb
|
||
```
|
||
|
||
### Portée des votes en attente : partagée (`global`) ou par serveur (`per-server`)
|
||
|
||
En mode `mysql` uniquement, `pending-votes.scope` (dans `config.properties` côté Velocity) contrôle si le compteur de votes en attente est **partagé** entre tous les serveurs ou **indépendant par serveur** :
|
||
|
||
- **`global`** (par défaut) : un seul compteur par joueur. Un `/claim` sur n'importe quel serveur le remet à 0 **partout** à la fois.
|
||
- **`per-server`** : chaque serveur listé dans `direct-vote.servers` a son propre compteur. Un vote hors ligne incrémente le compteur de **chaque** serveur de la liste. Un `/claim` sur le serveur 1 ne remet à 0 **que** le serveur 1 — le joueur garde ses votes en attente sur le serveur 2 et peut les réclamer séparément là-bas.
|
||
|
||
> Exemple : le joueur vote 2 fois hors ligne → 2 votes en attente sur *chaque* serveur. `/claim` sur le serveur 1 → 2 récompenses, serveur 1 repasse à 0, serveur 2 reste à 2. S'il revote une fois → serveur 1 = 1, serveur 2 = 3.
|
||
|
||
Pour activer `per-server`, il faut **les deux** :
|
||
1. `pending-votes.scope=per-server` + `direct-vote.servers` rempli dans `config.properties` (Velocity).
|
||
2. `storage.pending-votes-scope: per-server` + `server-name: "gen1"` (nom exact tiré de `direct-vote.servers`) dans le `config.yml` de **chaque** serveur Spigot concerné.
|
||
|
||
Si ces réglages ne correspondent pas entre le proxy et un serveur (scope différent, ou `server-name` absent/mal orthographié), ce serveur ne retrouvera jamais les votes stockés par Velocity.
|
||
|
||
## Fonctionnement du vote
|
||
|
||
1. Un site de vote appelle la console du proxy : `votenetwork vote <pseudo>`.
|
||
2. **Joueur connecté ET sur un serveur listé dans `direct-vote.servers`** : le proxy envoie un paquet sur le canal `votenetwork:vote`. Le serveur Spigot donne la récompense immédiatement et incrémente son VoteParty local de +1. **Rien n'est écrit en base.**
|
||
3. **Joueur déconnecté, OU connecté mais sur un serveur absent de `direct-vote.servers`** (ex: un lobby sans le plugin) : le proxy résout son UUID (API Mojang, avec repli si indisponible) et incrémente son compteur de votes en attente (MySQL ou YAML selon la config), de façon asynchrone.
|
||
4. Le joueur tape `/claim` sur un serveur Spigot : lecture asynchrone du compteur en attente, distribution des récompenses × N, VoteParty local +N, remise à 0.
|
||
5. `/vote stop` bloque `/claim` (mode maintenance, message personnalisable) ; `/vote start` le réactive.
|
||
|
||
> **Important** : `direct-vote.servers` (dans `config.properties` côté Velocity) doit lister les noms exacts des serveurs (tels que dans `velocity.toml`) où `VoteNetwork-Spigot.jar` est installé. Un joueur sur un serveur absent de cette liste (lobby, hub...) est traité comme "hors ligne" pour le vote — sinon le paquet direct part dans le vide (aucun plugin pour l'écouter) et le vote est perdu silencieusement.
|
||
|
||
## Commandes & permissions
|
||
|
||
| Commande | Où | Qui | Description |
|
||
|---|---|---|---|
|
||
| `votenetwork vote <pseudo>` | Velocity | Console uniquement | Enregistre un vote pour le joueur |
|
||
| `/claim` | Spigot | Joueurs | Récupère les votes en attente |
|
||
| `/vote stop\|start` | Spigot | `votenetwork.admin` (op par défaut) | Bascule le mode maintenance |
|
||
| `/vote testdb` | Spigot | `votenetwork.admin` (op par défaut) | Teste le stockage configuré (MySQL ou YAML) |
|
||
|
||
## VoteParty
|
||
|
||
- Compteur indépendant **par serveur**, toujours persistant localement dans `plugins/votenetwork/voteparty.yml` (indépendant de `storage.type`, qui ne concerne que les votes en attente), survit aux redémarrages.
|
||
- `voteparty.votes-requis` définit le seuil de déclenchement.
|
||
- `voteparty.commands` s'exécutent une fois le seuil atteint, puis le compteur repart à 0 (avec report de l'excédent si plusieurs votes arrivent d'un coup, ex. via `/claim` de N votes).
|
||
- Messages de progression et de déclenchement personnalisables (`voteparty.broadcast`).
|
||
|
||
## API publique (scoreboard / GUI)
|
||
|
||
Un autre plugin sur le même serveur Spigot peut lire l'état du vote via `fr.votenetwork.spigot.api.VoteNetworkAPI` :
|
||
|
||
```java
|
||
VoteNetworkAPI api = VoteNetworkAPI.get();
|
||
// ou : Bukkit.getServicesManager().getRegistration(VoteNetworkAPI.class).getProvider();
|
||
|
||
int current = api.getVotePartyCurrentVotes();
|
||
int required = api.getVotePartyRequiredVotes();
|
||
boolean maintenance = api.isMaintenanceEnabled();
|
||
|
||
api.getPendingVotes(player.getUniqueId(), pending -> {
|
||
// callback rappelé sur le thread principal — safe pour un scoreboard/GUI
|
||
scoreboardLine.setText("Votes en attente: " + pending);
|
||
});
|
||
```
|
||
|
||
- `getVotePartyCurrentVotes()` / `getVotePartyRequiredVotes()` : lecture directe en mémoire, thread principal uniquement.
|
||
- `getPendingVotes(...)` : lecture asynchrone du stockage configuré (MySQL ou YAML), ne consomme pas les votes contrairement à `/claim`.
|
||
|
||
### Placeholders PlaceholderAPI (scoreboard/GUI sans coder de plugin)
|
||
|
||
Si [PlaceholderAPI](https://www.spigotmc.org/resources/placeholderapi.6245/) est installé, VoteNetwork enregistre automatiquement ses propres placeholders (aucune config nécessaire) :
|
||
|
||
| Placeholder | Valeur |
|
||
|---|---|
|
||
| `%votenetwork_voteparty_current%` | Votes cumulés sur ce serveur pour le VoteParty |
|
||
| `%votenetwork_voteparty_required%` | Objectif VoteParty (`voteparty.votes-requis`) |
|
||
| `%votenetwork_voteparty_remaining%` | Votes restants avant déclenchement |
|
||
| `%votenetwork_maintenance%` | `true`/`false` |
|
||
| `%votenetwork_pending%` | Votes en attente du joueur (rafraîchi en arrière-plan, pas de lag) |
|
||
|
||
Utilisez ces placeholders directement dans la config de votre plugin de scoreboard/tab/GUI habituel (FeatherBoard, TAB, DeluxeMenus, ...) — **pas** `%current%`/`%required%` bruts, qui n'existent pas côté PlaceholderAPI et doivent être définis dans la config du plugin de scoreboard lui-même.
|
||
|
||
## Structure de la base de données
|
||
|
||
Créées automatiquement si absentes (mode `mysql`), les deux tables coexistent toujours — seule celle correspondant à `pending-votes.scope` est utilisée :
|
||
|
||
```sql
|
||
-- scope = global (par defaut)
|
||
CREATE TABLE IF NOT EXISTS nb_votes_attente (
|
||
player_uuid VARCHAR(36) NOT NULL PRIMARY KEY,
|
||
player_name VARCHAR(16) NOT NULL,
|
||
nombre_votes INT DEFAULT 0
|
||
);
|
||
|
||
-- scope = per-server
|
||
CREATE TABLE IF NOT EXISTS nb_votes_attente_serveur (
|
||
player_uuid VARCHAR(36) NOT NULL,
|
||
server_name VARCHAR(64) NOT NULL,
|
||
player_name VARCHAR(16) NOT NULL,
|
||
nombre_votes INT DEFAULT 0,
|
||
PRIMARY KEY (player_uuid, server_name)
|
||
);
|
||
```
|
||
|
||
---
|
||
|
||
## Notes techniques
|
||
|
||
- HikariCP + MySQL Connector/J sont shadés et relocalisés dans les deux jars (rien à installer manuellement sur le serveur). Le driver JDBC est chargé explicitement par son nom de classe relocalisé pour rester fiable après le shading.
|
||
- Toutes les requêtes SQL et I/O fichier sont asynchrones — aucun accès réseau ou disque ne bloque le thread principal du serveur ni celui du proxy.
|
||
- Si la connexion MySQL échoue au démarrage, le plugin reste actif (pas de crash) : corrigez `config.yml`/`config.properties` puis utilisez `/vote testdb`, ou redémarrez.
|
||
- **Mise à jour de config** : à chaque démarrage, les nouvelles options apportées par une mise à jour du plugin (absentes de votre `config.yml`/`config.properties` existant) sont ajoutées automatiquement, **sans jamais toucher aux valeurs que vous avez déjà personnalisées**. Côté Spigot, la réécriture du `config.yml` fait perdre les commentaires (limitation de l'API Bukkit) ; côté Velocity, les nouvelles clés sont simplement ajoutées en bas du `config.properties`, les commentaires existants sont préservés.
|