Files
VoteNetwork/README.md
T
SarTron-NorthBlueandClaude Sonnet 5 d5f6e0cfb3 Ajoute un script de release Gitea (scripts/release.sh)
Sur demande uniquement (pas de trigger auto par commit) : build les 2
jars, zip, cree le tag/release via l'API Gitea et y attache le zip.
Token passe en variable d'env GITEA_TOKEN, jamais stocke dans le repo.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 19:24:13 +04:00

229 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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/`.
### Publier une release (Gitea)
```
GITEA_TOKEN=xxxx ./scripts/release.sh 1.0.1 "Description de la release"
```
Build les 2 jars, les zip dans `dist/VoteNetwork.zip`, crée le tag/release sur Gitea et y attache le zip. Nécessite un token Gitea (Paramètres → Applications → Générer un nouveau jeton, scope `repo`), passé uniquement en variable d'environnement — jamais commité.
## 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.