diff --git a/build.gradle b/build.gradle index 8904161..ea26515 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'de.winniepat' -version = '1.2' +version = '1.3' repositories { mavenCentral() @@ -12,8 +12,12 @@ repositories { maven { url = 'https://jitpack.io' } } +def mcVersion = project.findProperty('mcVersion') ?: '1.21.4-R0.1-SNAPSHOT' +def deployDir = project.findProperty('deployDir') ?: 'C:/Users/winnie/Documents/lunaris/server/plugins' +def minJavaVersion = 21 + dependencies { - compileOnly('io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT') + compileOnly("io.papermc.paper:paper-api:${mcVersion}") compileOnly('com.github.MilkBowl:VaultAPI:1.7') { exclude group: 'org.bukkit', module: 'bukkit' @@ -26,21 +30,20 @@ tasks { } } -def targetJavaVersion = 21 java { - def javaVersion = JavaVersion.toVersion(targetJavaVersion) + def javaVersion = JavaVersion.toVersion(minJavaVersion) sourceCompatibility = javaVersion targetCompatibility = javaVersion if (JavaVersion.current() < javaVersion) { - toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion) + toolchain.languageVersion = JavaLanguageVersion.of(minJavaVersion) } } tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' - if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { - options.release.set(targetJavaVersion) + if (minJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) { + options.release.set(minJavaVersion) } } @@ -55,7 +58,7 @@ processResources { build.doLast { copy { - from("$buildDir/libs/GamblingPlugin-1.2.jar") - into("C:/Users/winnie/Documents/lunaris/server/plugins") + from("$buildDir/libs/${rootProject.name}-${version}.jar") + into(deployDir) } -} \ No newline at end of file +} diff --git a/src/main/java/de/winniepat/gamblingPlugin/GamblingPlugin.java b/src/main/java/de/winniepat/gamblingPlugin/GamblingPlugin.java index 39ae03a..099f1dd 100644 --- a/src/main/java/de/winniepat/gamblingPlugin/GamblingPlugin.java +++ b/src/main/java/de/winniepat/gamblingPlugin/GamblingPlugin.java @@ -3,6 +3,7 @@ package de.winniepat.gamblingPlugin; import de.winniepat.gamblingPlugin.commands.*; import de.winniepat.gamblingPlugin.gui.*; import de.winniepat.gamblingPlugin.listeners.*; +import de.winniepat.gamblingPlugin.util.ServerVersion; import net.milkbowl.vault.economy.Economy; import org.bukkit.Bukkit; import org.bukkit.event.Listener; @@ -20,29 +21,40 @@ public final class GamblingPlugin extends JavaPlugin { public void onEnable() { instance = this; - setupEconomy(); + String serverVersion = ServerVersion.current(); + if (ServerVersion.isSupported(serverVersion)) { + getLogger().info("GamblingPlugin enabled on Minecraft " + serverVersion + + " (supported: " + ServerVersion.MIN_SUPPORTED + " - " + ServerVersion.MAX_SUPPORTED + ")."); + } else { + getLogger().warning("Running on unsupported Minecraft version " + serverVersion + + "! Supported range: " + ServerVersion.MIN_SUPPORTED + " - " + ServerVersion.MAX_SUPPORTED + + ". The plugin may not work correctly."); + } + + if (!setupEconomy()) { + getServer().getPluginManager().disablePlugin(this); + return; + } registerCommands(); registerEvents(); - - getLogger().info("GamblingPlugin enabled."); + registerListeners(); } - private void setupEconomy() { + private boolean setupEconomy() { if (getServer().getPluginManager().getPlugin("Vault") == null) { getLogger().severe("Vault not found! Disabling plugin."); - getServer().getPluginManager().disablePlugin(this); - return; + return false; } RegisteredServiceProvider rsp = getServer().getServicesManager().getRegistration(Economy.class); if (rsp == null) { getLogger().severe("No Economy provider found! Disabling plugin."); - getServer().getPluginManager().disablePlugin(this); - return; + return false; } economy = rsp.getProvider(); getLogger().info("Economy setup successful with provider: " + economy.getName()); + return true; } @@ -63,6 +75,7 @@ public final class GamblingPlugin extends JavaPlugin { private void registerListeners() { getServer().getPluginManager().registerEvents(new SlotListener(), this); getServer().getPluginManager().registerEvents(new DoubleInteractListener(), this); + getServer().getPluginManager().registerEvents(new CaseListener(), this); Bukkit.getPluginManager().registerEvents(new RouletteListener(this), this); } @@ -70,5 +83,6 @@ public final class GamblingPlugin extends JavaPlugin { Objects.requireNonNull(getCommand("slots")).setExecutor(new SlotCommand()); Objects.requireNonNull(getCommand("double")).setExecutor(new DoubleCommand()); Objects.requireNonNull(getCommand("roulette")).setExecutor(new RouletteCommand()); + Objects.requireNonNull(getCommand("case")).setExecutor(new CaseCommand()); } } diff --git a/src/main/java/de/winniepat/gamblingPlugin/animations/CaseAnimation.java b/src/main/java/de/winniepat/gamblingPlugin/animations/CaseAnimation.java index 4440c4c..73a40a9 100644 --- a/src/main/java/de/winniepat/gamblingPlugin/animations/CaseAnimation.java +++ b/src/main/java/de/winniepat/gamblingPlugin/animations/CaseAnimation.java @@ -14,12 +14,41 @@ import java.util.*; public class CaseAnimation { + private static final Set OPEN_INVENTORIES = new HashSet<>(); + private static final Set OPEN_PLAYERS = new HashSet<>(); + + public static boolean isCaseInventory(Inventory inventory) { + return inventory != null && OPEN_INVENTORIES.contains(inventory); + } + + public static boolean isCasePlayer(Player player) { + return player != null && OPEN_PLAYERS.contains(player.getUniqueId()); + } + + public static void onCaseOpened(Player player, Inventory inventory) { + if (player != null) { + OPEN_PLAYERS.add(player.getUniqueId()); + } + if (inventory != null) { + OPEN_INVENTORIES.add(inventory); + } + } + + public static void onCaseClosed(Player player, Inventory inventory) { + if (player != null) { + OPEN_PLAYERS.remove(player.getUniqueId()); + } + if (inventory != null) { + OPEN_INVENTORIES.remove(inventory); + } + } + private final Player player; private final Inventory inv; private final List possibleRewards; private final Random random = new Random(); - private final int[] slots = {0, 1, 2, 3, 4, 5, 6, 7, 8}; + private final int[] slots = {9, 10, 11, 12, 13, 14, 15, 16, 17}; private final List currentScroll = new ArrayList<>(); private int shiftCount = 0; private boolean rewardGiven = false; @@ -28,11 +57,15 @@ public class CaseAnimation { this.player = player; this.inv = Bukkit.createInventory(null, 3 * 9, "§bOpening Case..."); this.possibleRewards = getPossibleRewards(); + onCaseOpened(player, inv); } public void start() { player.openInventory(inv); + inv.setItem(4, createReward(Material.GRAY_STAINED_GLASS_PANE, "§a▼")); + inv.setItem(22, createReward(Material.GRAY_STAINED_GLASS_PANE, "§a▲")); + for (int i = 0; i < slots.length + 10; i++) { currentScroll.add(getRandomReward()); } @@ -43,11 +76,30 @@ public class CaseAnimation { private void runAnimation(int shift) { if (shift >= currentScroll.size() - slots.length) { if (!rewardGiven) { - ItemStack reward = inv.getItem(4); - player.getInventory().addItem(reward); - player.sendMessage("§aYou won: §e" + reward.getItemMeta().getDisplayName()); - player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.2f, 1.0f); + ItemStack reward = inv.getItem(13); + if (reward == null) { + player.sendMessage("§cError: could not retrieve the case reward."); + } else { + inv.clear(13); + Map leftover = player.getInventory().addItem(reward); + if (!leftover.isEmpty()) { + player.getWorld().dropItemNaturally(player.getLocation(), leftover.get(0)); + player.sendMessage("§cYour inventory was full! The reward was dropped on the ground."); + } + player.sendMessage("§aYou won: §e" + reward.getItemMeta().getDisplayName()); + player.playSound(player.getLocation(), Sound.UI_TOAST_CHALLENGE_COMPLETE, 1.2f, 1.0f); + } + for (int slot : slots) { + inv.clear(slot); + } + inv.clear(4); + inv.clear(22); rewardGiven = true; + Bukkit.getScheduler().runTaskLater(GamblingPlugin.getInstance(), () -> { + if (player.getOpenInventory().getTopInventory() == inv) { + player.closeInventory(); + } + }, 30L); } return; } diff --git a/src/main/java/de/winniepat/gamblingPlugin/commands/CaseCommand.java b/src/main/java/de/winniepat/gamblingPlugin/commands/CaseCommand.java new file mode 100644 index 0000000..32afea2 --- /dev/null +++ b/src/main/java/de/winniepat/gamblingPlugin/commands/CaseCommand.java @@ -0,0 +1,32 @@ +package de.winniepat.gamblingPlugin.commands; + +import de.winniepat.gamblingPlugin.GamblingPlugin; +import de.winniepat.gamblingPlugin.animations.CaseAnimation; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class CaseCommand implements CommandExecutor { + + private static final double COST = 50.0; + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player player)) { + sender.sendMessage("Only players can use this command."); + return true; + } + + if (GamblingPlugin.getInstance().getEconomy().getBalance(player) < COST) { + player.sendMessage("§cYou don't have enough money to open a case! §7(Required: $" + (int) COST + ")"); + return true; + } + + GamblingPlugin.getInstance().getEconomy().withdrawPlayer(player, COST); + player.sendMessage("§7Case opened: §6-$" + (int) COST); + + new CaseAnimation(player).start(); + return true; + } +} diff --git a/src/main/java/de/winniepat/gamblingPlugin/gui/DoubleGUI.java b/src/main/java/de/winniepat/gamblingPlugin/gui/DoubleGUI.java index 69e59b4..9b52b92 100644 --- a/src/main/java/de/winniepat/gamblingPlugin/gui/DoubleGUI.java +++ b/src/main/java/de/winniepat/gamblingPlugin/gui/DoubleGUI.java @@ -8,6 +8,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -119,4 +120,11 @@ public class DoubleGUI implements Listener { e.setCancelled(true); } } + + @EventHandler + public void onInventoryDrag(InventoryDragEvent e) { + if (e.getView().getTitle().equals("§aDouble or Nothing")) { + e.setCancelled(true); + } + } } diff --git a/src/main/java/de/winniepat/gamblingPlugin/gui/RouletteGUI.java b/src/main/java/de/winniepat/gamblingPlugin/gui/RouletteGUI.java index 2a4deda..a81e0aa 100644 --- a/src/main/java/de/winniepat/gamblingPlugin/gui/RouletteGUI.java +++ b/src/main/java/de/winniepat/gamblingPlugin/gui/RouletteGUI.java @@ -8,6 +8,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -77,6 +78,13 @@ public class RouletteGUI implements Listener { } } + @EventHandler + public void onInventoryDrag(InventoryDragEvent e) { + if (e.getView().getTitle().startsWith("Roulette: ")) { + e.setCancelled(true); + } + } + @EventHandler public void onInventoryClose(InventoryCloseEvent e) { Player player = (Player) e.getPlayer(); diff --git a/src/main/java/de/winniepat/gamblingPlugin/gui/SlotGUI.java b/src/main/java/de/winniepat/gamblingPlugin/gui/SlotGUI.java index c1ffacf..cd34e80 100644 --- a/src/main/java/de/winniepat/gamblingPlugin/gui/SlotGUI.java +++ b/src/main/java/de/winniepat/gamblingPlugin/gui/SlotGUI.java @@ -7,6 +7,7 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -153,8 +154,19 @@ public class SlotGUI implements Listener { @EventHandler public void onInventoryClick(InventoryClickEvent e) { String title = e.getView().getTitle(); + Player player = (Player) e.getWhoClicked(); - if (title.equals("Choose a Color to Bet") || title.startsWith("Roulette: ")) { + if (title.equals("§6Slot Machine") + || title.equals("Choose a Color to Bet") + || title.startsWith("Roulette: ") + || roulettePlayers.contains(player.getUniqueId())) { + e.setCancelled(true); + } + } + + @EventHandler + public void onInventoryDrag(InventoryDragEvent e) { + if (e.getView().getTitle().equals("§6Slot Machine")) { e.setCancelled(true); } } diff --git a/src/main/java/de/winniepat/gamblingPlugin/listeners/CaseListener.java b/src/main/java/de/winniepat/gamblingPlugin/listeners/CaseListener.java new file mode 100644 index 0000000..2198379 --- /dev/null +++ b/src/main/java/de/winniepat/gamblingPlugin/listeners/CaseListener.java @@ -0,0 +1,38 @@ +package de.winniepat.gamblingPlugin.listeners; + +import de.winniepat.gamblingPlugin.animations.CaseAnimation; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryDragEvent; +import org.bukkit.inventory.InventoryView; + +public class CaseListener implements Listener { + + @EventHandler + public void onInventoryClick(InventoryClickEvent e) { + if (isCaseView(e.getView(), e.getWhoClicked() instanceof Player player ? player : null)) { + e.setCancelled(true); + } + } + + @EventHandler + public void onInventoryDrag(InventoryDragEvent e) { + if (isCaseView(e.getView(), e.getWhoClicked() instanceof Player player ? player : null)) { + e.setCancelled(true); + } + } + + @EventHandler + public void onInventoryClose(InventoryCloseEvent e) { + CaseAnimation.onCaseClosed(e.getPlayer() instanceof Player player ? player : null, e.getView().getTopInventory()); + } + + private boolean isCaseView(InventoryView view, Player player) { + return CaseAnimation.isCasePlayer(player) + || CaseAnimation.isCaseInventory(view.getTopInventory()) + || view.getTitle().equals("§bOpening Case..."); + } +} diff --git a/src/main/java/de/winniepat/gamblingPlugin/listeners/RouletteListener.java b/src/main/java/de/winniepat/gamblingPlugin/listeners/RouletteListener.java index a30e5c7..3e56d6d 100644 --- a/src/main/java/de/winniepat/gamblingPlugin/listeners/RouletteListener.java +++ b/src/main/java/de/winniepat/gamblingPlugin/listeners/RouletteListener.java @@ -78,11 +78,14 @@ public class RouletteListener implements Listener { Material result = originalItems[finalIndex].getType(); if (result == betColor) { - int multiplier = switch (result) { - case GREEN_WOOL -> 14; - case RED_WOOL, BLACK_WOOL -> 2; - default -> 0; - }; + int multiplier; + if (result == Material.GREEN_WOOL) { + multiplier = 14; + } else if (result == Material.RED_WOOL || result == Material.BLACK_WOOL) { + multiplier = 2; + } else { + multiplier = 0; + } double winnings = betCost * multiplier; GamblingPlugin.getInstance().getEconomy().depositPlayer(player, winnings); diff --git a/src/main/java/de/winniepat/gamblingPlugin/util/ServerVersion.java b/src/main/java/de/winniepat/gamblingPlugin/util/ServerVersion.java new file mode 100644 index 0000000..f1b8f13 --- /dev/null +++ b/src/main/java/de/winniepat/gamblingPlugin/util/ServerVersion.java @@ -0,0 +1,45 @@ +package de.winniepat.gamblingPlugin.util; + +import org.bukkit.Bukkit; + +public final class ServerVersion { + + public static final String MIN_SUPPORTED = "1.21.4"; + public static final String MAX_SUPPORTED = "26.1.2"; + + private ServerVersion() { + } + + public static String current() { + return Bukkit.getMinecraftVersion(); + } + + public static boolean isSupported() { + return isSupported(current()); + } + + public static boolean isSupported(String version) { + int[] v = parse(version); + return compare(v, parse(MIN_SUPPORTED)) >= 0 && compare(v, parse(MAX_SUPPORTED)) <= 0; + } + + private static int compare(int[] a, int[] b) { + for (int i = 0; i < 3; i++) { + int diff = Integer.compare(a[i], b[i]); + if (diff != 0) return diff; + } + return 0; + } + + private static int[] parse(String version) { + int[] parts = new int[3]; + String[] split = version.split("\\."); + for (int i = 0; i < split.length && i < 3; i++) { + try { + parts[i] = Integer.parseInt(split[i]); + } catch (NumberFormatException ignored) { + } + } + return parts; + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 835ce4d..f35ae27 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,5 +1,5 @@ name: GamblingPlugin -version: '1.1' +version: '${version}' main: de.winniepat.gamblingPlugin.GamblingPlugin api-version: '1.21' load: STARTUP