package hdvtdev.blockAndSeek.roulette; import hdvtdev.blockAndSeek.BlockAndSeek; import hdvtdev.blockAndSeek.BlockAndSeekMap; import hdvtdev.blockAndSeek.Localization; import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Random; public final class RouletteCreator implements InventoryHolder { private static final int[] slots = {3, 5, 7, 12, 14, 16, 21, 23, 25, 30, 32, 34, 39, 41, 43}; private static final int[] midSlots = {21, 23, 25}; private static final Random random = new Random(); private final Inventory roulette; private Task task; private volatile Boolean closedByPlayer = true; public RouletteCreator(@NotNull Player player, List blocks) { roulette = Bukkit.createInventory(this, 45, Localization.getComponent(player, "roulette-title")); this.createUnoptimizedRoulette(roulette, player, blocks); } public @NotNull Task getTask() { return task; } public @Nullable Boolean isClosedByPlayer() { return closedByPlayer; } @Override public @NotNull Inventory getInventory() { return roulette; } public void closeInventoryBySystem() { closedByPlayer = false; roulette.close(); } public void closeInventory() { closedByPlayer = null; roulette.close(); } public ItemStack randomPropItem() { return roulette.getItem(slots[random.nextInt(0, 15)]); } public ItemStack randomMidPropItem() { return roulette.getItem(midSlots[random.nextInt(0, 3)]); } @ApiStatus.Experimental private void createUnoptimizedRoulette(Inventory gui, Player player, List blocks) { BukkitTask rouletteTask = new BukkitRunnable() { final RouletteGenerator rouletteGenerator = new RouletteGenerator(blocks); final List> rows = List.of( new RouletteList<>(rouletteGenerator.getRandomRow(15)), new RouletteList<>(rouletteGenerator.getRandomRow(15)), new RouletteList<>(rouletteGenerator.getRandomRow(15)) ); final List items; { List rawItems = new ArrayList<>(); for (int j = 0; j < 3; j++) { ItemStack[] itemStacks = new ItemStack[5]; for (int l = 0; l < 5; l++) { itemStacks[l] = rows.get(j).next(); } rawItems.add(j, itemStacks); } items = rawItems; } final long startTime = System.currentTimeMillis(); double currentSpeed = 0; int i = 0; @Override public void run() { long now = System.currentTimeMillis(); double elapsed = (now - startTime) / 1000.0; if (elapsed >= 5) { this.cancel(); } double speed; if (elapsed < 2) speed = 1.0; else if (elapsed < 2.2) speed = 0.8; else if (elapsed < 2.4) speed = 0.6; else if (elapsed < 2.6) speed = 0.5; else if (elapsed < 2.8) speed = 0.4; else if (elapsed < 3) speed = 0.33; else if (elapsed < 3.2) speed = 0.28; else if (elapsed < 3.5) speed = 0.22; else if (elapsed < 3.8) speed = 0.15; else speed = 0.1; task(speed); i++; } private void task(double speed) { if (currentSpeed >= 1) { currentSpeed = 0; for (int j = 0; j < 5; j++) { gui.setItem(3 + j * 9, items.getFirst()[j]); gui.setItem(5 + j * 9, items.get(1)[j]); gui.setItem(7 + j * 9, items.get(2)[j]); } player.playSound(player.getLocation(), Sound.UI_BUTTON_CLICK, 0.5f, 2f); for (int j = 4; j >= 1; j--) { items.getFirst()[j] = items.getFirst()[j - 1]; items.get(1)[j] = items.get(1)[j - 1]; items.get(2)[j] = items.get(2)[j - 1]; } items.getFirst()[0] = rows.getFirst().next(); items.get(1)[0] = rows.get(1).next(); items.get(2)[0] = rows.get(2).next(); } else currentSpeed += speed; } }.runTaskTimer(BlockAndSeek.getInstance(), 0, 1); task = new Task(rouletteTask, Bukkit.getScheduler().runTaskLater(BlockAndSeek.getInstance(), this::closeInventoryBySystem, 300)); player.openInventory(gui); } public record Task(BukkitTask rouletteTask, BukkitTask autoCloseTask) { public void cancelBoth() { rouletteTask.cancel(); autoCloseTask.cancel(); } } }