4 Commits
Author SHA1 Message Date
SarTron-NorthBlueandClaude Sonnet 5 6b20a6e342 Ajoute voteparty.broadcast.every pour limiter le spam de progression
CI / build (push) Successful in 12m14s
Le message de progression VoteParty s'affichait a chaque vote. Ajoute
une option every (defaut 10) pour n'annoncer que tous les N votes, plus
systematiquement au dernier vote avant le declenchement.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 17:26:13 +04:00
SarTron-NorthBlueandClaude Sonnet 5 cdc692d6d2 Fix : %player% jamais remplace dans les commandes VoteParty
CI / build (push) Successful in 12m41s
Les commandes voteparty.commands s'executaient une seule fois cote
console sans substitution de %player%, ce qui envoyait le placeholder
brut aux plugins de recompense (ex. "excellentcrates key give %player%
epic 5" -> "Joueur introuvable"). Les commandes contenant %player% sont
maintenant executees une fois par joueur en ligne ; les commandes sans
placeholder (deja globales, ex. "goldencrates broadcast_give ...")
gardent leur comportement precedent.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 17:23:46 +04:00
SarTron-NorthBlueandClaude Sonnet 5 0a470339f4 chore: push de test pour verifier le webhook Discord
CI / build (push) Successful in 12m5s
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-16 08:23:52 +04:00
SarTron-NorthBlueandClaude Sonnet 5 4aa1a25c54 Ajoute le menu principal /votemenu (profil, reclamation, administration) - v1.0.2
CI / build (push) Successful in 11m50s
Trois nouveaux ecrans GUI navigables depuis /votemenu :
- Menu principal : tete du joueur + progression VoteParty, boutons vers
  le menu de vote, la reclamation et (ops) l'administration.
- Menu de reclamation : equivalent visuel de /claim, affiche le nombre
  de votes en attente (resolu en async) et permet de les reclamer d'un clic.
- Menu d'administration (permission votenetwork.admin) : bascule le mode
  maintenance sans passer par la commande texte.

Extraction de la logique de reclamation dans ClaimAction, partagee entre
/claim et le menu visuel.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 13:50:43 +04:00
19 changed files with 636 additions and 43 deletions
+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>fr.votenetwork</groupId>
<artifactId>votenetwork-parent</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
<packaging>pom</packaging>
<modules>
+1 -1
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>fr.votenetwork</groupId>
<artifactId>votenetwork-parent</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
</parent>
<artifactId>votenetwork-spigot</artifactId>
@@ -0,0 +1,54 @@
package fr.votenetwork.spigot;
import fr.votenetwork.spigot.storage.PendingVoteStore;
import fr.votenetwork.spigot.voteparty.VoteParty;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
/**
* Reclame les votes en attente d'un joueur et distribue les recompenses. Partagee entre la
* commande /claim (texte) et le menu de reclamation visuel (/votemenu).
*/
public final class ClaimAction {
private ClaimAction() {
}
public static void claim(VoteNetworkSpigot plugin, VoteConfig config, PendingVoteStore pendingVoteStore,
VoteParty voteParty, Player player) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () ->
pendingVoteStore.fetchAndClear(
player.getUniqueId(),
pendingVotes -> Bukkit.getScheduler().runTask(plugin, () -> apply(plugin, config, voteParty, player, pendingVotes)),
exception -> Bukkit.getScheduler().runTask(plugin, () -> {
plugin.getLogger().severe("Erreur reclamation pour " + player.getName() + ": " + exception.getMessage());
player.sendMessage(config.getMessageMaintenance());
})
)
);
}
private static void apply(VoteNetworkSpigot plugin, VoteConfig config, VoteParty voteParty, Player player, int pendingVotes) {
if (pendingVotes <= 0) {
player.sendMessage(config.getMessageClaimEmpty());
return;
}
for (int i = 0; i < pendingVotes; i++) {
for (String cmd : config.getVoteRewardCommands()) {
String parsed = cmd.replace("%player%", player.getName());
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), parsed);
}
}
voteParty.addVotes(pendingVotes);
player.sendMessage(config.getMessageClaimSuccess().replace("%amount%", String.valueOf(pendingVotes)));
if (config.isVoteBroadcastEnabled()) {
Bukkit.broadcastMessage(config.getVoteBroadcastMessage()
.replace("%player%", player.getName())
.replace("%amount%", String.valueOf(pendingVotes)));
}
}
}
@@ -92,6 +92,11 @@ public class VoteConfig {
return cfg().getBoolean("voteparty.broadcast.enabled", true);
}
/** N'annonce la progression que tous les N votes (1 = a chaque vote). */
public int getVotePartyBroadcastEvery() {
return cfg().getInt("voteparty.broadcast.every", 10);
}
public String getVotePartyProgressMessage() {
return colorize(cfg().getString("voteparty.broadcast.progress-message",
"&b[Vote] &f%current%&7/&f%required% &fvotes avant le prochain VoteParty !"));
@@ -197,6 +202,108 @@ public class VoteConfig {
return sites;
}
// --- Menu principal (/votemenu) ---
public String getMainMenuTitle() {
return colorize(cfg().getString("gui.main-menu.title", "&8VoteNetwork - Menu"));
}
public List<String> getMainMenuHeadLore() {
return colorizeList(cfg().getStringList("gui.main-menu.head-lore"));
}
public String getMainMenuVoteItemMaterial() {
return cfg().getString("gui.main-menu.vote-item.material", "PAPER");
}
public String getMainMenuVoteItemName() {
return colorize(cfg().getString("gui.main-menu.vote-item.name", "&aVoter"));
}
public List<String> getMainMenuVoteItemLore() {
return colorizeList(cfg().getStringList("gui.main-menu.vote-item.lore"));
}
public String getMainMenuClaimItemMaterial() {
return cfg().getString("gui.main-menu.claim-item.material", "CHEST");
}
public String getMainMenuClaimItemName() {
return colorize(cfg().getString("gui.main-menu.claim-item.name", "&eMes votes en attente"));
}
public List<String> getMainMenuClaimItemLore() {
return colorizeList(cfg().getStringList("gui.main-menu.claim-item.lore"));
}
public String getMainMenuAdminItemMaterial() {
return cfg().getString("gui.main-menu.admin-item.material", "REDSTONE");
}
public String getMainMenuAdminItemName() {
return colorize(cfg().getString("gui.main-menu.admin-item.name", "&cAdministration"));
}
public List<String> getMainMenuAdminItemLore() {
return colorizeList(cfg().getStringList("gui.main-menu.admin-item.lore"));
}
// --- Menu de reclamation (/claim visuel) ---
public String getClaimMenuTitle() {
return colorize(cfg().getString("gui.claim-menu.title", "&8VoteNetwork - Reclamer"));
}
public String getClaimMenuLoadingLore() {
return colorize(cfg().getString("gui.claim-menu.loading-lore", "&7Chargement..."));
}
public String getClaimMenuAvailableMaterial() {
return cfg().getString("gui.claim-menu.available.material", "CHEST");
}
public String getClaimMenuAvailableName() {
return colorize(cfg().getString("gui.claim-menu.available.name", "&e%amount% vote(s) en attente"));
}
public List<String> getClaimMenuAvailableLore() {
return colorizeList(cfg().getStringList("gui.claim-menu.available.lore"));
}
public String getClaimMenuEmptyMaterial() {
return cfg().getString("gui.claim-menu.empty.material", "BARRIER");
}
public String getClaimMenuEmptyName() {
return colorize(cfg().getString("gui.claim-menu.empty.name", "&7Aucun vote en attente"));
}
public List<String> getClaimMenuEmptyLore() {
return colorizeList(cfg().getStringList("gui.claim-menu.empty.lore"));
}
// --- Menu d'administration (/votemenu, reserve aux ops) ---
public String getAdminMenuTitle() {
return colorize(cfg().getString("gui.admin-menu.title", "&8VoteNetwork - Administration"));
}
public String getAdminMenuItemMaterial() {
return cfg().getString("gui.admin-menu.item.material", "LEVER");
}
public String getAdminMenuItemNameEnabled() {
return colorize(cfg().getString("gui.admin-menu.item.name-maintenance-on", "&c&lMaintenance : ACTIVEE"));
}
public String getAdminMenuItemNameDisabled() {
return colorize(cfg().getString("gui.admin-menu.item.name-maintenance-off", "&a&lMaintenance : DESACTIVEE"));
}
public List<String> getAdminMenuItemLore() {
return colorizeList(cfg().getStringList("gui.admin-menu.item.lore"));
}
private String colorize(String input) {
return input == null ? "" : ChatColor.translateAlternateColorCodes('&', input);
}
@@ -6,6 +6,8 @@ import fr.votenetwork.spigot.api.VoteNetworkAPIImpl;
import fr.votenetwork.spigot.command.ClaimCommand;
import fr.votenetwork.spigot.command.VoteAdminCommand;
import fr.votenetwork.spigot.command.VoteGuiCommand;
import fr.votenetwork.spigot.command.VoteMenuCommand;
import fr.votenetwork.spigot.gui.VoteMenuListener;
import fr.votenetwork.spigot.gui.VotePartyGuiListener;
import fr.votenetwork.spigot.listener.VoteMessageListener;
import fr.votenetwork.spigot.placeholder.VoteNetworkPlaceholders;
@@ -58,7 +60,10 @@ public class VoteNetworkSpigot extends JavaPlugin {
getCommand("claim").setExecutor(new ClaimCommand(this, voteConfig, pendingVoteStore, voteParty, maintenanceState));
getCommand("vote").setExecutor(new VoteAdminCommand(this, voteConfig, pendingVoteStore, maintenanceState));
getCommand("votegui").setExecutor(new VoteGuiCommand(voteConfig, voteParty));
getCommand("votemenu").setExecutor(new VoteMenuCommand(voteConfig, voteParty));
getServer().getPluginManager().registerEvents(new VotePartyGuiListener(voteConfig), this);
getServer().getPluginManager().registerEvents(
new VoteMenuListener(this, voteConfig, pendingVoteStore, voteParty, maintenanceState), this);
VoteNetworkAPI api = new VoteNetworkAPIImpl(this, voteConfig, pendingVoteStore, voteParty, maintenanceState);
VoteNetworkAPIHolder.set(api);
@@ -1,11 +1,11 @@
package fr.votenetwork.spigot.command;
import fr.votenetwork.spigot.ClaimAction;
import fr.votenetwork.spigot.MaintenanceState;
import fr.votenetwork.spigot.VoteNetworkSpigot;
import fr.votenetwork.spigot.VoteConfig;
import fr.votenetwork.spigot.storage.PendingVoteStore;
import fr.votenetwork.spigot.voteparty.VoteParty;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@@ -42,41 +42,7 @@ public class ClaimCommand implements CommandExecutor {
return true;
}
Bukkit.getScheduler().runTaskAsynchronously(plugin, () ->
pendingVoteStore.fetchAndClear(
player.getUniqueId(),
pendingVotes -> Bukkit.getScheduler().runTask(plugin, () -> applyClaim(player, pendingVotes)),
exception -> Bukkit.getScheduler().runTask(plugin, () -> {
plugin.getLogger().severe("Erreur /claim pour " + player.getName() + ": " + exception.getMessage());
player.sendMessage(config.getMessageMaintenance());
})
)
);
ClaimAction.claim(plugin, config, pendingVoteStore, voteParty, player);
return true;
}
private void applyClaim(Player player, int pendingVotes) {
if (pendingVotes <= 0) {
player.sendMessage(config.getMessageClaimEmpty());
return;
}
for (int i = 0; i < pendingVotes; i++) {
for (String cmd : config.getVoteRewardCommands()) {
String parsed = cmd.replace("%player%", player.getName());
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), parsed);
}
}
voteParty.addVotes(pendingVotes);
player.sendMessage(config.getMessageClaimSuccess().replace("%amount%", String.valueOf(pendingVotes)));
if (config.isVoteBroadcastEnabled()) {
Bukkit.broadcastMessage(config.getVoteBroadcastMessage()
.replace("%player%", player.getName())
.replace("%amount%", String.valueOf(pendingVotes)));
}
}
}
@@ -0,0 +1,31 @@
package fr.votenetwork.spigot.command;
import fr.votenetwork.spigot.VoteConfig;
import fr.votenetwork.spigot.gui.MainMenuGui;
import fr.votenetwork.spigot.voteparty.VoteParty;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class VoteMenuCommand implements CommandExecutor {
private final VoteConfig config;
private final VoteParty voteParty;
public VoteMenuCommand(VoteConfig config, VoteParty voteParty) {
this.config = config;
this.voteParty = voteParty;
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(ChatColor.RED + "Commande reservee aux joueurs.");
return true;
}
MainMenuGui.open(player, config, voteParty);
return true;
}
}
@@ -0,0 +1,47 @@
package fr.votenetwork.spigot.gui;
import fr.votenetwork.spigot.MaintenanceState;
import fr.votenetwork.spigot.VoteConfig;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Locale;
/** Ops-only screen (permission votenetwork.admin) to toggle maintenance mode with one click. */
public final class AdminMenuGui {
private AdminMenuGui() {
}
public static void open(Player player, VoteConfig config, MaintenanceState maintenanceState) {
AdminMenuHolder holder = new AdminMenuHolder();
Inventory inventory = Bukkit.createInventory(holder, 27, config.getAdminMenuTitle());
holder.setInventory(inventory);
inventory.setItem(AdminMenuHolder.ITEM_SLOT, buildItem(config, maintenanceState.isStopped()));
player.openInventory(inventory);
}
public static ItemStack buildItem(VoteConfig config, boolean stopped) {
Material material;
try {
material = Material.valueOf(config.getAdminMenuItemMaterial().toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
material = Material.LEVER;
}
ItemStack item = new ItemStack(material);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(stopped ? config.getAdminMenuItemNameEnabled() : config.getAdminMenuItemNameDisabled());
meta.setLore(config.getAdminMenuItemLore());
item.setItemMeta(meta);
}
return item;
}
}
@@ -0,0 +1,21 @@
package fr.votenetwork.spigot.gui;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/** Marker holder for the ops-only administration screen (toggle maintenance mode). */
public class AdminMenuHolder implements InventoryHolder {
public static final int ITEM_SLOT = 13;
private Inventory inventory;
@Override
public Inventory getInventory() {
return inventory;
}
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
}
@@ -0,0 +1,80 @@
package fr.votenetwork.spigot.gui;
import fr.votenetwork.spigot.VoteConfig;
import fr.votenetwork.spigot.VoteNetworkSpigot;
import fr.votenetwork.spigot.storage.PendingVoteStore;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Locale;
/**
* Visual counterpart of /claim: shows how many votes are waiting for the player, resolved
* asynchronously via {@link PendingVoteStore#peek}, and lets them claim by clicking the item.
*/
public final class ClaimMenuGui {
private ClaimMenuGui() {
}
public static void open(Player player, VoteNetworkSpigot plugin, VoteConfig config, PendingVoteStore pendingVoteStore) {
ClaimMenuHolder holder = new ClaimMenuHolder();
Inventory inventory = Bukkit.createInventory(holder, 27, config.getClaimMenuTitle());
holder.setInventory(inventory);
ItemStack loading = new ItemStack(Material.CLOCK);
ItemMeta loadingMeta = loading.getItemMeta();
if (loadingMeta != null) {
loadingMeta.setDisplayName(config.getClaimMenuLoadingLore());
loading.setItemMeta(loadingMeta);
}
inventory.setItem(ClaimMenuHolder.ITEM_SLOT, loading);
player.openInventory(inventory);
Bukkit.getScheduler().runTaskAsynchronously(plugin, () ->
pendingVoteStore.peek(
player.getUniqueId(),
amount -> Bukkit.getScheduler().runTask(plugin, () -> {
holder.setPendingVotes(amount);
if (player.getOpenInventory().getTopInventory().getHolder() == holder) {
inventory.setItem(ClaimMenuHolder.ITEM_SLOT, buildItem(config, amount));
}
}),
exception -> Bukkit.getScheduler().runTask(plugin, () -> {
plugin.getLogger().severe("Erreur menu reclamation pour " + player.getName() + ": " + exception.getMessage());
player.closeInventory();
})
)
);
}
public static ItemStack buildItem(VoteConfig config, int amount) {
boolean available = amount > 0;
String materialName = available ? config.getClaimMenuAvailableMaterial() : config.getClaimMenuEmptyMaterial();
String name = available
? config.getClaimMenuAvailableName().replace("%amount%", String.valueOf(amount))
: config.getClaimMenuEmptyName();
java.util.List<String> lore = available ? config.getClaimMenuAvailableLore() : config.getClaimMenuEmptyLore();
Material material;
try {
material = Material.valueOf(materialName.toUpperCase(Locale.ROOT));
} catch (IllegalArgumentException e) {
material = Material.CHEST;
}
ItemStack item = new ItemStack(material);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
meta.setLore(lore);
item.setItemMeta(meta);
}
return item;
}
}
@@ -0,0 +1,31 @@
package fr.votenetwork.spigot.gui;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/** Marker holder for the visual /claim screen opened from the main menu. */
public class ClaimMenuHolder implements InventoryHolder {
public static final int ITEM_SLOT = 13;
private Inventory inventory;
private volatile int pendingVotes = -1;
@Override
public Inventory getInventory() {
return inventory;
}
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
/** -1 while the async lookup is still pending, >= 0 once resolved. */
public int getPendingVotes() {
return pendingVotes;
}
public void setPendingVotes(int pendingVotes) {
this.pendingVotes = pendingVotes;
}
}
@@ -0,0 +1,74 @@
package fr.votenetwork.spigot.gui;
import fr.votenetwork.spigot.VoteConfig;
import fr.votenetwork.spigot.voteparty.VoteParty;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.SkullMeta;
/**
* /votemenu entry point: player head with VoteParty progress, plus navigation to the vote-site
* links (/votegui), the visual claim menu, and (ops only) the administration menu.
*/
public final class MainMenuGui {
private MainMenuGui() {
}
public static void open(Player player, VoteConfig config, VoteParty voteParty) {
MainMenuHolder holder = new MainMenuHolder();
Inventory inventory = Bukkit.createInventory(holder, 27, config.getMainMenuTitle());
holder.setInventory(inventory);
int required = config.getVotePartyVotesRequired();
int current = Math.min(voteParty.getCurrentVotes(), required);
ItemStack head = new ItemStack(Material.PLAYER_HEAD);
SkullMeta skullMeta = (SkullMeta) head.getItemMeta();
if (skullMeta != null) {
skullMeta.setOwningPlayer(player);
skullMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', "&b&l" + player.getName()));
skullMeta.setLore(config.getMainMenuHeadLore().stream()
.map(line -> line.replace("%player%", player.getName())
.replace("%current%", String.valueOf(current))
.replace("%required%", String.valueOf(required)))
.toList());
head.setItemMeta(skullMeta);
}
inventory.setItem(4, head);
inventory.setItem(MainMenuHolder.VOTE_SLOT, buildItem(
config.getMainMenuVoteItemMaterial(), config.getMainMenuVoteItemName(), config.getMainMenuVoteItemLore()));
inventory.setItem(MainMenuHolder.CLAIM_SLOT, buildItem(
config.getMainMenuClaimItemMaterial(), config.getMainMenuClaimItemName(), config.getMainMenuClaimItemLore()));
if (player.hasPermission("votenetwork.admin")) {
inventory.setItem(MainMenuHolder.ADMIN_SLOT, buildItem(
config.getMainMenuAdminItemMaterial(), config.getMainMenuAdminItemName(), config.getMainMenuAdminItemLore()));
}
player.openInventory(inventory);
}
private static ItemStack buildItem(String materialName, String name, java.util.List<String> lore) {
Material material;
try {
material = Material.valueOf(materialName.toUpperCase(java.util.Locale.ROOT));
} catch (IllegalArgumentException e) {
material = Material.PAPER;
}
ItemStack item = new ItemStack(material);
ItemMeta meta = item.getItemMeta();
if (meta != null) {
meta.setDisplayName(name);
meta.setLore(lore);
item.setItemMeta(meta);
}
return item;
}
}
@@ -0,0 +1,23 @@
package fr.votenetwork.spigot.gui;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
/** Marker holder for the /votemenu main screen. */
public class MainMenuHolder implements InventoryHolder {
public static final int VOTE_SLOT = 11;
public static final int CLAIM_SLOT = 13;
public static final int ADMIN_SLOT = 15;
private Inventory inventory;
@Override
public Inventory getInventory() {
return inventory;
}
public void setInventory(Inventory inventory) {
this.inventory = inventory;
}
}
@@ -0,0 +1,83 @@
package fr.votenetwork.spigot.gui;
import fr.votenetwork.spigot.ClaimAction;
import fr.votenetwork.spigot.MaintenanceState;
import fr.votenetwork.spigot.VoteConfig;
import fr.votenetwork.spigot.VoteNetworkSpigot;
import fr.votenetwork.spigot.storage.PendingVoteStore;
import fr.votenetwork.spigot.voteparty.VoteParty;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
/** Click handling for the main/claim/admin menus (/votemenu tree). */
public class VoteMenuListener implements Listener {
private final VoteNetworkSpigot plugin;
private final VoteConfig config;
private final PendingVoteStore pendingVoteStore;
private final VoteParty voteParty;
private final MaintenanceState maintenanceState;
public VoteMenuListener(VoteNetworkSpigot plugin, VoteConfig config, PendingVoteStore pendingVoteStore,
VoteParty voteParty, MaintenanceState maintenanceState) {
this.plugin = plugin;
this.config = config;
this.pendingVoteStore = pendingVoteStore;
this.voteParty = voteParty;
this.maintenanceState = maintenanceState;
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
Object rawHolder = event.getInventory().getHolder();
if (!(event.getWhoClicked() instanceof Player player)) {
return;
}
if (rawHolder instanceof MainMenuHolder) {
event.setCancelled(true);
handleMainMenuClick(player, event.getRawSlot());
} else if (rawHolder instanceof ClaimMenuHolder holder) {
event.setCancelled(true);
handleClaimMenuClick(player, holder, event.getRawSlot());
} else if (rawHolder instanceof AdminMenuHolder) {
event.setCancelled(true);
handleAdminMenuClick(player, event.getRawSlot());
}
}
private void handleMainMenuClick(Player player, int slot) {
if (slot == MainMenuHolder.VOTE_SLOT) {
VotePartyGui.open(player, config, voteParty);
} else if (slot == MainMenuHolder.CLAIM_SLOT) {
ClaimMenuGui.open(player, plugin, config, pendingVoteStore);
} else if (slot == MainMenuHolder.ADMIN_SLOT && player.hasPermission("votenetwork.admin")) {
AdminMenuGui.open(player, config, maintenanceState);
}
}
private void handleClaimMenuClick(Player player, ClaimMenuHolder holder, int slot) {
if (slot != ClaimMenuHolder.ITEM_SLOT || holder.getPendingVotes() < 0) {
return;
}
if (maintenanceState.isStopped()) {
player.closeInventory();
player.sendMessage(config.getMessageMaintenance());
return;
}
player.closeInventory();
ClaimAction.claim(plugin, config, pendingVoteStore, voteParty, player);
}
private void handleAdminMenuClick(Player player, int slot) {
if (slot != AdminMenuHolder.ITEM_SLOT || !player.hasPermission("votenetwork.admin")) {
return;
}
boolean newState = !maintenanceState.isStopped();
maintenanceState.setStopped(newState);
player.sendMessage(newState ? config.getMessageMaintenanceEnabled() : config.getMessageMaintenanceDisabled());
player.getOpenInventory().getTopInventory().setItem(AdminMenuHolder.ITEM_SLOT, AdminMenuGui.buildItem(config, newState));
}
}
@@ -47,10 +47,14 @@ public class VoteParty {
public void addVotes(int amount) {
int required = config.getVotePartyVotesRequired();
int updated = currentVotes.addAndGet(amount);
int shown = Math.min(updated, required);
if (config.isVotePartyBroadcastEnabled()) {
// N'annonce la progression que tous les N votes (config), plus le dernier avant le
// declenchement, pour eviter de spam le chat a chaque vote individuel.
int every = Math.max(1, config.getVotePartyBroadcastEvery());
if (config.isVotePartyBroadcastEnabled() && (shown % every == 0 || shown >= required)) {
Bukkit.broadcastMessage(config.getVotePartyProgressMessage()
.replace("%current%", String.valueOf(Math.min(updated, required)))
.replace("%current%", String.valueOf(shown))
.replace("%required%", String.valueOf(required)));
}
@@ -62,14 +66,25 @@ public class VoteParty {
save();
}
/**
* Commands without %player% run once (e.g. a crate plugin's own "give to everyone"
* command). Commands containing %player% are dispatched once per online player, since
* VoteParty rewards the whole server rather than a single voter.
*/
private void trigger() {
if (config.isVotePartyBroadcastEnabled()) {
Bukkit.broadcastMessage(config.getVotePartyTriggeredMessage());
}
for (String command : config.getVotePartyCommands()) {
if (command.contains("%player%")) {
for (org.bukkit.entity.Player player : Bukkit.getOnlinePlayers()) {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command.replace("%player%", player.getName()));
}
} else {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command);
}
}
}
public int getCurrentVotes() {
return currentVotes.get();
+53
View File
@@ -44,6 +44,10 @@ voteparty:
- "goldencrates broadcast_give vote_key 1"
broadcast:
enabled: true
# N'annonce la progression que tous les N votes (10 = 1 message toutes les 10 votes),
# plus systematiquement au dernier vote avant le declenchement. Mettre a 1 pour annoncer
# a chaque vote.
every: 10
progress-message: "&b[Vote] &f%current%&7/&f%required% &fvotes avant le prochain VoteParty !"
triggered-message: "&a[Vote] &fVoteParty declenche ! Profitez des recompenses !"
@@ -71,6 +75,55 @@ gui:
lore:
- "&7Clique pour voter !"
# Menu principal /votemenu : profil du joueur, progression VoteParty, et boutons de
# navigation vers le menu de vote (/votegui), de reclamation et (pour les ops) d'administration.
main-menu:
title: "&8VoteNetwork - Menu"
head-lore:
- "&7Joueur : &f%player%"
- "&7Progression VoteParty :"
- "&f%current%&7/&f%required% &7votes"
vote-item:
material: PAPER
name: "&aVoter"
lore:
- "&7Clique pour voir les liens de vote."
claim-item:
material: CHEST
name: "&eMes votes en attente"
lore:
- "&7Clique pour reclamer tes votes stockes."
admin-item:
material: REDSTONE
name: "&cAdministration"
lore:
- "&7Clique pour gerer le mode maintenance."
# Menu de reclamation visuel (equivalent GUI de /claim).
claim-menu:
title: "&8VoteNetwork - Reclamer"
loading-lore: "&7Chargement..."
available:
material: CHEST
name: "&e%amount% vote(s) en attente"
lore:
- "&7Clique pour reclamer !"
empty:
material: BARRIER
name: "&7Aucun vote en attente"
lore:
- "&7Reviens plus tard."
# Menu d'administration (reserve aux ops, permission votenetwork.admin).
admin-menu:
title: "&8VoteNetwork - Administration"
item:
material: LEVER
name-maintenance-on: "&c&lMaintenance : ACTIVEE"
name-maintenance-off: "&a&lMaintenance : DESACTIVEE"
lore:
- "&7Clique pour basculer le mode maintenance."
messages:
direct-vote: "&a[Vote] &fMerci pour ton vote !"
claim-success: "&a[Vote] &fVous avez recupere &e%amount% &fvote(s) en attente !"
+3
View File
@@ -17,6 +17,9 @@ commands:
votegui:
description: Ouvre le GUI de progression du VoteParty avec les liens de vote.
usage: /votegui
votemenu:
description: Ouvre le menu principal (profil, votes en attente, administration).
usage: /votemenu
permissions:
votenetwork.admin:
+1 -1
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>fr.votenetwork</groupId>
<artifactId>votenetwork-parent</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
</parent>
<artifactId>votenetwork-velocity</artifactId>
@@ -14,7 +14,7 @@ import java.nio.file.Path;
@Plugin(
id = "votenetwork",
name = "VoteNetwork",
version = "1.0.1",
version = "1.0.2",
description = "Systeme de vote reseau Velocity <-> Spigot",
authors = {"Sar_Tron"}
)