Ajoute la portee per-server pour les votes en attente + credits/licence

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>
This commit is contained in:
SarTron-NorthBlue
2026-07-12 14:33:22 +04:00
co-authored by Claude Sonnet 5
parent 74b2914529
commit 261e220d1a
11 changed files with 238 additions and 20 deletions
@@ -30,6 +30,15 @@ public class VoteConfig {
return !"yaml".equalsIgnoreCase(getStorageType());
}
/**
* Doit correspondre exactement a pending-votes.scope cote Velocity :
* global : /claim consomme le compteur partage entre tous les serveurs.
* per-server : /claim ne consomme que le compteur de CE serveur (server-name).
*/
public boolean isPerServerScope() {
return "per-server".equalsIgnoreCase(cfg().getString("storage.pending-votes-scope", "global"));
}
public String getMysqlHost() {
return cfg().getString("mysql.host", "127.0.0.1");
}
@@ -54,6 +63,14 @@ public class VoteConfig {
return cfg().getInt("mysql.pool-size", 5);
}
/**
* Nom de CE serveur, tel que declare cote Velocity dans direct-vote.servers.
* Uniquement necessaire si le proxy utilise pending-votes.scope=per-server.
*/
public String getServerName() {
return cfg().getString("server-name", "");
}
public List<String> getVoteRewardCommands() {
return cfg().getStringList("rewards.vote-commands");
}
@@ -73,16 +73,24 @@ public class MySqlPendingVoteStore implements PendingVoteStore {
}
private void createTableIfNotExists() {
String sql = "CREATE TABLE IF NOT EXISTS nb_votes_attente (" +
String globalSql = "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" +
")";
String perServerSql = "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)" +
")";
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute(sql);
statement.execute(globalSql);
statement.execute(perServerSql);
} catch (SQLException e) {
plugin.getLogger().severe("Impossible de creer la table nb_votes_attente: " + e.getMessage());
plugin.getLogger().severe("Impossible de creer les tables de votes en attente: " + e.getMessage());
}
}
@@ -92,6 +100,14 @@ public class MySqlPendingVoteStore implements PendingVoteStore {
onError.accept(new SQLException("Pool MySQL indisponible (echec de connexion au demarrage)"));
return;
}
if (config.isPerServerScope()) {
fetchAndClearPerServer(uuid, onResult, onError);
} else {
fetchAndClearGlobal(uuid, onResult, onError);
}
}
private void fetchAndClearGlobal(UUID uuid, IntConsumer onResult, Consumer<Exception> onError) {
String selectSql = "SELECT nombre_votes FROM nb_votes_attente WHERE player_uuid = ?";
String resetSql = "UPDATE nb_votes_attente SET nombre_votes = 0 WHERE player_uuid = ?";
@@ -120,16 +136,59 @@ public class MySqlPendingVoteStore implements PendingVoteStore {
}
}
private void fetchAndClearPerServer(UUID uuid, IntConsumer onResult, Consumer<Exception> onError) {
if (config.getServerName().isEmpty()) {
onError.accept(new SQLException("storage.pending-votes-scope=per-server mais server-name est vide dans config.yml"));
return;
}
String selectSql = "SELECT nombre_votes FROM nb_votes_attente_serveur WHERE player_uuid = ? AND server_name = ?";
String resetSql = "UPDATE nb_votes_attente_serveur SET nombre_votes = 0 WHERE player_uuid = ? AND server_name = ?";
try (Connection connection = dataSource.getConnection()) {
int pendingVotes = 0;
try (PreparedStatement select = connection.prepareStatement(selectSql)) {
select.setString(1, uuid.toString());
select.setString(2, config.getServerName());
try (ResultSet resultSet = select.executeQuery()) {
if (resultSet.next()) {
pendingVotes = resultSet.getInt("nombre_votes");
}
}
}
if (pendingVotes > 0) {
try (PreparedStatement reset = connection.prepareStatement(resetSql)) {
reset.setString(1, uuid.toString());
reset.setString(2, config.getServerName());
reset.executeUpdate();
}
}
onResult.accept(pendingVotes);
} catch (SQLException e) {
onError.accept(e);
}
}
@Override
public void peek(UUID uuid, IntConsumer onResult, Consumer<Exception> onError) {
if (!isConnected()) {
onError.accept(new SQLException("Pool MySQL indisponible (echec de connexion au demarrage)"));
return;
}
String sql = "SELECT nombre_votes FROM nb_votes_attente WHERE player_uuid = ?";
boolean perServer = config.isPerServerScope();
String sql = perServer
? "SELECT nombre_votes FROM nb_votes_attente_serveur WHERE player_uuid = ? AND server_name = ?"
: "SELECT nombre_votes FROM nb_votes_attente WHERE player_uuid = ?";
try (Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, uuid.toString());
if (perServer) {
statement.setString(2, config.getServerName());
}
try (ResultSet resultSet = statement.executeQuery()) {
onResult.accept(resultSet.next() ? resultSet.getInt("nombre_votes") : 0);
}
+8
View File
@@ -8,6 +8,14 @@
# partage automatiquement avec le fichier YAML du proxy Velocity si vous etes en reseau.
storage:
type: mysql
# Doit correspondre EXACTEMENT a pending-votes.scope cote Velocity (config.properties) :
# global (par defaut) : /claim consomme le compteur partage entre tous les serveurs.
# per-server : /claim ne consomme que le compteur de CE serveur (voir server-name ci-dessous).
pending-votes-scope: global
# Nom de CE serveur, IDENTIQUE a celui utilise dans direct-vote.servers cote Velocity.
# Uniquement necessaire si storage.pending-votes-scope=per-server.
server-name: ""
mysql:
host: 127.0.0.1
+1 -1
View File
@@ -2,7 +2,7 @@ name: votenetwork
main: fr.votenetwork.spigot.VoteNetworkSpigot
version: ${project.version}
api-version: 1.18
author: VoteNetwork
author: Sar_Tron
description: Reception des votes reseau (direct ou en attente) avec VoteParty local.
softdepend: [PlaceholderAPI]