diff --git a/.gitignore b/.gitignore index 8a0a60d..cd57bb0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,17 @@ -# Project exclude paths +# Gradle /.gradle/ /build/ -/build/classes/java/main/ \ No newline at end of file + +# IntelliJ IDEA +/.idea/ + +# Eclipse +/.classpath +/.project +/.settings/ + +# Compiled output +/bin/ + +# macOS +.DS_Store \ No newline at end of file diff --git a/README.md b/README.md index e90fbc2..d684bd1 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@

Randomized Minigames

- This spigot plugin adds a couple of Minigames to Minecraft all based on some sort of randomization. Currently working are two different types of Force Item Battles, a type of minigame where each player has to aquire an item faster than the others. + This spigot plugin adds a couple of Minigames to Minecraft all based on some sort of randomization. Currently working are five different Minigames, including three variants of Force Item Battle, a type of minigame where each player has to aquire an item faster than the others.
Explore the docs » There, sadly, are no docs yet.
@@ -39,7 +39,13 @@

  • Installation
  • -
  • Usage
  • +
  • + Usage + +
  • Roadmap
  • Contributing
  • License
  • @@ -77,13 +83,41 @@ As every Spigot Plugin `/minigames` - Opens a GUI of all available Minigames.
    `/minigames killall`- Kills all minigames currently running, will be removed in the future since it shouldn't be necessary
    +### Minigames + +| Name | Description | +|---|---| +| **Force Item Battle** | Each player is assigned a random item and has to obtain it first. Items are assigned individually, so everyone is hunting something different. | +| **Force Item Battle (Same Items)** | Same as above, but all players share the same target item at any given time. | +| **Force Item Battle (Teams)** | The team variant. Players are split into teams of 2–6, and teammates share a target item. First team to reach the win limit wins. | +| **Block Randomizer** | Block drops are randomized per player — breaking any block gives you a random item instead of the usual drop. | +| **Only Chests** | Mob drops and block drops are disabled. The only way to get items is from chests. | + +### Setup + +After selecting a minigame, you get a setup screen with the following options: + +- **Select Players** — pick who participates +- **Win Limit** — set the number of items a player (or team) needs to collect to win. Shows the current limit in green when active, red "Off" when disabled. +- **Timer** — set a time limit after which the game ends and the player with the highest score wins. Shows the remaining time in green when active, red "Off" when disabled. + +Win Limit and Timer are mutually exclusive — enabling one disables the other. + +For **Force Item Battle Teams**, there's an extra step before the setup screen where you choose the number of teams and assign players to each one. + +**After every minigame**, all players are restored to their pre-game state: inventory, armor, offhand, XP level, health, food, and position are all put back. There's a 10-second countdown on the action bar before the reset happens. + +If a player **disconnects mid-game**, they can rejoin and be put back into the running game with their score intact. If the game has already ended by the time they reconnect, their inventory is restored then instead. + +

    (back to top)

    + ## Roadmap -- [ ] Fully implementing Force-Item-Battle Team variant +- [x] Fully implementing Force-Item-Battle Team variant +- [x] Make the GUI easier to work with - [ ] Add another minigame, not sure which atm -- [ ] Make the GUI easier to work with - [ ] Adding usefull JavaDocs - [ ] probably other stuff I currently dont think about. @@ -127,4 +161,3 @@ Distributed under the GPL v3 License. See `LICENSE.md` for more information.

    (back to top)

    - diff --git a/gradle.properties b/gradle.properties index e69de29..eb30735 100644 --- a/gradle.properties +++ b/gradle.properties @@ -0,0 +1 @@ +org.gradle.java.home=/usr/lib/jvm/java-21-openjdk diff --git a/src/main/java/de/ventority/randomizedminigames/Minigames/BlockRandomizer.java b/src/main/java/de/ventority/randomizedminigames/Minigames/BlockRandomizer.java index 6664615..fe39ed2 100644 --- a/src/main/java/de/ventority/randomizedminigames/Minigames/BlockRandomizer.java +++ b/src/main/java/de/ventority/randomizedminigames/Minigames/BlockRandomizer.java @@ -1,6 +1,7 @@ package de.ventority.randomizedminigames.Minigames; import de.ventority.randomizedminigames.misc.Timer.Timer; +import de.ventority.randomizedminigames.util.MinigameHandler; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.EnderDragon; @@ -70,12 +71,14 @@ public class BlockRandomizer implements MinigameBase { @Override public void killGame() { - + timer.stopCounter(); + MinigameHandler.resetSettings(owner); + MinigameHandler.deleteGame(this); } @Override public void stopGame() { - + killGame(); } @Override diff --git a/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattle.java b/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattle.java index be3193c..06af02c 100644 --- a/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattle.java +++ b/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattle.java @@ -1,17 +1,20 @@ package de.ventority.randomizedminigames.Minigames; +import de.ventority.randomizedminigames.RandomizedMinigames; import de.ventority.randomizedminigames.gui.InGame.GamesScoreboardManager; +import de.ventority.randomizedminigames.misc.ColorCycler; import de.ventority.randomizedminigames.misc.Timer.Timer; import de.ventority.randomizedminigames.util.MinigameHandler; import de.ventority.randomizedminigames.util.PlayerBackupHandler; import de.ventority.randomizedminigames.util.Settings; +import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; -import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; +import org.bukkit.scoreboard.Scoreboard; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -25,10 +28,12 @@ import org.bukkit.event.player.PlayerRespawnEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import java.awt.Color; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; +import java.util.UUID; public class ForceItemBattle implements MinigameBase, Listener { protected final HashMap currentItems; @@ -41,8 +46,24 @@ public class ForceItemBattle implements MinigameBase, Listener { private final Player owner; protected Settings settings; private final Timer timer; - private final List disconnected = new ArrayList<>(); + private final HashMap disconnectedStates = new HashMap<>(); private final HashMap skips = new HashMap<>(); + private boolean isActive = true; + + private static class DisconnectedState { + final ItemStack currentItem; + final int score; + final int skipsLeft; + DisconnectedState(ItemStack currentItem, int score, int skipsLeft) { + this.currentItem = currentItem; + this.score = score; + this.skipsLeft = skipsLeft; + } + } + private final ColorCycler bossBarColors = new ColorCycler( + new Color(130, 50, 170), new Color(160, 50, 190), 0.2); + private int bossBarTick = 0; + private org.bukkit.scheduler.BukkitTask bossBarTask; private final List SURVIVAL_ITEMS = loadMaterials(); @@ -81,6 +102,20 @@ public class ForceItemBattle implements MinigameBase, Listener { player.getInventory().addItem(skip); } timer.startCounter(); + bossBarTask = Bukkit.getScheduler().runTaskTimer( + RandomizedMinigames.serverSettingsHandler.getPlugin(), + () -> { + String color = ChatColor.of(bossBarColors.getColor(bossBarTick++)).toString(); + for (Map.Entry entry : new HashMap<>(itemDisplays).entrySet()) { + ItemStack item = currentItems.get(entry.getKey()); + if (item == null) continue; + String name = item.getType().getTranslationKey() + .replace("block.minecraft.", "") + .replace("_", " ") + .replace("item.minecraft.", ""); + entry.getValue().setTitle(color + ChatColor.BOLD + name); + } + }, 0L, 1L); } @Override @@ -121,11 +156,6 @@ public class ForceItemBattle implements MinigameBase, Listener { protected void updatePlayerItem(Player player, ItemStack item) { currentItems.replace(player, item); - String key = currentItems.get(player).getType().getTranslationKey(); - String displayName = key.replace("block.minecraft.", "") - .replace("_", " ") - .replace("item.minecraft.", ""); - itemDisplays.get(player).setTitle(displayName); ItemStack[] contents = player.getInventory().getContents(); for (ItemStack i : contents) checkItem(player, i); @@ -163,6 +193,7 @@ public class ForceItemBattle implements MinigameBase, Listener { timer.pauseCounter(); Timer t = new Timer(contestants, this, this::killGame, "Resetting game in: "); t.setStopTime(10); + t.setReversed(true); t.startCounter(); } @@ -181,22 +212,28 @@ public class ForceItemBattle implements MinigameBase, Listener { } public void killGame() { - backups.restoreAll(); - for (Player p : itemDisplays.keySet()) { - itemDisplays.get(p).setVisible(false); - itemDisplays.get(p).removePlayer(p); + isActive = false; + timer.stopCounter(); + if (bossBarTask != null) bossBarTask.cancel(); + + for (BossBar bar : itemDisplays.values()) { + bar.setVisible(false); + bar.removeAll(); } itemDisplays.clear(); - if (settings.getScoreboardStatus()) { + if (scoreboardManager != null) { scoreboardManager.removeScoreboard(); scoreboardManager = null; } - if (settings.getScoreboardStatus()) - for (Player player : contestants) - player.setScoreboard(Objects.requireNonNull(Bukkit.getScoreboardManager()).getMainScoreboard()); - itemDisplays.clear(); + Scoreboard main = Objects.requireNonNull(Bukkit.getScoreboardManager()).getMainScoreboard(); + for (Player player : contestants) { + if (player.isOnline()) + player.setScoreboard(main); + } + + backups.restoreAll(); MinigameHandler.resetSettings(owner); MinigameHandler.deleteGame(this); } @@ -261,16 +298,50 @@ public class ForceItemBattle implements MinigameBase, Listener { @EventHandler public void onPlayerLeave(PlayerQuitEvent e) { - if (contestants.contains(e.getPlayer())) { - disconnected.add(e.getPlayer()); - removePlayer(e.getPlayer()); - } + Player p = e.getPlayer(); + if (!contestants.contains(p)) return; + + disconnectedStates.put(p.getUniqueId(), new DisconnectedState( + currentItems.get(p), + currentScores.getOrDefault(p, 0), + skips.getOrDefault(p, 0) + )); + currentItems.remove(p); + currentScores.remove(p); + skips.remove(p); + removePlayer(p); } @EventHandler public void onPlayerJoin(PlayerJoinEvent e) { - if (disconnected.contains(e.getPlayer())) { + Player p = e.getPlayer(); + UUID uuid = p.getUniqueId(); + DisconnectedState state = disconnectedStates.remove(uuid); + if (state == null) return; + if (isActive) { + // Re-add player to the running game + contestants.add(p); + currentItems.put(p, state.currentItem); + currentScores.put(p, state.score); + skips.put(p, state.skipsLeft); + + BossBar bar = Bukkit.createBossBar("", BarColor.PURPLE, BarStyle.SOLID); + bar.addPlayer(p); + bar.setVisible(true); + itemDisplays.put(p, bar); + + if (settings.getScoreboardStatus() && scoreboardManager != null) + p.setScoreboard(scoreboardManager.getScoreboard()); + + p.getInventory().clear(); + ItemStack skipItem = new ItemStack(Material.BARRIER, state.skipsLeft); + org.bukkit.inventory.meta.ItemMeta meta = skipItem.getItemMeta(); + if (meta != null) { meta.setDisplayName(org.bukkit.ChatColor.RED + "Skip"); skipItem.setItemMeta(meta); } + if (state.skipsLeft > 0) p.getInventory().addItem(skipItem); + } else { + // Game already ended — restore their pre-game backup + PlayerBackupHandler.restoreIfPending(p); } } @EventHandler diff --git a/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattleTeams.java b/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattleTeams.java index 2df8641..c177ebb 100644 --- a/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattleTeams.java +++ b/src/main/java/de/ventority/randomizedminigames/Minigames/ForceItemBattleTeams.java @@ -1,16 +1,17 @@ package de.ventority.randomizedminigames.Minigames; import de.ventority.randomizedminigames.util.Team; -import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.GameMode; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.List; -public class ForceItemBattleTeams extends ForceItemBattle{ +public class ForceItemBattleTeams extends ForceItemBattle { private final List teams; + public ForceItemBattleTeams(List players, Player owner, List teams) { super(players, owner); this.teams = teams; @@ -18,27 +19,40 @@ public class ForceItemBattleTeams extends ForceItemBattle{ @Override protected void updatePlayerItem(Player p, ItemStack item) { + // teams is null while super() is still running, fall back to per-player assignment + if (teams == null) { + super.updatePlayerItem(p, item); + return; + } for (Team team : teams) { - for (Player curPlayer : team.getPlayers()) { - super.updatePlayerItem(curPlayer, item); + if (team.getPlayers().contains(p)) { + for (Player teammate : team.getPlayers()) { + super.updatePlayerItem(teammate, item); + } + return; } } } @Override protected void showEndMessage(Player winner) { + Team winningTeam = null; + for (Team team : teams) { + if (team.getPlayers().contains(winner)) { + winningTeam = team; + break; + } + } + String title = winningTeam != null + ? winningTeam.getColor() + winningTeam.getColor().name() + " Team" + ChatColor.RESET + " won!" + : winner.getName() + " won!"; + for (Player player : contestants) { player.teleport(winner); if (player != winner) player.setGameMode(GameMode.SPECTATOR); - Team winningTeam = new Team(null, null); - for (Team team : teams) - if (team.getPlayers().contains(player)) winningTeam = team; - player.sendTitle(winningTeam.getColor() + winningTeam.getColor().name() + "Team " + ChatColor.RESET + " won!", - "Resetting players...", 10, 70, 20); + player.sendTitle(title, "Resetting players...", 10, 70, 20); player.setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); } } - - } diff --git a/src/main/java/de/ventority/randomizedminigames/Minigames/OnlyChests.java b/src/main/java/de/ventority/randomizedminigames/Minigames/OnlyChests.java index db15267..8441fc0 100644 --- a/src/main/java/de/ventority/randomizedminigames/Minigames/OnlyChests.java +++ b/src/main/java/de/ventority/randomizedminigames/Minigames/OnlyChests.java @@ -1,6 +1,7 @@ package de.ventority.randomizedminigames.Minigames; import de.ventority.randomizedminigames.misc.Timer.Timer; +import de.ventority.randomizedminigames.util.MinigameHandler; import org.bukkit.Material; import org.bukkit.entity.EnderDragon; import org.bukkit.entity.EntityType; @@ -47,17 +48,19 @@ public class OnlyChests implements MinigameBase{ @Override public void killGame() { - + timer.stopCounter(); + MinigameHandler.resetSettings(owner); + MinigameHandler.deleteGame(this); } @Override public void stopGame() { - + killGame(); } @Override public Player getOwner() { - return null; + return owner; } @EventHandler @@ -73,8 +76,7 @@ public class OnlyChests implements MinigameBase{ timer.pauseCounter(); } if (event.getDamageSource().getCausingEntity() instanceof Player && contestants.contains((Player) event.getDamageSource().getCausingEntity())) - if (event.getEntity().getType() != EntityType.BLAZE) { + if (event.getEntity().getType() != EntityType.BLAZE) event.getDrops().clear(); - } } } diff --git a/src/main/java/de/ventority/randomizedminigames/RandomizedMinigames.java b/src/main/java/de/ventority/randomizedminigames/RandomizedMinigames.java index 5537992..a773caa 100644 --- a/src/main/java/de/ventority/randomizedminigames/RandomizedMinigames.java +++ b/src/main/java/de/ventority/randomizedminigames/RandomizedMinigames.java @@ -2,7 +2,10 @@ package de.ventority.randomizedminigames; import de.ventority.randomizedminigames.gui.GUIClickEvent; import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.PlayerBackupHandler; +import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.plugin.java.JavaPlugin; public final class RandomizedMinigames extends JavaPlugin implements Listener { @@ -21,6 +24,11 @@ public final class RandomizedMinigames extends JavaPlugin implements Listener { MinigameHandler.killAll(); } + @EventHandler + public void onPlayerJoin(PlayerJoinEvent e) { + PlayerBackupHandler.restoreIfPending(e.getPlayer()); + } + private void init() { serverSettingsHandler.setPlugin(this); } diff --git a/src/main/java/de/ventority/randomizedminigames/gui/BaseWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/BaseWindow.java index 8805f7f..461ccaf 100644 --- a/src/main/java/de/ventority/randomizedminigames/gui/BaseWindow.java +++ b/src/main/java/de/ventority/randomizedminigames/gui/BaseWindow.java @@ -4,101 +4,73 @@ import de.ventority.randomizedminigames.RandomizedMinigames; import net.md_5.bungee.api.ChatColor; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; - -import java.util.Objects; public abstract class BaseWindow { protected final Player p; protected final Inventory gui; - public BaseWindow(Player p) { + protected BaseWindow(Player p) { this.p = p; - gui = Bukkit.createInventory(p, 54, RandomizedMinigames.serverSettingsHandler.getServerName() - + ChatColor.RESET + ChatColor.DARK_GRAY); + gui = Bukkit.createInventory(null, 54, + RandomizedMinigames.serverSettingsHandler.getServerName() + ChatColor.RESET + ChatColor.DARK_GRAY); } protected void fillBorder() { - ItemStack stack; - for (int i = 0; i < 9; i++) { - stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE, 1); - addNBT(stack, "Action", "none"); - setItemName(stack, " "); - addItemToGUI(i, stack); - } - for (int i = 1; i < 5; i++) { - stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE, 1); - addNBT(stack, "Action", "none"); - setItemName(stack, " "); - addItemToGUI(9 * i, stack); - stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE, 1); - addNBT(stack, "Action", "none"); - setItemName(stack, " "); - addItemToGUI(8 + 9 * i, stack); - } - for (int i = 0; i < 9; i++) { - stack = new ItemStack(Material.BLACK_STAINED_GLASS_PANE, 1); - setItemName(stack, " "); - addNBT(stack, "Action", "none"); - addItemToGUI(i + 5 * 9, stack); + for (int i = 0; i < 9; i++) placeBorderPane(i); + for (int row = 1; row < 5; row++) { + placeBorderPane(9 * row); + placeBorderPane(8 + 9 * row); } + for (int i = 0; i < 9; i++) placeBorderPane(45 + i); + } + + private void placeBorderPane(int slot) { + ItemStack pane = new ItemStack(Material.BLACK_STAINED_GLASS_PANE); + setName(pane, " "); + NBTHelper.set(pane, "Action", "none"); + gui.setItem(slot, pane); } protected abstract void fillGUI(); + public abstract void handleClick(String action, InventoryClickEvent event); + public void buildWindow() { fillBorder(); fillGUI(); - addNBT(Objects.requireNonNull(gui.getItem(0)), "ItemMiniGame", "true"); + GUIClickEvent.register(p, this); p.openInventory(gui); } - protected void addNBT(ItemStack item, String key, String value) { - ItemMeta meta = item.getItemMeta(); - NamespacedKey key1 = new NamespacedKey(RandomizedMinigames.serverSettingsHandler.getPlugin(), key); - if (meta == null) return; - PersistentDataContainer data = meta.getPersistentDataContainer(); - data.set(key1, PersistentDataType.STRING, value); - item.setItemMeta(meta); + protected ItemStack makeItem(Material material, String name) { + ItemStack item = new ItemStack(material); + setName(item, name); + return item; } - protected void setItemName(ItemStack item, String name) { + protected void setName(ItemStack item, String name) { ItemMeta meta = item.getItemMeta(); if (meta == null) return; meta.setDisplayName(name); item.setItemMeta(meta); } - protected void addItemToGUI(int index, ItemStack item) { - addNBT(item, "ItemMiniGame", "true"); - gui.setItem(index, item); + // Place an item at a specific slot, overwriting whatever is there (including border). + protected void place(int slot, ItemStack item) { + gui.setItem(slot, item); } - protected void addItemToGUI(ItemStack item) { - addNBT(item, "ItemMiniGame", "true"); + // Add an item to the next available inner slot. + protected void add(ItemStack item) { gui.addItem(item); } public Inventory getGUI() { return gui; } - - private Player getPlayer() { - return p; - } - - protected String getNBT(ItemStack item, String key) { - if (item == null) return "ItemIsNull"; - ItemMeta meta = item.getItemMeta(); - NamespacedKey nsKey = new NamespacedKey(RandomizedMinigames.serverSettingsHandler.getPlugin(), key); - if (meta == null) return "NoItemMeta"; - PersistentDataContainer data = meta.getPersistentDataContainer(); - return data.get(nsKey, PersistentDataType.STRING); - } } diff --git a/src/main/java/de/ventority/randomizedminigames/gui/GUIClickEvent.java b/src/main/java/de/ventority/randomizedminigames/gui/GUIClickEvent.java index acc398a..ff9b313 100644 --- a/src/main/java/de/ventority/randomizedminigames/gui/GUIClickEvent.java +++ b/src/main/java/de/ventority/randomizedminigames/gui/GUIClickEvent.java @@ -1,49 +1,54 @@ package de.ventority.randomizedminigames.gui; -import de.ventority.randomizedminigames.gui.handlers.MinigameSelectHandler; -import de.ventority.randomizedminigames.gui.handlers.MinigameSetupHandler; -import de.ventority.randomizedminigames.gui.handlers.SettingsHandler; -import de.ventority.randomizedminigames.RandomizedMinigames; import org.bukkit.Material; -import org.bukkit.NamespacedKey; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.Inventory; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; public class GUIClickEvent implements Listener { + private static final Map openWindows = new HashMap<>(); + + public static void register(Player p, BaseWindow window) { + openWindows.put(p.getUniqueId(), window); + } + @EventHandler - public void onClickEvent(InventoryClickEvent event) { - Inventory inventory = event.getClickedInventory(); - if (event.getCurrentItem() == null) return; - if (inventory == null) return; - if (inventory.getItem(0) == null) return; - if (isMinigamePlugin(inventory.getItem(0))) { - event.setCancelled(true); - if (event.getCurrentItem().getType() == (Material.BLACK_STAINED_GLASS_PANE)) return; - switch (getNBT(event.getCurrentItem(), "Type")) { - case "none": return; - case "MinigameSelect": new MinigameSelectHandler(event, getNBT(event.getCurrentItem(), "Action")).handle(); - case "MinigameSetup": new MinigameSetupHandler(event, getNBT(event.getCurrentItem(), "Action")).handle(); - case "Misc": new SettingsHandler(event, getNBT(event.getCurrentItem(), "Action")).handle(); - } + public void onClose(InventoryCloseEvent event) { + if (!(event.getPlayer() instanceof Player)) return; + Player p = (Player) event.getPlayer(); + BaseWindow window = openWindows.get(p.getUniqueId()); + // Only unregister if the closing inventory is the one we track. + // When a new window opens, register() is called before p.openInventory() fires this + // event, so the map already holds the new window and won't be removed here. + if (window != null && window.getGUI().equals(event.getInventory())) { + openWindows.remove(p.getUniqueId()); } } - private String getNBT(ItemStack item, String key) { - if (item == null) return "ItemIsNull"; - ItemMeta meta = item.getItemMeta(); - NamespacedKey nsKey = new NamespacedKey(RandomizedMinigames.serverSettingsHandler.getPlugin(), key); - if (meta == null) return "NoItemMeta"; - PersistentDataContainer data = meta.getPersistentDataContainer(); - return data.get(nsKey, PersistentDataType.STRING); - } + @EventHandler + public void onClickEvent(InventoryClickEvent event) { + if (!(event.getWhoClicked() instanceof Player)) return; + Player p = (Player) event.getWhoClicked(); + BaseWindow window = openWindows.get(p.getUniqueId()); + if (window == null) return; + if (!window.getGUI().equals(event.getClickedInventory())) return; - private boolean isMinigamePlugin(ItemStack item) { - return getNBT(item, "ItemMiniGame") != null && getNBT(item, "ItemMiniGame").equals("true"); + event.setCancelled(true); + + ItemStack item = event.getCurrentItem(); + if (item == null || item.getType() == Material.AIR) return; + if (item.getType() == Material.BLACK_STAINED_GLASS_PANE) return; + + String action = NBTHelper.get(item, "Action"); + if (action == null || action.equals("none")) return; + + window.handleClick(action, event); } } diff --git a/src/main/java/de/ventority/randomizedminigames/gui/GUICreator.java b/src/main/java/de/ventority/randomizedminigames/gui/GUICreator.java deleted file mode 100644 index 3ca79e8..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/GUICreator.java +++ /dev/null @@ -1,89 +0,0 @@ -package de.ventority.randomizedminigames.gui; - -import com.google.gson.Gson; -import de.ventority.randomizedminigames.util.MinigameHandler; -import de.ventority.randomizedminigames.util.Settings; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -public class GUICreator extends BaseWindow { - private final String path; - - // DTOs als statische Klassen - private static class GUIItem { - int slot; - String material; - String name; - Map nbt; - } - private static class GUIConfig { - String title; - int rows; - List items; - } - - public GUICreator(Player p, String path) { - super(p); - this.path = path; - } - - @Override - protected void fillGUI() { - Settings playerSettings = MinigameHandler.getSettings(p); - - Gson gson = new Gson(); - GUIConfig config; - - try (InputStream in = Objects.requireNonNull( - getClass().getClassLoader().getResourceAsStream(path), - "Resource not found: " + path - ); - Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) { - - config = gson.fromJson(reader, GUIConfig.class); - if (config == null) { - throw new IllegalStateException("Parsed GUI config is null; is the file empty? Path: " + path); - } - if (config.items == null) { - throw new IllegalStateException("'items' is null in GUI config. Path: " + path); - } - } catch (Exception e) { - System.out.println("Error loading " + path + ". Check that the file is packaged under src/main/resources and not empty."); - return; - } - - for (GUIItem guiItem : config.items) { - Material mat = Material.valueOf(guiItem.material.toUpperCase()); - ItemStack item = new ItemStack(mat); - - if (guiItem.nbt != null) { - for (Map.Entry entry : guiItem.nbt.entrySet()) { - addNBT(item, entry.getKey(), entry.getValue()); - } - } - - String displayName = guiItem.name - .replace("%scoreboard%", playerSettings.getScoreboardStatus() ? ChatColor.GREEN + "On" : ChatColor.RED + "Off") - .replace("%scoreboardState%", playerSettings.getScoreboardStatus() ? ChatColor.GREEN + "On" : ChatColor.RED + "Off") - .replace("%timer%", playerSettings.isTimed ? ChatColor.GREEN + "On" : ChatColor.RED + "Off"); - - setItemName(item, displayName); - - if (guiItem.slot == -1) { - addItemToGUI(item); - } else { - addItemToGUI(guiItem.slot, item); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/MinigameSetup.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/MinigameSetup.java deleted file mode 100644 index 8cf6d77..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/MinigameSetup.java +++ /dev/null @@ -1,62 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import de.ventority.randomizedminigames.util.Settings; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -public class MinigameSetup extends BaseWindow { - - public MinigameSetup(Player p) { - super(p); - } - - @Override - protected void fillGUI() { - ItemStack playerSelect = new ItemStack(Material.PLAYER_HEAD); - addNBT(playerSelect, "Type", "MinigameSetup"); - addNBT(playerSelect, "Action", "startPlayerSelection"); - setItemName(playerSelect, "Select Players"); - addItemToGUI(playerSelect); - - ItemStack setLimit = new ItemStack(Material.BOOK); - addNBT(setLimit, "Type", "MinigameSetup"); - addNBT(setLimit, "Action", "startLimitSelection"); - setItemName(setLimit, "Set win limit"); - addItemToGUI(setLimit); - - Settings playerSettings = MinigameHandler.getSettings(p); - ItemStack scoreboard = new ItemStack(Material.EMERALD); - addNBT(scoreboard, "Type", "MinigameSetup"); - addNBT(scoreboard, "Action", "switchScoreboard"); - setItemName(scoreboard, "Scoreboard: " + (playerSettings.getScoreboardStatus() ? (ChatColor.GREEN + "On") : ChatColor.RED + "Off")); - addItemToGUI(scoreboard); - - ItemStack start = new ItemStack(Material.GREEN_DYE); - addNBT(start, "Type", "MinigameSetup"); - addNBT(start, "Action", "startGame"); - setItemName(start, "Start"); - addItemToGUI(50, start); - - ItemStack timer = new ItemStack(Material.CLOCK); - addNBT(timer, "Type", "MinigameSetup"); - addNBT(timer, "Action", "startTimerSetup"); - setItemName(timer, "Set Timer"); - addItemToGUI(timer); - - ItemStack enableTimer = new ItemStack(Material.TARGET); - addNBT(enableTimer, "Type", "MinigameSetup"); - addNBT(enableTimer, "Action", "toggleTimer"); - setItemName(enableTimer, "Timer: " + (playerSettings.isTimed ? (ChatColor.GREEN + "On") : ChatColor.RED + "Off")); - addItemToGUI(enableTimer); - - ItemStack back = new ItemStack(Material.ARROW); - addNBT(back, "Type", "MinigameSelect"); - addNBT(back, "Action", "homeMenu"); - setItemName(back, "Back"); - addItemToGUI(49, back); - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/PlayerSelection.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/PlayerSelection.java deleted file mode 100644 index 8e9dc68..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/PlayerSelection.java +++ /dev/null @@ -1,48 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; - -public class PlayerSelection extends BaseWindow { - public PlayerSelection(Player p) { - super(p); - } - - - @Override - protected void fillGUI() { - for (Player player : Bukkit.getOnlinePlayers()) { - if (!MinigameHandler.getOccupiedPlayers().contains(player)) { - ItemStack item = getPlayerHead(player); - addNBT(item, "Type", "MinigameSetup"); - addNBT(item, "Action", "clickedPlayer"); - addNBT(item, "Player", player.getDisplayName()); - addItemToGUI(item); - } - } - - ItemStack back = new ItemStack(Material.ARROW); - addNBT(back, "Type", "MinigameSetup"); - addNBT(back, "Action", "homeMenu"); - setItemName(back, "Back"); - addItemToGUI(49, back); - } - - private ItemStack getPlayerHead(Player player) { - ItemStack head = new ItemStack(Material.PLAYER_HEAD); - SkullMeta meta = (SkullMeta) head.getItemMeta(); - if (meta != null) { - meta.setOwningPlayer(player); - meta.setDisplayName((MinigameHandler.getSettings(p).getSelectedPlayers().contains(player) ? - ChatColor.GREEN : ChatColor.RED) + player.getName()); - head.setItemMeta(meta); - } - return head; - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/SetLimit.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/SetLimit.java deleted file mode 100644 index 4ffcb56..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/SetLimit.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -public class SetLimit extends BaseWindow { - public SetLimit(Player p) { - super(p); - } - - @Override - protected void fillGUI() { - ItemStack add = new ItemStack(Material.RED_DYE); - addNBT(add, "Type", "MinigameSetup"); - addNBT(add, "Action", "addToLimit"); - setItemName(add, "Add"); - addItemToGUI(14, add); - - ItemStack sub = new ItemStack(Material.GREEN_DYE); - addNBT(sub, "Type", "MinigameSetup"); - addNBT(sub, "Action", "subFromLimit"); - setItemName(sub, "Sub"); - addItemToGUI(12, sub); - - ItemStack display = new ItemStack(Material.PAPER); - addNBT(display, "Type", "MinigameSetup"); - addNBT(display, "Action", "none"); - setItemName(display, "" + MinigameHandler.getSettings(p).getSelectedLimit()); - addItemToGUI(13, display); - - ItemStack back = new ItemStack(Material.ARROW); - addNBT(back, "Type", "MinigameSetup"); - addNBT(back, "Action", "homeMenu"); - setItemName(back, "Back"); - addItemToGUI(49, back); - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/SetTimeLimit.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/SetTimeLimit.java deleted file mode 100644 index 6f17492..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/SetTimeLimit.java +++ /dev/null @@ -1,75 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -public class SetTimeLimit extends BaseWindow { - public SetTimeLimit(Player p) { - super(p); - } - - @Override - protected void fillGUI() { - ItemStack add30 = new ItemStack(Material.RED_DYE); - addNBT(add30, "Type", "MinigameSetup"); - addNBT(add30, "Action", "add30ToTimeLimit"); - setItemName(add30, "+30min"); - addItemToGUI(16, add30); - - ItemStack add10 = new ItemStack(Material.RED_DYE); - addNBT(add10, "Type", "MinigameSetup"); - addNBT(add10, "Action", "add10ToTimeLimit"); - setItemName(add10, "+10min"); - addItemToGUI(15, add10); - - ItemStack add1 = new ItemStack(Material.RED_DYE); - addNBT(add1, "Type", "MinigameSetup"); - addNBT(add1, "Action", "add1ToTimeLimit"); - setItemName(add1, "+1min"); - addItemToGUI(14, add1); - - ItemStack sub30 = new ItemStack(Material.GREEN_DYE); - addNBT(sub30, "Type", "MinigameSetup"); - addNBT(sub30, "Action", "sub30FromTimeLimit"); - setItemName(sub30, "-30min"); - addItemToGUI(10, sub30); - - ItemStack sub10 = new ItemStack(Material.GREEN_DYE); - addNBT(sub10, "Type", "MinigameSetup"); - addNBT(sub10, "Action", "sub10FromTimeLimit"); - setItemName(sub10, "-10min"); - addItemToGUI(11, sub10); - - ItemStack sub1 = new ItemStack(Material.GREEN_DYE); - addNBT(sub1, "Type", "MinigameSetup"); - addNBT(sub1, "Action", "sub1FromTimeLimit"); - setItemName(sub1, "-1min"); - addItemToGUI(12, sub1); - - ItemStack display = new ItemStack(Material.PAPER); - addNBT(display, "Type", "MinigameSetup"); - addNBT(display, "Action", "none"); - setItemName(display, formattedTime(MinigameHandler.getSettings(p).getTimeLimit())); - addItemToGUI(13, display); - - ItemStack back = new ItemStack(Material.ARROW); - addNBT(back, "Type", "MinigameSetup"); - addNBT(back, "Action", "homeMenu"); - setItemName(back, "Back"); - addItemToGUI(49, back); - } - - private String formattedTime(int time) { - int minutes = (int)Math.floor((double) time / 60); - int seconds = time % 60; - StringBuilder sb = new StringBuilder(); - if (minutes != 0) { - sb.append(minutes).append(":"); - } - sb.append(seconds); - return sb.toString(); - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamCountSelection.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamCountSelection.java deleted file mode 100644 index 821424e..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamCountSelection.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -public class TeamCountSelection extends BaseWindow { - public TeamCountSelection(Player p) { - super(p); - } - - - @Override - protected void fillGUI() { - ItemStack add = new ItemStack(Material.RED_DYE); - addNBT(add, "Type", "MinigameSetup"); - addNBT(add, "Action", "addTeamCount"); - setItemName(add, "Add"); - addItemToGUI(14, add); - - ItemStack sub = new ItemStack(Material.GREEN_DYE); - addNBT(sub, "Type", "MinigameSetup"); - addNBT(sub, "Action", "subTeamCount"); - setItemName(sub, "Sub"); - addItemToGUI(12, sub); - - ItemStack display = new ItemStack(Material.PAPER); - addNBT(display, "Type", "MinigameSetup"); - addNBT(display, "Action", "none"); - setItemName(display, "" + MinigameHandler.getSettings(p).getTeamCount()); - addItemToGUI(13, display); - - ItemStack next = new ItemStack(Material.ARROW); - addNBT(next, "Type", "MinigameSetup"); - addNBT(next, "Action", "TeamSetupSelection"); - setItemName(next, "Next"); - addItemToGUI(49, next); - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamOverview.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamOverview.java deleted file mode 100644 index 6771580..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamOverview.java +++ /dev/null @@ -1,16 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import org.bukkit.entity.Player; - -public class TeamOverview extends BaseWindow { - - public TeamOverview(Player p) { - super(p); - } - - @Override - protected void fillGUI() { - - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamPlayerSelection.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamPlayerSelection.java deleted file mode 100644 index 56fdcfc..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamPlayerSelection.java +++ /dev/null @@ -1,58 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import net.md_5.bungee.api.ChatColor; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.SkullMeta; - -public class TeamPlayerSelection extends BaseWindow { - public TeamPlayerSelection(Player p) { - super(p); - } - - - @Override - protected void fillGUI() { - for (Player player : Bukkit.getOnlinePlayers()) { - if (!MinigameHandler.getOccupiedPlayers().contains(player)) { - ItemStack item = getPlayerHead(player); - addNBT(item, "Type", "MinigameSetup"); - addNBT(item, "Action", "clickedPlayerInTeams"); - addNBT(item, "Player", player.getDisplayName()); - addItemToGUI(item); - } - } - final ChatColor[] colors = new ChatColor[]{ChatColor.GREEN, - ChatColor.RED, ChatColor.BLUE, ChatColor.DARK_PURPLE, - ChatColor.BLACK, ChatColor.DARK_GREEN}; - final Material[] material = new Material[]{Material.GREEN_WOOL, Material.RED_WOOL, - Material.BLUE_WOOL, Material.PURPLE_WOOL, Material.BLACK_WOOL, Material.GREEN_WOOL}; - - ItemStack selectedTeam = new ItemStack(material[MinigameHandler.getSettings(p).getSelectedTeamIndex()], 1); - setItemName(selectedTeam, colors[MinigameHandler.getSettings(p).getSelectedTeamIndex()] + "Team #" + (MinigameHandler.getSettings(p).getSelectedTeamIndex() + 1)); - addNBT(selectedTeam, "Team", Integer.toString(MinigameHandler.getSettings(p).getSelectedTeamIndex())); - addItemToGUI(4, selectedTeam); - - ItemStack back = new ItemStack(Material.ARROW); - addNBT(back, "Type", "MinigameSetup"); - addNBT(back, "Action", "homeMenu"); - setItemName(back, "Back"); - addItemToGUI(49, back); - } - - private ItemStack getPlayerHead(Player player) { - ItemStack head = new ItemStack(Material.PLAYER_HEAD); - SkullMeta meta = (SkullMeta) head.getItemMeta(); - if (meta != null) { - meta.setOwningPlayer(player); - meta.setDisplayName((MinigameHandler.getSettings(p).getSelectedPlayers().contains(player) ? - ChatColor.GREEN : ChatColor.RED) + player.getName()); - head.setItemMeta(meta); - } - return head; - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamSetupSelection.java b/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamSetupSelection.java deleted file mode 100644 index aa3e831..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/MinigameSetups/TeamSetupSelection.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.ventority.randomizedminigames.gui.MinigameSetups; - -import de.ventority.randomizedminigames.gui.BaseWindow; -import de.ventority.randomizedminigames.util.MinigameHandler; -import org.bukkit.ChatColor; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -public class TeamSetupSelection extends BaseWindow { - private final ChatColor[] colors = new ChatColor[]{ChatColor.GREEN, ChatColor.RED, ChatColor.BLUE, ChatColor.DARK_PURPLE, ChatColor.BLACK, ChatColor.DARK_GREEN}; - private final Material[] material = new Material[]{Material.GREEN_WOOL, Material.RED_WOOL, Material.BLUE_WOOL, Material.PURPLE_WOOL, Material.BLACK_WOOL, Material.GREEN_WOOL}; - - public TeamSetupSelection(Player p) { - super(p); - } - - @Override - protected void fillGUI() { - for (int i = 0; i < MinigameHandler.getSettings(p).getTeamCount(); i++) { - ItemStack item = new ItemStack(material[i], 1); - setItemName(item, colors[i] + "Team #" + (i + 1)); - addNBT(item, "Type", "MinigameSetup"); - addNBT(item, "Action", "selectTeam"); - addNBT(item, "selectedTeam", Integer.toString(i)); - addItemToGUI(item); - } - - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/NBTHelper.java b/src/main/java/de/ventority/randomizedminigames/gui/NBTHelper.java new file mode 100644 index 0000000..6948db5 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/NBTHelper.java @@ -0,0 +1,27 @@ +package de.ventority.randomizedminigames.gui; + +import de.ventority.randomizedminigames.RandomizedMinigames; +import org.bukkit.NamespacedKey; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.persistence.PersistentDataType; + +public final class NBTHelper { + private NBTHelper() {} + + public static void set(ItemStack item, String key, String value) { + ItemMeta meta = item.getItemMeta(); + if (meta == null) return; + NamespacedKey nsKey = new NamespacedKey(RandomizedMinigames.serverSettingsHandler.getPlugin(), key); + meta.getPersistentDataContainer().set(nsKey, PersistentDataType.STRING, value); + item.setItemMeta(meta); + } + + public static String get(ItemStack item, String key) { + if (item == null) return null; + ItemMeta meta = item.getItemMeta(); + if (meta == null) return null; + NamespacedKey nsKey = new NamespacedKey(RandomizedMinigames.serverSettingsHandler.getPlugin(), key); + return meta.getPersistentDataContainer().get(nsKey, PersistentDataType.STRING); + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/SettingsWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/SettingsWindow.java deleted file mode 100644 index 6fd9ff2..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/SettingsWindow.java +++ /dev/null @@ -1,20 +0,0 @@ -package de.ventority.randomizedminigames.gui; - -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -public class SettingsWindow extends BaseWindow{ - - public SettingsWindow(Player p) { - super(p); - } - - @Override - public void fillGUI() { - ItemStack setContestants = new ItemStack(Material.ZOMBIE_HEAD, 1); - setItemName(setContestants, "Add Contestants"); - addNBT(setContestants, "Status", "addContestants"); - gui.addItem(setContestants); - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/handlers/GUIHandler.java b/src/main/java/de/ventority/randomizedminigames/gui/handlers/GUIHandler.java deleted file mode 100644 index 9f66c3e..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/handlers/GUIHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.ventority.randomizedminigames.gui.handlers; - -import de.ventority.randomizedminigames.RandomizedMinigames; -import org.bukkit.NamespacedKey; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.bukkit.persistence.PersistentDataContainer; -import org.bukkit.persistence.PersistentDataType; - -public abstract class GUIHandler { - protected final InventoryClickEvent event; - protected final String action; - - public GUIHandler(InventoryClickEvent event, String action) { - this.event = event; - this.action = action; - } - - public abstract void handle(); - - protected String getNBT(ItemStack item, String key) { - if (item == null) return "ItemIsNull"; - ItemMeta meta = item.getItemMeta(); - NamespacedKey nsKey = new NamespacedKey(RandomizedMinigames.serverSettingsHandler.getPlugin(), key); - if (meta == null) return "NoItemMeta"; - PersistentDataContainer data = meta.getPersistentDataContainer(); - return data.get(nsKey, PersistentDataType.STRING); - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/handlers/MinigameSelectHandler.java b/src/main/java/de/ventority/randomizedminigames/gui/handlers/MinigameSelectHandler.java deleted file mode 100644 index ebdf948..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/handlers/MinigameSelectHandler.java +++ /dev/null @@ -1,30 +0,0 @@ -package de.ventority.randomizedminigames.gui.handlers; - -import de.ventority.randomizedminigames.gui.MinigameSetups.MinigameSetup; -import de.ventority.randomizedminigames.gui.MinigameSetups.TeamCountSelection; -import de.ventority.randomizedminigames.util.MinigameHandler; -import de.ventority.randomizedminigames.util.Settings; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; - -public class MinigameSelectHandler extends GUIHandler{ - public MinigameSelectHandler(InventoryClickEvent event, String action) { - super(event, action); - } - - @Override - public void handle() { - Settings settings = MinigameHandler.getSettings((Player) event.getWhoClicked()); - if (action.equals("startForceItem") || action.equals("startForceItemSameItem") || action.equals("startBlockRandomizer") || action.equals("startOnlyChests")) { - settings.selectMinigame(Integer.parseInt(getNBT(event.getCurrentItem(), "selectedMinigame"))); - new MinigameSetup((Player) event.getWhoClicked()).buildWindow(); - } - if (action.equals("startForceItemTeams")) { - settings.selectMinigame(Integer.parseInt(getNBT(event.getCurrentItem(), "selectedMinigame"))); - new TeamCountSelection((Player)event.getWhoClicked()).buildWindow(); - } - if (action.equals("homeMenu")) { - new MinigameSetup((Player) event.getWhoClicked()).buildWindow(); - } - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/handlers/MinigameSetupHandler.java b/src/main/java/de/ventority/randomizedminigames/gui/handlers/MinigameSetupHandler.java deleted file mode 100644 index b5a9c17..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/handlers/MinigameSetupHandler.java +++ /dev/null @@ -1,116 +0,0 @@ -package de.ventority.randomizedminigames.gui.handlers; - -import de.ventority.randomizedminigames.gui.MinigameSetups.*; -import de.ventority.randomizedminigames.util.Team; -import de.ventority.randomizedminigames.util.MinigameHandler; -import de.ventority.randomizedminigames.util.Settings; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; - -public class MinigameSetupHandler extends GUIHandler { - - public MinigameSetupHandler(InventoryClickEvent event, String action) { - super(event, action); - } - - @Override - public void handle() { - if (action.equals("homeMenu")) { - new MinigameSetup((Player) event.getWhoClicked()).buildWindow(); - } - - Settings playerSettings = MinigameHandler.getSettings(((Player) event.getWhoClicked()).getPlayer()); - if (action.equals("clickedPlayer")) { - Player toWork = Bukkit.getPlayer(getNBT(event.getCurrentItem(), "Player")); - if (playerSettings.getSelectedPlayers().contains(toWork)) { - playerSettings.removePlayersFromSelection(toWork); - } else { - playerSettings.addPlayersToSelection(toWork); - } - new PlayerSelection((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("subFromLimit")) { - playerSettings.subFromWinLimit(); - new SetLimit((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("addToLimit")) { - playerSettings.addToWinLimit(); - new SetLimit((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("addTeamCount")) { - playerSettings.addTeamCount(); - new TeamCountSelection((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("subTeamCount")) { - playerSettings.subTeamCount(); - new TeamCountSelection((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("startPlayerSelection")) { - new PlayerSelection((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("startLimitSelection")) { - new SetLimit((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("switchScoreboard")) { - playerSettings.switchScoreboard(); - new MinigameSetup((Player) event.getWhoClicked()).buildWindow(); - } - - if (action.equals("toggleTimer")) { - playerSettings.isTimed = !playerSettings.isTimed; - new MinigameSetup((Player) event.getWhoClicked()).buildWindow(); - } - - if (action.equals("startGame")) { - MinigameHandler.createMinigame(playerSettings.getSelectedMinigame(), (Player) event.getWhoClicked()); - event.getWhoClicked().closeInventory(); - } - - if (action.equals("TeamSetupSelection")) { - new TeamSetupSelection((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("selectTeam")) { - MinigameHandler.getSettings(((Player) event.getWhoClicked()).getPlayer()).setSelectedTeamIndex(Integer.parseInt(getNBT(event.getCurrentItem(), "selectedTeam"))); - new TeamPlayerSelection((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.equals("clickedPlayerInTeams")) { - Player toWork = Bukkit.getPlayer(getNBT(event.getCurrentItem(), "Player")); - int teamNumber = Integer.parseInt(getNBT(event.getClickedInventory().getItem(4), "Team")); - Team team = playerSettings.getTeam(teamNumber - 1); - if (playerSettings.getSelectedPlayers().contains(toWork)) { - team.removePlayer(toWork); - playerSettings.removePlayersFromSelection(toWork); - } else { - team.addPlayer(toWork); - playerSettings.addPlayersToSelection(toWork); - } - return; - } - - if (action.equals("startTimerSetup")) { - new SetTimeLimit((Player)event.getWhoClicked()).buildWindow(); - } - - if (action.contains("FromTimeLimit") || action.contains("ToTimeLimit")) { - switch (action) { - case "add30ToTimeLimit": playerSettings.setTimeLimit(playerSettings.getTimeLimit() + 30*60); break; - case "add10ToTimeLimit": playerSettings.setTimeLimit(playerSettings.getTimeLimit() + 10*60); break; - case "add1ToTimeLimit": playerSettings.setTimeLimit(playerSettings.getTimeLimit() + 60); break; - case "sub30FromTimeLimit": playerSettings.setTimeLimit(playerSettings.getTimeLimit() - 30*60); break; - case "sub10FromTimeLimit": playerSettings.setTimeLimit(playerSettings.getTimeLimit() - 10*60); break; - case "sub1FromTimeLimit": playerSettings.setTimeLimit(playerSettings.getTimeLimit() - 60); break; - } - new SetTimeLimit((Player)event.getWhoClicked()).buildWindow(); - } - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/handlers/SettingsHandler.java b/src/main/java/de/ventority/randomizedminigames/gui/handlers/SettingsHandler.java deleted file mode 100644 index 3ec3b4d..0000000 --- a/src/main/java/de/ventority/randomizedminigames/gui/handlers/SettingsHandler.java +++ /dev/null @@ -1,18 +0,0 @@ -package de.ventority.randomizedminigames.gui.handlers; - -import de.ventority.randomizedminigames.gui.SettingsWindow; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.InventoryClickEvent; - -public class SettingsHandler extends GUIHandler { - public SettingsHandler(InventoryClickEvent event, String action) { - super(event, action); - } - - @Override - public void handle() { - if (action.equals("selectSettings")) { - new SettingsWindow((Player)event.getWhoClicked()); - } - } -} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigameSetupWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigameSetupWindow.java new file mode 100644 index 0000000..c187ec3 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigameSetupWindow.java @@ -0,0 +1,88 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class MinigameSetupWindow extends BaseWindow { + + public MinigameSetupWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + + ItemStack playerSelect = makeItem(Material.PLAYER_HEAD, "Select Players"); + NBTHelper.set(playerSelect, "Action", "startPlayerSelection"); + add(playerSelect); + + String limitLabel = !settings.isTimed + ? ChatColor.GREEN + String.valueOf(settings.getSelectedLimit()) + : ChatColor.RED + "Off"; + ItemStack setLimit = makeItem(Material.BOOK, "Win Limit: " + limitLabel); + NBTHelper.set(setLimit, "Action", "startLimitSelection"); + add(setLimit); + + ItemStack scoreboard = makeItem(Material.EMERALD, + "Scoreboard: " + (settings.getScoreboardStatus() ? ChatColor.GREEN + "On" : ChatColor.RED + "Off")); + NBTHelper.set(scoreboard, "Action", "switchScoreboard"); + add(scoreboard); + + String timerLabel = settings.isTimed + ? ChatColor.GREEN + formatTime(settings.getTimeLimit()) + : ChatColor.RED + "Off"; + ItemStack timer = makeItem(Material.CLOCK, "Timer: " + timerLabel); + NBTHelper.set(timer, "Action", "startTimerSetup"); + add(timer); + + ItemStack start = makeItem(Material.GREEN_DYE, "Start"); + NBTHelper.set(start, "Action", "startGame"); + place(50, start); + + ItemStack back = makeItem(Material.ARROW, "Back"); + NBTHelper.set(back, "Action", "back"); + place(49, back); + } + + private String formatTime(int totalSeconds) { + int minutes = totalSeconds / 60; + int seconds = totalSeconds % 60; + if (minutes == 0) return String.valueOf(seconds); + return minutes + ":" + String.format("%02d", seconds); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + Settings settings = MinigameHandler.getSettings(p); + switch (action) { + case "startPlayerSelection": + new PlayerSelectionWindow(p).buildWindow(); + break; + case "startLimitSelection": + new SetLimitWindow(p).buildWindow(); + break; + case "switchScoreboard": + settings.switchScoreboard(); + new MinigameSetupWindow(p).buildWindow(); + break; + case "startTimerSetup": + new SetTimeLimitWindow(p).buildWindow(); + break; + case "startGame": + MinigameHandler.createMinigame(settings.getSelectedMinigame(), p); + p.closeInventory(); + break; + case "back": + new MinigamesDisplayWindow(p).buildWindow(); + break; + } + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigamesDisplayWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigamesDisplayWindow.java index 264b298..d6dc08a 100644 --- a/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigamesDisplayWindow.java +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/MinigamesDisplayWindow.java @@ -1,8 +1,11 @@ package de.ventority.randomizedminigames.gui.windows; -import de.ventority.randomizedminigames.gui.BaseWindow; import de.ventority.randomizedminigames.Minigames.Minigame; +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.inventory.ItemStack; public class MinigamesDisplayWindow extends BaseWindow { @@ -14,12 +17,23 @@ public class MinigamesDisplayWindow extends BaseWindow { @Override protected void fillGUI() { for (Minigame minigame : Minigame.values()) { - ItemStack item = new ItemStack(minigame.getMaterial(), 1); - setItemName(item, minigame.getName()); - addNBT(item, "Type", "MinigameSelect"); - addNBT(item, "Action", minigame.getAction()); - addNBT(item, "selectedMinigame", Integer.toString(minigame.getNumber())); - addItemToGUI(item); + ItemStack item = makeItem(minigame.getMaterial(), minigame.getName()); + NBTHelper.set(item, "Action", minigame.getAction()); + NBTHelper.set(item, "selectedMinigame", Integer.toString(minigame.getNumber())); + add(item); + } + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + String selectedMinigame = NBTHelper.get(event.getCurrentItem(), "selectedMinigame"); + if (selectedMinigame != null) { + MinigameHandler.getSettings(p).selectMinigame(Integer.parseInt(selectedMinigame)); + } + if (action.equals("startForceItemTeams")) { + new TeamCountSelectionWindow(p).buildWindow(); + } else { + new MinigameSetupWindow(p).buildWindow(); } } } diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/PlayerSelectionWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/PlayerSelectionWindow.java new file mode 100644 index 0000000..8af2448 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/PlayerSelectionWindow.java @@ -0,0 +1,69 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +public class PlayerSelectionWindow extends BaseWindow { + + public PlayerSelectionWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + for (Player online : Bukkit.getOnlinePlayers()) { + if (!MinigameHandler.getOccupiedPlayers().contains(online)) { + boolean selected = settings.getSelectedPlayers().contains(online); + ItemStack head = makePlayerHead(online, selected); + NBTHelper.set(head, "Action", "clickedPlayer"); + NBTHelper.set(head, "Player", online.getName()); + add(head); + } + } + + ItemStack back = makeItem(Material.ARROW, "Back"); + NBTHelper.set(back, "Action", "back"); + place(49, back); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + if (action.equals("back")) { + new MinigameSetupWindow(p).buildWindow(); + return; + } + if (action.equals("clickedPlayer")) { + String playerName = NBTHelper.get(event.getCurrentItem(), "Player"); + Player target = Bukkit.getPlayer(playerName); + if (target == null) return; + Settings settings = MinigameHandler.getSettings(p); + if (settings.getSelectedPlayers().contains(target)) { + settings.removePlayersFromSelection(target); + } else { + settings.addPlayersToSelection(target); + } + new PlayerSelectionWindow(p).buildWindow(); + } + } + + private ItemStack makePlayerHead(Player target, boolean selected) { + ItemStack head = new ItemStack(Material.PLAYER_HEAD); + SkullMeta meta = (SkullMeta) head.getItemMeta(); + if (meta != null) { + meta.setOwningPlayer(target); + meta.setDisplayName((selected ? ChatColor.GREEN : ChatColor.RED) + target.getName()); + head.setItemMeta(meta); + } + return head; + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/SetLimitWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/SetLimitWindow.java new file mode 100644 index 0000000..ac4f7ae --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/SetLimitWindow.java @@ -0,0 +1,67 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class SetLimitWindow extends BaseWindow { + + public SetLimitWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + + ItemStack sub = makeItem(Material.GREEN_DYE, "Sub"); + NBTHelper.set(sub, "Action", "subFromLimit"); + place(12, sub); + + ItemStack display = makeItem(Material.PAPER, String.valueOf(settings.getSelectedLimit())); + NBTHelper.set(display, "Action", "none"); + place(13, display); + + ItemStack add = makeItem(Material.RED_DYE, "Add"); + NBTHelper.set(add, "Action", "addToLimit"); + place(14, add); + + ItemStack toggle = !settings.isTimed + ? makeItem(Material.LIME_DYE, ChatColor.GREEN + "Enabled - click to disable") + : makeItem(Material.GRAY_DYE, ChatColor.RED + "Disabled - click to enable"); + NBTHelper.set(toggle, "Action", "toggleWinLimit"); + place(22, toggle); + + ItemStack back = makeItem(Material.ARROW, "Back"); + NBTHelper.set(back, "Action", "back"); + place(49, back); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + Settings settings = MinigameHandler.getSettings(p); + switch (action) { + case "addToLimit": + settings.addToWinLimit(); + new SetLimitWindow(p).buildWindow(); + break; + case "subFromLimit": + settings.subFromWinLimit(); + new SetLimitWindow(p).buildWindow(); + break; + case "toggleWinLimit": + settings.isTimed = !settings.isTimed; + new SetLimitWindow(p).buildWindow(); + break; + case "back": + new MinigameSetupWindow(p).buildWindow(); + break; + } + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/SetTimeLimitWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/SetTimeLimitWindow.java new file mode 100644 index 0000000..327d0aa --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/SetTimeLimitWindow.java @@ -0,0 +1,84 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class SetTimeLimitWindow extends BaseWindow { + + public SetTimeLimitWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + + ItemStack sub30 = makeItem(Material.GREEN_DYE, "-30min"); + NBTHelper.set(sub30, "Action", "sub30"); + place(10, sub30); + + ItemStack sub10 = makeItem(Material.GREEN_DYE, "-10min"); + NBTHelper.set(sub10, "Action", "sub10"); + place(11, sub10); + + ItemStack sub1 = makeItem(Material.GREEN_DYE, "-1min"); + NBTHelper.set(sub1, "Action", "sub1"); + place(12, sub1); + + ItemStack display = makeItem(Material.PAPER, formatTime(settings.getTimeLimit())); + NBTHelper.set(display, "Action", "none"); + place(13, display); + + ItemStack add1 = makeItem(Material.RED_DYE, "+1min"); + NBTHelper.set(add1, "Action", "add1"); + place(14, add1); + + ItemStack add10 = makeItem(Material.RED_DYE, "+10min"); + NBTHelper.set(add10, "Action", "add10"); + place(15, add10); + + ItemStack add30 = makeItem(Material.RED_DYE, "+30min"); + NBTHelper.set(add30, "Action", "add30"); + place(16, add30); + + ItemStack toggle = settings.isTimed + ? makeItem(Material.LIME_DYE, ChatColor.GREEN + "Enabled - click to disable") + : makeItem(Material.GRAY_DYE, ChatColor.RED + "Disabled - click to enable"); + NBTHelper.set(toggle, "Action", "toggleTimer"); + place(22, toggle); + + ItemStack back = makeItem(Material.ARROW, "Back"); + NBTHelper.set(back, "Action", "back"); + place(49, back); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + Settings settings = MinigameHandler.getSettings(p); + switch (action) { + case "add30": settings.setTimeLimit(settings.getTimeLimit() + 30 * 60); break; + case "add10": settings.setTimeLimit(settings.getTimeLimit() + 10 * 60); break; + case "add1": settings.setTimeLimit(settings.getTimeLimit() + 60); break; + case "sub30": settings.setTimeLimit(settings.getTimeLimit() - 30 * 60); break; + case "sub10": settings.setTimeLimit(settings.getTimeLimit() - 10 * 60); break; + case "sub1": settings.setTimeLimit(settings.getTimeLimit() - 60); break; + case "toggleTimer": settings.isTimed = !settings.isTimed; break; + case "back": new MinigameSetupWindow(p).buildWindow(); return; + } + new SetTimeLimitWindow(p).buildWindow(); + } + + private String formatTime(int totalSeconds) { + int minutes = totalSeconds / 60; + int seconds = totalSeconds % 60; + if (minutes == 0) return String.valueOf(seconds); + return minutes + ":" + String.format("%02d", seconds); + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/SettingsWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/SettingsWindow.java new file mode 100644 index 0000000..4b6b612 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/SettingsWindow.java @@ -0,0 +1,27 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class SettingsWindow extends BaseWindow { + + public SettingsWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + ItemStack setContestants = makeItem(Material.ZOMBIE_HEAD, "Add Contestants"); + NBTHelper.set(setContestants, "Action", "addContestants"); + add(setContestants); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + // Not yet implemented + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamCountSelectionWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamCountSelectionWindow.java new file mode 100644 index 0000000..30b5dc7 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamCountSelectionWindow.java @@ -0,0 +1,57 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class TeamCountSelectionWindow extends BaseWindow { + + public TeamCountSelectionWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + + ItemStack sub = makeItem(Material.GREEN_DYE, "Sub"); + NBTHelper.set(sub, "Action", "subTeamCount"); + place(12, sub); + + ItemStack display = makeItem(Material.PAPER, String.valueOf(settings.getTeamCount())); + NBTHelper.set(display, "Action", "none"); + place(13, display); + + ItemStack add = makeItem(Material.RED_DYE, "Add"); + NBTHelper.set(add, "Action", "addTeamCount"); + place(14, add); + + ItemStack next = makeItem(Material.ARROW, "Next"); + NBTHelper.set(next, "Action", "next"); + place(49, next); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + Settings settings = MinigameHandler.getSettings(p); + switch (action) { + case "addTeamCount": + settings.addTeamCount(); + new TeamCountSelectionWindow(p).buildWindow(); + break; + case "subTeamCount": + settings.subTeamCount(); + new TeamCountSelectionWindow(p).buildWindow(); + break; + case "next": + MinigameHandler.getSettings(p).initTeams(); + new TeamSetupSelectionWindow(p).buildWindow(); + break; + } + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamPlayerSelectionWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamPlayerSelectionWindow.java new file mode 100644 index 0000000..381e7c2 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamPlayerSelectionWindow.java @@ -0,0 +1,93 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import de.ventority.randomizedminigames.util.Team; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.SkullMeta; + +public class TeamPlayerSelectionWindow extends BaseWindow { + private static final ChatColor[] TEAM_COLORS = { + ChatColor.GREEN, ChatColor.RED, ChatColor.BLUE, + ChatColor.DARK_PURPLE, ChatColor.BLACK, ChatColor.DARK_GREEN + }; + private static final Material[] TEAM_MATERIALS = { + Material.GREEN_WOOL, Material.RED_WOOL, Material.BLUE_WOOL, + Material.PURPLE_WOOL, Material.BLACK_WOOL, Material.GREEN_WOOL + }; + + public TeamPlayerSelectionWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + int teamIndex = settings.getSelectedTeamIndex(); + Team currentTeam = settings.getTeam(teamIndex); + + for (Player online : Bukkit.getOnlinePlayers()) { + if (MinigameHandler.getOccupiedPlayers().contains(online)) continue; + + boolean inCurrentTeam = currentTeam.getPlayers().contains(online); + // Hide players already assigned to a different team + boolean inOtherTeam = settings.getSelectedPlayers().contains(online) && !inCurrentTeam; + if (inOtherTeam) continue; + + ItemStack head = makePlayerHead(online, inCurrentTeam); + NBTHelper.set(head, "Action", "clickedPlayerInTeams"); + NBTHelper.set(head, "Player", online.getName()); + add(head); + } + + ItemStack teamIndicator = makeItem(TEAM_MATERIALS[teamIndex], + TEAM_COLORS[teamIndex] + "Team #" + (teamIndex + 1)); + NBTHelper.set(teamIndicator, "Action", "none"); + place(4, teamIndicator); + + ItemStack back = makeItem(Material.ARROW, "Back"); + NBTHelper.set(back, "Action", "back"); + place(49, back); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + if (action.equals("back")) { + new TeamSetupSelectionWindow(p).buildWindow(); + return; + } + if (action.equals("clickedPlayerInTeams")) { + String playerName = NBTHelper.get(event.getCurrentItem(), "Player"); + Player target = Bukkit.getPlayer(playerName); + if (target == null) return; + Settings settings = MinigameHandler.getSettings(p); + Team team = settings.getTeam(settings.getSelectedTeamIndex()); + if (team.getPlayers().contains(target)) { + team.removePlayer(target); + settings.removePlayersFromSelection(target); + } else { + team.addPlayer(target); + settings.addPlayersToSelection(target); + } + new TeamPlayerSelectionWindow(p).buildWindow(); + } + } + + private ItemStack makePlayerHead(Player target, boolean inCurrentTeam) { + ItemStack head = new ItemStack(Material.PLAYER_HEAD); + SkullMeta meta = (SkullMeta) head.getItemMeta(); + if (meta != null) { + meta.setOwningPlayer(target); + meta.setDisplayName((inCurrentTeam ? ChatColor.GREEN : ChatColor.RED) + target.getName()); + head.setItemMeta(meta); + } + return head; + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamSetupSelectionWindow.java b/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamSetupSelectionWindow.java new file mode 100644 index 0000000..94db091 --- /dev/null +++ b/src/main/java/de/ventority/randomizedminigames/gui/windows/TeamSetupSelectionWindow.java @@ -0,0 +1,56 @@ +package de.ventority.randomizedminigames.gui.windows; + +import de.ventority.randomizedminigames.gui.BaseWindow; +import de.ventority.randomizedminigames.gui.NBTHelper; +import de.ventority.randomizedminigames.util.MinigameHandler; +import de.ventority.randomizedminigames.util.Settings; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +public class TeamSetupSelectionWindow extends BaseWindow { + private static final ChatColor[] TEAM_COLORS = { + ChatColor.GREEN, ChatColor.RED, ChatColor.BLUE, + ChatColor.DARK_PURPLE, ChatColor.BLACK, ChatColor.DARK_GREEN + }; + private static final Material[] TEAM_MATERIALS = { + Material.GREEN_WOOL, Material.RED_WOOL, Material.BLUE_WOOL, + Material.PURPLE_WOOL, Material.BLACK_WOOL, Material.GREEN_WOOL + }; + + public TeamSetupSelectionWindow(Player p) { + super(p); + } + + @Override + protected void fillGUI() { + Settings settings = MinigameHandler.getSettings(p); + for (int i = 0; i < settings.getTeamCount(); i++) { + int playerCount = settings.getTeam(i).getPlayers().size(); + String name = TEAM_COLORS[i] + "Team #" + (i + 1) + ChatColor.GRAY + " (" + playerCount + " players)"; + ItemStack item = makeItem(TEAM_MATERIALS[i], name); + NBTHelper.set(item, "Action", "selectTeam"); + NBTHelper.set(item, "selectedTeam", Integer.toString(i)); + add(item); + } + + ItemStack start = makeItem(Material.GREEN_DYE, "Start Game"); + NBTHelper.set(start, "Action", "startGame"); + place(50, start); + } + + @Override + public void handleClick(String action, InventoryClickEvent event) { + if (action.equals("selectTeam")) { + String teamIndex = NBTHelper.get(event.getCurrentItem(), "selectedTeam"); + if (teamIndex == null) return; + MinigameHandler.getSettings(p).setSelectedTeamIndex(Integer.parseInt(teamIndex)); + new TeamPlayerSelectionWindow(p).buildWindow(); + } else if (action.equals("startGame")) { + MinigameHandler.createMinigame(3, p); + p.closeInventory(); + } + } +} diff --git a/src/main/java/de/ventority/randomizedminigames/misc/ColorCycler.java b/src/main/java/de/ventority/randomizedminigames/misc/ColorCycler.java index fa651da..cf3701f 100644 --- a/src/main/java/de/ventority/randomizedminigames/misc/ColorCycler.java +++ b/src/main/java/de/ventority/randomizedminigames/misc/ColorCycler.java @@ -1,4 +1,37 @@ package de.ventority.randomizedminigames.misc; +import java.awt.Color; + public class ColorCycler { + private final Color from; + private final Color to; + private final double cyclesPerSecond; + + /** + * @param from start color of the pulse + * @param to end color of the pulse + * @param cyclesPerSecond how many full dark→light→dark cycles per second + */ + public ColorCycler(Color from, Color to, double cyclesPerSecond) { + this.from = from; + this.to = to; + this.cyclesPerSecond = cyclesPerSecond; + } + + /** + * Returns the interpolated color for a given tick (20 ticks = 1 second). + * Uses a sine wave so the transition is smooth in both directions. + */ + public Color getColor(int tick) { + double t = (Math.sin(tick * (2 * Math.PI * cyclesPerSecond / 20.0)) + 1.0) / 2.0; + return new Color( + lerp(from.getRed(), to.getRed(), t), + lerp(from.getGreen(), to.getGreen(), t), + lerp(from.getBlue(), to.getBlue(), t) + ); + } + + private static int lerp(int a, int b, double t) { + return (int) Math.round(a + (b - a) * t); + } } diff --git a/src/main/java/de/ventority/randomizedminigames/misc/Timer/Timer.java b/src/main/java/de/ventority/randomizedminigames/misc/Timer/Timer.java index fd53755..97fe4fe 100644 --- a/src/main/java/de/ventority/randomizedminigames/misc/Timer/Timer.java +++ b/src/main/java/de/ventority/randomizedminigames/misc/Timer/Timer.java @@ -2,13 +2,16 @@ package de.ventority.randomizedminigames.misc.Timer; import de.ventority.randomizedminigames.Minigames.MinigameBase; import de.ventority.randomizedminigames.RandomizedMinigames; +import de.ventority.randomizedminigames.misc.ColorCycler; import de.ventority.randomizedminigames.util.MinigameHandler; +import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import java.awt.Color; import java.util.List; @@ -23,7 +26,11 @@ public class Timer { private boolean isReversed = false; private String customText; private int countedSeconds = 0; - private String defaultText; + private final ColorCycler colorCycler = new ColorCycler( + new Color(110, 0, 145), + new Color(130, 50, 170), + 0.2 + ); public Timer(List players, MinigameBase minigame, String text) { this.players = players; @@ -49,14 +56,13 @@ public class Timer { counterTask = Bukkit.getScheduler().runTaskTimer(RandomizedMinigames.serverSettingsHandler.getPlugin(), () -> { countedSeconds = counter / 20; - updateText(); updatePlayers(); if (!isPaused) { counter++; - if (countedSeconds == stopTime && MinigameHandler.getSettings(minigame.getOwner()).isTimed) { + if (countedSeconds == stopTime) { if (methodToCall != null) methodToCall.run(); - else + else if (MinigameHandler.getSettings(minigame.getOwner()).isTimed) minigame.stopGame(); stopCounter(); } @@ -104,30 +110,11 @@ public class Timer { } private void updatePlayers() { -// int amplitude = 40; -// -// int step = counter % (amplitude * 2); -// int brightness = step <= amplitude ? step : (amplitude * 2 - step); -// -// int baseRed = 125; -// int baseGreen = 0; -// int baseBlue = 130; -// -// -// Color c = new Color( -// baseRed + 2*brightness, -// baseGreen, -// baseBlue + 2*brightness -// ); -// - TextComponent msg = new TextComponent(defaultText); -// msg.setColor(ChatColor.of(c)); - msg.setBold(true); - + TextComponent msg = new TextComponent("§l" + updateText()); + msg.setColor(ChatColor.of(colorCycler.getColor(counter))); for (Player player : players) { player.spigot().sendMessage(ChatMessageType.ACTION_BAR, msg); } - } public void setStopTime(int seconds) { diff --git a/src/main/java/de/ventority/randomizedminigames/util/MinigameHandler.java b/src/main/java/de/ventority/randomizedminigames/util/MinigameHandler.java index cc92707..6607d37 100644 --- a/src/main/java/de/ventority/randomizedminigames/util/MinigameHandler.java +++ b/src/main/java/de/ventority/randomizedminigames/util/MinigameHandler.java @@ -16,13 +16,18 @@ public class MinigameHandler { public static void createMinigame(int gameNumber, Player caller) { List players = settings.get(caller).getSelectedPlayers(); + MinigameBase newGame = null; switch (gameNumber) { - case 0: minigames.add(new ForceItemBattle(players, caller)); break; - case 1: minigames.add(new ForceItemBattleSameItems(players, caller)); break; - case 2: minigames.add(new BlockRandomizer(players, caller)); break; - case 4: minigames.add(new OnlyChests(players, caller)); break; + case 0: newGame = new ForceItemBattle(players, caller); break; + case 1: newGame = new ForceItemBattleSameItems(players, caller); break; + case 2: newGame = new BlockRandomizer(players, caller); break; + case 3: newGame = new ForceItemBattleTeams(players, caller, settings.get(caller).getTeams()); break; + case 4: newGame = new OnlyChests(players, caller); break; + } + if (newGame != null) { + minigames.add(newGame); + getServer().getPluginManager().registerEvents(newGame, RandomizedMinigames.serverSettingsHandler.getPlugin()); } - getServer().getPluginManager().registerEvents(minigames.getFirst(), RandomizedMinigames.serverSettingsHandler.getPlugin()); } public static List getMinigames() { @@ -45,7 +50,7 @@ public class MinigameHandler { } public static void killAll() { - for (MinigameBase minigame : minigames) + for (MinigameBase minigame : new ArrayList<>(minigames)) minigame.killGame(); } diff --git a/src/main/java/de/ventority/randomizedminigames/util/PlayerBackup.java b/src/main/java/de/ventority/randomizedminigames/util/PlayerBackup.java index 6b8e173..6d46f62 100644 --- a/src/main/java/de/ventority/randomizedminigames/util/PlayerBackup.java +++ b/src/main/java/de/ventority/randomizedminigames/util/PlayerBackup.java @@ -7,36 +7,35 @@ import org.bukkit.inventory.ItemStack; public class PlayerBackup { private final ItemStack[] inventory; private final ItemStack[] armor; + private final ItemStack offhand; private final float exp; + private final int level; private final Location location; - private GameMode gamemode; + private final GameMode gamemode; + private final double health; + private final int foodLevel; - public PlayerBackup(ItemStack[] inventory, ItemStack[] armor, float exp, Location location, GameMode gamemode) { + public PlayerBackup(ItemStack[] inventory, ItemStack[] armor, ItemStack offhand, + float exp, int level, Location location, GameMode gamemode, + double health, int foodLevel) { this.inventory = inventory; this.armor = armor; + this.offhand = offhand; this.exp = exp; + this.level = level; this.location = location; this.gamemode = gamemode; + this.health = health; + this.foodLevel = foodLevel; } - public ItemStack[] getInventory() { - return inventory; - } - - public ItemStack[] getArmor() { - return armor; - } - - public float getExp() { - return exp; - } - - public Location getLocation() { - return location; - } - - public GameMode getGamemode() { - return gamemode; - } - + public ItemStack[] getInventory() { return inventory; } + public ItemStack[] getArmor() { return armor; } + public ItemStack getOffhand() { return offhand; } + public float getExp() { return exp; } + public int getLevel() { return level; } + public Location getLocation() { return location; } + public GameMode getGamemode() { return gamemode; } + public double getHealth() { return health; } + public int getFoodLevel() { return foodLevel; } } diff --git a/src/main/java/de/ventority/randomizedminigames/util/PlayerBackupHandler.java b/src/main/java/de/ventority/randomizedminigames/util/PlayerBackupHandler.java index 1ccb01d..1e2c7aa 100644 --- a/src/main/java/de/ventority/randomizedminigames/util/PlayerBackupHandler.java +++ b/src/main/java/de/ventority/randomizedminigames/util/PlayerBackupHandler.java @@ -1,32 +1,91 @@ package de.ventority.randomizedminigames.util; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import java.util.Collection; import java.util.HashMap; import java.util.List; +import java.util.UUID; public class PlayerBackupHandler { - private HashMap playerBackups = new HashMap<>(); + // Backups for players currently in a minigame, keyed by UUID so they survive reconnects. + private final HashMap playerBackups = new HashMap<>(); + + // Players who were offline when killGame() ran — restored the next time they join. + private static final HashMap pendingRestores = new HashMap<>(); public PlayerBackupHandler(List players) { for (Player player : players) { - PlayerBackup backup = new PlayerBackup(player.getInventory().getContents(), player.getInventory().getArmorContents(), player.getExp(), player.getLocation(), player.getGameMode()); - playerBackups.put(player, backup); + playerBackups.put(player.getUniqueId(), new PlayerBackup( + clone(player.getInventory().getContents()), + clone(player.getInventory().getArmorContents()), + cloneItem(player.getInventory().getItemInOffHand()), + player.getExp(), + player.getLevel(), + player.getLocation(), + player.getGameMode(), + player.getHealth(), + player.getFoodLevel() + )); } } public void restorePlayerBackup(Player player) { - PlayerBackup backup = playerBackups.get(player); + PlayerBackup backup = playerBackups.get(player.getUniqueId()); + if (backup == null) return; + applyBackup(player, backup); + } + + /** + * Restores online players immediately. + * Players who are currently offline are queued in pendingRestores + * and will be restored the next time they join. + */ + public void restoreAll() { + for (UUID uuid : playerBackups.keySet()) { + Player player = Bukkit.getPlayer(uuid); + if (player != null && player.isOnline()) { + applyBackup(player, playerBackups.get(uuid)); + } else { + pendingRestores.put(uuid, playerBackups.get(uuid)); + } + } + } + + /** Called on every PlayerJoinEvent — restores any backup queued while the player was offline. */ + public static void restoreIfPending(Player player) { + PlayerBackup backup = pendingRestores.remove(player.getUniqueId()); + if (backup != null) applyBackup(player, backup); + } + + private static void applyBackup(Player player, PlayerBackup backup) { + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + Collection effects = player.getActivePotionEffects(); + for (PotionEffect effect : effects) + player.removePotionEffect(effect.getType()); + player.getInventory().setContents(backup.getInventory()); player.getInventory().setArmorContents(backup.getArmor()); + player.getInventory().setItemInOffHand(backup.getOffhand()); player.setExp(backup.getExp()); + player.setLevel(backup.getLevel()); + player.setHealth(backup.getHealth()); + player.setFoodLevel(backup.getFoodLevel()); player.teleport(backup.getLocation()); player.setGameMode(backup.getGamemode()); } - public void restoreAll() { - for (Player player : playerBackups.keySet()) { - restorePlayerBackup(player); - } + private static org.bukkit.inventory.ItemStack[] clone(org.bukkit.inventory.ItemStack[] source) { + org.bukkit.inventory.ItemStack[] copy = new org.bukkit.inventory.ItemStack[source.length]; + for (int i = 0; i < source.length; i++) + copy[i] = source[i] != null ? source[i].clone() : null; + return copy; + } + + private static org.bukkit.inventory.ItemStack cloneItem(org.bukkit.inventory.ItemStack item) { + return item != null ? item.clone() : null; } } diff --git a/src/main/java/de/ventority/randomizedminigames/util/Settings.java b/src/main/java/de/ventority/randomizedminigames/util/Settings.java index 96833cf..0e017a1 100644 --- a/src/main/java/de/ventority/randomizedminigames/util/Settings.java +++ b/src/main/java/de/ventority/randomizedminigames/util/Settings.java @@ -1,5 +1,6 @@ package de.ventority.randomizedminigames.util; +import org.bukkit.ChatColor; import org.bukkit.entity.Player; import java.util.ArrayList; @@ -88,6 +89,22 @@ public class Settings { this.timeLimit = timeLimit; } + public void initTeams() { + teams.clear(); + selectedPlayers.clear(); + ChatColor[] colors = { + ChatColor.GREEN, ChatColor.RED, ChatColor.BLUE, + ChatColor.DARK_PURPLE, ChatColor.BLACK, ChatColor.DARK_GREEN + }; + for (int i = 0; i < selectedTeamCount; i++) { + teams.add(new Team(new ArrayList<>(), colors[i])); + } + } + + public List getTeams() { + return teams; + } + public Team getTeam(int i) { return teams.get(i); } diff --git a/src/main/resources/gui/MinigameSetup.json b/src/main/resources/gui/MinigameSetup.json deleted file mode 100644 index 09e6629..0000000 --- a/src/main/resources/gui/MinigameSetup.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "title": "Minigame Setup", - "rows": 6, - "items": [ - { - "slot": -1, - "material": "PLAYER_HEAD", - "name": "Select Players", - "nbt": { - "Type": "MinigameSetup", - "Action": "startPlayerSelection" - } - }, - { - "slot": -1, - "material": "BOOK", - "name": "Set win limit", - "nbt": { - "Type": "MinigameSetup", - "Action": "startLimitSelection" - } - }, - { - "slot": -1, - "material": "EMERALD", - "name": "Scoreboard: %scoreboardState%", - "nbt": { - "Type": "MinigameSetup", - "Action": "switchScoreboard" - } - }, - { - "slot": 50, - "material": "GREEN_DYE", - "name": "Start", - "nbt": { - "Type": "MinigameSetup", - "Action": "startGame" - } - }, - { - "slot": -1, - "material": "CLOCK", - "name": "Set Timer", - "nbt": { - "Type": "MinigameSetup", - "Action": "startTimerSetup" - } - }, - { - "slot": -1, - "material": "TARGET", - "name": "Timer: %timer%", - "nbt": { - "Type": "MinigameSetup", - "Action": "toggleTimer" - } - }, - { - "slot": 49, - "material": "ARROW", - "name": "Back", - "nbt": { - "Type": "MinigameSelect", - "Action": "homeMenu" - } - } - ] -}