diff --git a/pom.xml b/pom.xml index 839051c..ca6490a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ fr.votenetwork votenetwork-parent - 1.0.0 + 1.0.1 pom diff --git a/spigot/pom.xml b/spigot/pom.xml index 0a84672..f7e5135 100644 --- a/spigot/pom.xml +++ b/spigot/pom.xml @@ -7,7 +7,7 @@ fr.votenetwork votenetwork-parent - 1.0.0 + 1.0.1 votenetwork-spigot diff --git a/spigot/src/main/java/fr/votenetwork/spigot/VoteConfig.java b/spigot/src/main/java/fr/votenetwork/spigot/VoteConfig.java index 0914bd1..39e1d83 100644 --- a/spigot/src/main/java/fr/votenetwork/spigot/VoteConfig.java +++ b/spigot/src/main/java/fr/votenetwork/spigot/VoteConfig.java @@ -1,9 +1,14 @@ package fr.votenetwork.spigot; +import fr.votenetwork.spigot.gui.VoteSite; import org.bukkit.ChatColor; +import org.bukkit.Material; import org.bukkit.configuration.file.FileConfiguration; +import java.util.ArrayList; import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.stream.Collectors; public class VoteConfig { @@ -141,6 +146,57 @@ public class VoteConfig { "&cVous n'avez pas la permission d'utiliser cette commande.")); } + public String getGuiTitle() { + return colorize(cfg().getString("gui.title", "&8VoteNetwork")); + } + + public String getGuiProgressItemMaterial() { + return cfg().getString("gui.progress-item.material", "NETHER_STAR"); + } + + public String getGuiProgressItemName() { + return colorize(cfg().getString("gui.progress-item.name", "&b&lVoteParty")); + } + + public List getGuiProgressItemLore() { + return colorizeList(cfg().getStringList("gui.progress-item.lore")); + } + + public String getGuiClickMessage() { + return colorize(cfg().getString("gui.click-message", "&a[Vote] Clique sur le lien pour voter :")); + } + + /** + * Parses gui.vote-sites (a YAML list of maps: name/material/url/lore) into VoteSite + * objects, one item per configured vote site. + */ + public List getVoteSites() { + List sites = new ArrayList<>(); + for (Map raw : cfg().getMapList("gui.vote-sites")) { + String name = raw.containsKey("name") ? String.valueOf(raw.get("name")) : "&aVoter"; + String materialName = raw.containsKey("material") ? String.valueOf(raw.get("material")) : "PAPER"; + String url = raw.containsKey("url") ? String.valueOf(raw.get("url")) : ""; + + List lore = new ArrayList<>(); + Object loreObj = raw.get("lore"); + if (loreObj instanceof List loreList) { + for (Object line : loreList) { + lore.add(String.valueOf(line)); + } + } + + Material material; + try { + material = Material.valueOf(materialName.toUpperCase(Locale.ROOT)); + } catch (IllegalArgumentException e) { + material = Material.PAPER; + } + + sites.add(new VoteSite(colorize(name), material, url, colorizeList(lore))); + } + return sites; + } + private String colorize(String input) { return input == null ? "" : ChatColor.translateAlternateColorCodes('&', input); } diff --git a/spigot/src/main/java/fr/votenetwork/spigot/VoteNetworkSpigot.java b/spigot/src/main/java/fr/votenetwork/spigot/VoteNetworkSpigot.java index f24e99b..1b76606 100644 --- a/spigot/src/main/java/fr/votenetwork/spigot/VoteNetworkSpigot.java +++ b/spigot/src/main/java/fr/votenetwork/spigot/VoteNetworkSpigot.java @@ -5,6 +5,8 @@ import fr.votenetwork.spigot.api.VoteNetworkAPIHolder; 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.gui.VotePartyGuiListener; import fr.votenetwork.spigot.listener.VoteMessageListener; import fr.votenetwork.spigot.placeholder.VoteNetworkPlaceholders; import fr.votenetwork.spigot.storage.MySqlPendingVoteStore; @@ -55,6 +57,8 @@ 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)); + getServer().getPluginManager().registerEvents(new VotePartyGuiListener(voteConfig), this); VoteNetworkAPI api = new VoteNetworkAPIImpl(this, voteConfig, pendingVoteStore, voteParty, maintenanceState); VoteNetworkAPIHolder.set(api); diff --git a/spigot/src/main/java/fr/votenetwork/spigot/command/VoteGuiCommand.java b/spigot/src/main/java/fr/votenetwork/spigot/command/VoteGuiCommand.java new file mode 100644 index 0000000..854c796 --- /dev/null +++ b/spigot/src/main/java/fr/votenetwork/spigot/command/VoteGuiCommand.java @@ -0,0 +1,31 @@ +package fr.votenetwork.spigot.command; + +import fr.votenetwork.spigot.VoteConfig; +import fr.votenetwork.spigot.gui.VotePartyGui; +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 VoteGuiCommand implements CommandExecutor { + + private final VoteConfig config; + private final VoteParty voteParty; + + public VoteGuiCommand(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; + } + VotePartyGui.open(player, config, voteParty); + return true; + } +} diff --git a/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGui.java b/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGui.java new file mode 100644 index 0000000..680de71 --- /dev/null +++ b/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGui.java @@ -0,0 +1,72 @@ +package fr.votenetwork.spigot.gui; + +import fr.votenetwork.spigot.VoteConfig; +import fr.votenetwork.spigot.voteparty.VoteParty; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; + +/** + * Builds and opens the VoteParty progress GUI: a progress item (slot 4) plus one item per + * configured vote site (starting at slot 9), each opening its URL when clicked. + */ +public final class VotePartyGui { + + public static final int PROGRESS_SLOT = 4; + public static final int SITES_START_SLOT = 9; + + private VotePartyGui() { + } + + public static void open(Player player, VoteConfig config, VoteParty voteParty) { + List sites = config.getVoteSites(); + int size = ((SITES_START_SLOT + sites.size() + 8) / 9) * 9; + size = Math.max(size, 18); + + VotePartyGuiHolder holder = new VotePartyGuiHolder(); + Inventory inventory = Bukkit.createInventory(holder, size, config.getGuiTitle()); + holder.setInventory(inventory); + + int required = config.getVotePartyVotesRequired(); + int current = Math.min(voteParty.getCurrentVotes(), required); + + ItemStack progressItem = new ItemStack(materialOrFallback(config.getGuiProgressItemMaterial())); + ItemMeta progressMeta = progressItem.getItemMeta(); + if (progressMeta != null) { + progressMeta.setDisplayName(config.getGuiProgressItemName()); + progressMeta.setLore(config.getGuiProgressItemLore().stream() + .map(line -> line.replace("%current%", String.valueOf(current)) + .replace("%required%", String.valueOf(required))) + .toList()); + progressItem.setItemMeta(progressMeta); + } + inventory.setItem(PROGRESS_SLOT, progressItem); + + int slot = SITES_START_SLOT; + for (VoteSite site : sites) { + ItemStack item = new ItemStack(site.getMaterial()); + ItemMeta meta = item.getItemMeta(); + if (meta != null) { + meta.setDisplayName(site.getName()); + meta.setLore(site.getLore()); + item.setItemMeta(meta); + } + inventory.setItem(slot, item); + slot++; + } + + player.openInventory(inventory); + } + + private static org.bukkit.Material materialOrFallback(String name) { + try { + return org.bukkit.Material.valueOf(name.toUpperCase(java.util.Locale.ROOT)); + } catch (IllegalArgumentException e) { + return org.bukkit.Material.NETHER_STAR; + } + } +} diff --git a/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGuiHolder.java b/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGuiHolder.java new file mode 100644 index 0000000..3109961 --- /dev/null +++ b/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGuiHolder.java @@ -0,0 +1,23 @@ +package fr.votenetwork.spigot.gui; + +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; + +/** + * Marker holder used to recognize our own GUI inventory in InventoryClickEvent, so the + * listener never touches clicks happening in unrelated inventories (chests, other plugins' + * GUIs, etc.). + */ +public class VotePartyGuiHolder implements InventoryHolder { + + private Inventory inventory; + + @Override + public Inventory getInventory() { + return inventory; + } + + public void setInventory(Inventory inventory) { + this.inventory = inventory; + } +} diff --git a/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGuiListener.java b/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGuiListener.java new file mode 100644 index 0000000..c7d5bef --- /dev/null +++ b/spigot/src/main/java/fr/votenetwork/spigot/gui/VotePartyGuiListener.java @@ -0,0 +1,53 @@ +package fr.votenetwork.spigot.gui; + +import fr.votenetwork.spigot.VoteConfig; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.List; + +/** + * Bukkit cannot open a browser directly from an inventory click, so a click on a vote-site + * item closes the GUI and sends a clickable chat message (ClickEvent OPEN_URL) instead. + */ +public class VotePartyGuiListener implements Listener { + + private final VoteConfig config; + + public VotePartyGuiListener(VoteConfig config) { + this.config = config; + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (!(event.getInventory().getHolder() instanceof VotePartyGuiHolder)) { + return; + } + event.setCancelled(true); + + int slot = event.getRawSlot(); + if (slot < VotePartyGui.SITES_START_SLOT || !(event.getWhoClicked() instanceof Player player)) { + return; + } + + List sites = config.getVoteSites(); + int index = slot - VotePartyGui.SITES_START_SLOT; + if (index < 0 || index >= sites.size()) { + return; + } + + VoteSite site = sites.get(index); + if (site.getUrl() == null || site.getUrl().isEmpty()) { + return; + } + + player.closeInventory(); + TextComponent message = new TextComponent(config.getGuiClickMessage() + " " + site.getUrl()); + message.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, site.getUrl())); + player.spigot().sendMessage(message); + } +} diff --git a/spigot/src/main/java/fr/votenetwork/spigot/gui/VoteSite.java b/spigot/src/main/java/fr/votenetwork/spigot/gui/VoteSite.java new file mode 100644 index 0000000..d1fa954 --- /dev/null +++ b/spigot/src/main/java/fr/votenetwork/spigot/gui/VoteSite.java @@ -0,0 +1,40 @@ +package fr.votenetwork.spigot.gui; + +import org.bukkit.Material; + +import java.util.List; + +/** + * A single vote-site entry configured in config.yml (gui.vote-sites): the display item and + * the URL opened (via a clickable chat message) when the player clicks it in the GUI. + */ +public class VoteSite { + + private final String name; + private final Material material; + private final String url; + private final List lore; + + public VoteSite(String name, Material material, String url, List lore) { + this.name = name; + this.material = material; + this.url = url; + this.lore = lore; + } + + public String getName() { + return name; + } + + public Material getMaterial() { + return material; + } + + public String getUrl() { + return url; + } + + public List getLore() { + return lore; + } +} diff --git a/spigot/src/main/resources/config.yml b/spigot/src/main/resources/config.yml index c600160..38ee5d1 100644 --- a/spigot/src/main/resources/config.yml +++ b/spigot/src/main/resources/config.yml @@ -47,6 +47,30 @@ voteparty: progress-message: "&b[Vote] &f%current%&7/&f%required% &fvotes avant le prochain VoteParty !" triggered-message: "&a[Vote] &fVoteParty declenche ! Profitez des recompenses !" +# GUI /votegui : affiche la progression du VoteParty et des items cliquables vers les sites +# de vote (ouvre le lien via un message chat cliquable, Bukkit ne peut pas ouvrir un navigateur +# directement depuis un clic d'inventaire). +gui: + title: "&8VoteNetwork" + progress-item: + material: NETHER_STAR + name: "&b&lVoteParty" + lore: + - "&7Progression actuelle :" + - "&f%current%&7/&f%required% &7votes" + click-message: "&a[Vote] Clique sur le lien pour voter :" + vote-sites: + - name: "&aVoter sur le site 1" + material: PAPER + url: "https://example.com/vote/site1" + lore: + - "&7Clique pour voter !" + - name: "&aVoter sur le site 2" + material: BOOK + url: "https://example.com/vote/site2" + lore: + - "&7Clique pour voter !" + messages: direct-vote: "&a[Vote] &fMerci pour ton vote !" claim-success: "&a[Vote] &fVous avez recupere &e%amount% &fvote(s) en attente !" diff --git a/spigot/src/main/resources/plugin.yml b/spigot/src/main/resources/plugin.yml index 9031b9a..aaa65ab 100644 --- a/spigot/src/main/resources/plugin.yml +++ b/spigot/src/main/resources/plugin.yml @@ -14,6 +14,9 @@ commands: description: Administration du systeme de vote (maintenance, test du stockage). usage: /vote permission: votenetwork.admin + votegui: + description: Ouvre le GUI de progression du VoteParty avec les liens de vote. + usage: /votegui permissions: votenetwork.admin: diff --git a/velocity/pom.xml b/velocity/pom.xml index 0c50857..c858217 100644 --- a/velocity/pom.xml +++ b/velocity/pom.xml @@ -7,7 +7,7 @@ fr.votenetwork votenetwork-parent - 1.0.0 + 1.0.1 votenetwork-velocity diff --git a/velocity/src/main/java/fr/votenetwork/velocity/VoteNetworkVelocity.java b/velocity/src/main/java/fr/votenetwork/velocity/VoteNetworkVelocity.java index d507155..a2dc281 100644 --- a/velocity/src/main/java/fr/votenetwork/velocity/VoteNetworkVelocity.java +++ b/velocity/src/main/java/fr/votenetwork/velocity/VoteNetworkVelocity.java @@ -14,7 +14,7 @@ import java.nio.file.Path; @Plugin( id = "votenetwork", name = "VoteNetwork", - version = "1.0.0", + version = "1.0.1", description = "Systeme de vote reseau Velocity <-> Spigot", authors = {"Sar_Tron"} )