Compare commits
2
Commits
a47376db3a
...
a76c641b7d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a76c641b7d | ||
|
|
ffbeb2de66 |
@@ -32,6 +32,8 @@ Compatible **Java 17**, compile contre l'API Spigot **1.18.2** (additive, donc c
|
|||||||
- Serveur : `plugins/votenetwork/config.yml`
|
- Serveur : `plugins/votenetwork/config.yml`
|
||||||
4. Redémarrer.
|
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
|
## Build depuis les sources
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -97,10 +99,10 @@ messages:
|
|||||||
|
|
||||||
## Stockage : MySQL ou YAML
|
## Stockage : MySQL ou YAML
|
||||||
|
|
||||||
Chaque composant choisit indépendamment son stockage via `storage.type` :
|
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é pour un vrai réseau) : partagé entre le proxy et tous les serveurs. La table `nb_votes_attente` est créée automatiquement au démarrage si absente.
|
- **`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 du plugin. Pratique en solo/test, **mais pas synchronisé automatiquement** entre le fichier du proxy et celui d'un serveur — chacun a sa propre copie locale. N'utilisez ce mode en réseau multi-machines que si les dossiers de plugins sont partagés sur le même disque (montage réseau, symlink). Sinon, un vote stocké côté proxy en YAML ne sera jamais vu par `/claim` sur un serveur Spigot séparé.
|
- **`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 :
|
Testez la connexion/l'accès au stockage configuré côté Spigot avec :
|
||||||
|
|
||||||
@@ -129,7 +131,7 @@ Testez la connexion/l'accès au stockage configuré côté Spigot avec :
|
|||||||
|
|
||||||
## VoteParty
|
## VoteParty
|
||||||
|
|
||||||
- Compteur indépendant **par serveur**, persistant localement (`plugins/votenetwork/voteparty.yml`), survit aux redémarrages.
|
- 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.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).
|
- `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`).
|
- Messages de progression et de déclenchement personnalisables (`voteparty.broadcast`).
|
||||||
@@ -174,3 +176,4 @@ CREATE TABLE IF NOT EXISTS nb_votes_attente (
|
|||||||
- 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.
|
- 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.
|
- 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.
|
- 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.
|
||||||
|
|||||||
@@ -10,9 +10,14 @@ import fr.votenetwork.spigot.storage.MySqlPendingVoteStore;
|
|||||||
import fr.votenetwork.spigot.storage.PendingVoteStore;
|
import fr.votenetwork.spigot.storage.PendingVoteStore;
|
||||||
import fr.votenetwork.spigot.storage.YamlPendingVoteStore;
|
import fr.votenetwork.spigot.storage.YamlPendingVoteStore;
|
||||||
import fr.votenetwork.spigot.voteparty.VoteParty;
|
import fr.votenetwork.spigot.voteparty.VoteParty;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.plugin.ServicePriority;
|
import org.bukkit.plugin.ServicePriority;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
public class VoteNetworkSpigot extends JavaPlugin {
|
public class VoteNetworkSpigot extends JavaPlugin {
|
||||||
|
|
||||||
public static final String CHANNEL = "votenetwork:vote";
|
public static final String CHANNEL = "votenetwork:vote";
|
||||||
@@ -25,6 +30,7 @@ public class VoteNetworkSpigot extends JavaPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
saveDefaultConfig();
|
saveDefaultConfig();
|
||||||
|
mergeMissingConfigKeys();
|
||||||
|
|
||||||
this.voteConfig = new VoteConfig(this);
|
this.voteConfig = new VoteConfig(this);
|
||||||
this.maintenanceState = new MaintenanceState();
|
this.maintenanceState = new MaintenanceState();
|
||||||
@@ -55,6 +61,43 @@ public class VoteNetworkSpigot extends JavaPlugin {
|
|||||||
getLogger().info("VoteNetwork (Spigot) demarre.");
|
getLogger().info("VoteNetwork (Spigot) demarre.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajoute dans config.yml les cles presentes dans le config.yml embarque dans le jar mais
|
||||||
|
* absentes du fichier existant (nouvelles options apportees par une mise a jour du plugin),
|
||||||
|
* sans jamais modifier une valeur deja definie par l'admin.
|
||||||
|
*
|
||||||
|
* Limite connue : Bukkit ne preserve pas les commentaires lors de la reecriture du fichier.
|
||||||
|
*/
|
||||||
|
private void mergeMissingConfigKeys() {
|
||||||
|
try (InputStreamReader reader = new InputStreamReader(getResource("config.yml"), StandardCharsets.UTF_8)) {
|
||||||
|
YamlConfiguration defaults = YamlConfiguration.loadConfiguration(reader);
|
||||||
|
YamlConfiguration current = YamlConfiguration.loadConfiguration(getConfigFile());
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
for (String key : defaults.getKeys(true)) {
|
||||||
|
if (defaults.isConfigurationSection(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!current.isSet(key)) {
|
||||||
|
current.set(key, defaults.get(key));
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
current.save(getConfigFile());
|
||||||
|
reloadConfig();
|
||||||
|
getLogger().info("config.yml mis a jour avec les nouvelles options manquantes (valeurs existantes conservees).");
|
||||||
|
}
|
||||||
|
} catch (IOException | java.io.UncheckedIOException e) {
|
||||||
|
getLogger().warning("Impossible de fusionner les nouvelles options de config.yml : " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private java.io.File getConfigFile() {
|
||||||
|
return new java.io.File(getDataFolder(), "config.yml");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
getServer().getServicesManager().unregisterAll(this);
|
getServer().getServicesManager().unregisterAll(this);
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ public class VoteConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mergeMissingConfigKeys(configFile);
|
||||||
|
|
||||||
try (InputStream in = Files.newInputStream(configFile)) {
|
try (InputStream in = Files.newInputStream(configFile)) {
|
||||||
properties.load(in);
|
properties.load(in);
|
||||||
}
|
}
|
||||||
@@ -68,6 +70,42 @@ public class VoteConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ajoute a la fin de config.properties les cles presentes dans le fichier par defaut du jar
|
||||||
|
* mais absentes du fichier existant (nouvelles options apportees par une mise a jour du
|
||||||
|
* plugin), sans jamais toucher aux lignes/valeurs deja presentes. Preserve donc aussi les
|
||||||
|
* commentaires existants (simple ajout de lignes, pas de reecriture complete).
|
||||||
|
*/
|
||||||
|
private void mergeMissingConfigKeys(Path configFile) throws IOException {
|
||||||
|
Properties defaults = new Properties();
|
||||||
|
try (InputStream in = getClass().getClassLoader().getResourceAsStream("config.properties")) {
|
||||||
|
if (in == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
defaults.load(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
Properties existing = new Properties();
|
||||||
|
try (InputStream in = Files.newInputStream(configFile)) {
|
||||||
|
existing.load(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder toAppend = new StringBuilder();
|
||||||
|
for (String key : defaults.stringPropertyNames()) {
|
||||||
|
if (!existing.containsKey(key)) {
|
||||||
|
toAppend.append(key).append('=').append(defaults.getProperty(key)).append(System.lineSeparator());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toAppend.length() > 0) {
|
||||||
|
String addition = System.lineSeparator()
|
||||||
|
+ "# --- options ajoutees automatiquement par une mise a jour du plugin ---" + System.lineSeparator()
|
||||||
|
+ toAppend;
|
||||||
|
Files.writeString(configFile, addition, java.nio.file.StandardOpenOption.APPEND);
|
||||||
|
logger.info("config.properties mis a jour avec les nouvelles options manquantes (valeurs existantes conservees).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMysqlStorage() {
|
public boolean isMysqlStorage() {
|
||||||
return !"yaml".equalsIgnoreCase(storageType);
|
return !"yaml".equalsIgnoreCase(storageType);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user