commit 469cbcbea560958fcc77492192b20015033edf69 Author: Matheus Date: Sat Mar 9 14:34:58 2024 -0400 Upload everything :P diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/discord.xml b/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..4418ef3 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..910b3e1 --- /dev/null +++ b/pom.xml @@ -0,0 +1,97 @@ + + + 4.0.0 + + dev.lugami.otaku + Otaku + 1.0-SNAPSHOT + + + 8 + 8 + UTF-8 + + + + + org.spigotmc + spigot + 1.8.8-R0.1-SNAPSHOT + provided + + + org.projectlombok + lombok + 1.18.20 + provided + + + org.spigotmc + plugin-annotations + 1.2.3-SNAPSHOT + provided + + + com.qrakn + honcho + 1.0-SNAPSHOT + compile + + + com.comphenix.protocol + ProtocolLib + 4.7.0 + provided + + + + + + dmulloy2-repo + https://repo.dmulloy2.net/repository/public/ + + + + + clean install + Otaku + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 3.0.0 + + false + false + + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/Constants.java b/src/main/java/dev/lugami/otaku/Constants.java new file mode 100644 index 0000000..801b7b8 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/Constants.java @@ -0,0 +1,28 @@ +package dev.lugami.otaku; + +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.menu.Button; +import lombok.Getter; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Random; + +public class Constants { + + @Getter + private static final Random random = new Random(); + + @Getter + private static final Button placeholder = new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.STAINED_GLASS_PANE) + .durability(15) + .name(" ") + .build(); + } + }; + +} diff --git a/src/main/java/dev/lugami/otaku/Main.java b/src/main/java/dev/lugami/otaku/Main.java new file mode 100644 index 0000000..8516a21 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/Main.java @@ -0,0 +1,74 @@ +package dev.lugami.otaku; + +import com.qrakn.honcho.Honcho; +import dev.lugami.otaku.board.Board; +import dev.lugami.otaku.commands.*; +import dev.lugami.otaku.commands.kit.*; +import dev.lugami.otaku.essentials.Essentials; +import dev.lugami.otaku.hotbar.Hotbar; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.listener.FFAListener; +import dev.lugami.otaku.listener.Listeners; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.ProfileListener; +import dev.lugami.otaku.utils.CombatManager; +import dev.lugami.otaku.utils.EnderpearlManager; +import dev.lugami.otaku.utils.board.Assemble; +import dev.lugami.otaku.utils.board.AssembleStyle; +import dev.lugami.otaku.utils.config.BasicConfigurationFile; +import dev.lugami.otaku.utils.menu.MenuListener; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.plugin.java.annotation.plugin.Plugin; +import org.bukkit.plugin.java.annotation.plugin.author.Author; + +import java.util.Arrays; + +@Plugin(name = "Otaku", version = "${project.version}") +@Author("Lugami") +public class Main extends JavaPlugin { + + @Getter @Setter private static Main instance; + @Getter private BasicConfigurationFile mainConfig; + @Getter private BasicConfigurationFile scoreboardConfig; + @Getter private BasicConfigurationFile profileConfig; + @Getter private BasicConfigurationFile kitsConfig; + @Getter @Setter private Honcho honcho; + @Getter private Essentials essentials; + @Getter private Assemble board; + @Getter private CombatManager combatManager; + @Getter private EnderpearlManager enderpearlManager; + + public void onEnable() { + setInstance(this); + honcho = new Honcho(this); + mainConfig = new BasicConfigurationFile(this, "config"); + essentials = new Essentials(this); + scoreboardConfig = new BasicConfigurationFile(this, "scoreboard"); + profileConfig = new BasicConfigurationFile(this, "profiles"); + kitsConfig = new BasicConfigurationFile(this, "kits"); + board = new Assemble(this, new Board(), 2, false, AssembleStyle.MODIFIED, true); + combatManager = new CombatManager(); + combatManager.runTaskTimer(this, 0, 2); + enderpearlManager = new EnderpearlManager(); + enderpearlManager.runTaskTimer(this, 0, 2); + Kit.init(); + Hotbar.init(); + Arrays.asList(new FFAListener(), new Listeners(), new ProfileListener(), new MenuListener()).forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, this)); + Arrays.asList(new FFACommand(), new FFASetSpawnCommand(), new KitSetIconCommand(), new KitCreateCommand(), new KitDeleteCommand(), new KitGetLoadoutCommand(), new KitSetLoadoutCommand(), new KitsCommand(), new KitSetLocationCommand(), new MainMenuCommand(), new FFAJoinCommand(), new FFAQuitCommand(), new KitCommand(), new ReKitCommand()).forEach(command -> honcho.registerCommand(command)); + getServer().getWorlds().forEach(essentials::clearEntities); + } + + @Override + public void onDisable() { + for (Player player : getServer().getOnlinePlayers()) { + player.kickPlayer("Server restarting"); + } + Kit.saveAll(); + //Profile.saveAll(); + Profile.removeAll(); + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/board/Board.java b/src/main/java/dev/lugami/otaku/board/Board.java new file mode 100644 index 0000000..8be3e9b --- /dev/null +++ b/src/main/java/dev/lugami/otaku/board/Board.java @@ -0,0 +1,75 @@ +package dev.lugami.otaku.board; + +import com.google.common.collect.Lists; +import dev.lugami.otaku.Main; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.PlayerCache; +import dev.lugami.otaku.utils.board.AssembleAdapter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.List; + +public class Board implements AssembleAdapter { + @Override + public String getTitle(Player player) { + return CC.translate(Main.getInstance().getScoreboardConfig().getString("scoreboard.global.title")); + } + + @Override + public List getLines(Player player) { + List strings = Lists.newArrayList(); + Profile profile = Profile.getOrCreate(player); + if (profile == null) { + strings.addAll(CC.translate(Main.getInstance().getScoreboardConfig().getStringList("scoreboard.profile"))); + } else { + if (!profile.getSettings().scoreboard()) { + return null; + } + switch (profile.getState()) { + case LOBBY: + for (String s : Main.getInstance().getScoreboardConfig().getStringList("scoreboard.lobby")) { + if (s.equals("") && !Main.getInstance().getCombatManager().isInCombat(player) + || s.equals("") && !Main.getInstance().getEnderpearlManager().isPearlCooldown(player)) continue; + strings.add(providePlaceholders(s, player)); + } + break; + case PLAYING: + for (String s : Main.getInstance().getScoreboardConfig().getStringList("scoreboard.ffa")) { + if (s.equals("") && !Main.getInstance().getCombatManager().isInCombat(player) + || s.equals("") && !Main.getInstance().getEnderpearlManager().isPearlCooldown(player)) continue; + strings.add(providePlaceholders(s, player)); + } + break; + } + } + return strings; + } + + private String providePlaceholders(String s, Player player) { + final String COMBAT_PLACEHOLDER = ""; + final String PEARL_PLACEHOLDER = ""; + Profile profile = Profile.getOrCreate(player); + if (profile == null) return null; + + if (s.equals(COMBAT_PLACEHOLDER) && Main.getInstance().getCombatManager().isInCombat(player)) { + String combatAddition = Main.getInstance().getScoreboardConfig().getString("scoreboard.combat-addition"); + String seconds = String.valueOf(Main.getInstance().getCombatManager().getCombatTime(player)); + s = s.replace(COMBAT_PLACEHOLDER, combatAddition.replace("", seconds)); + } else if (s.equals(PEARL_PLACEHOLDER) && Main.getInstance().getEnderpearlManager().isPearlCooldown(player)) { + String pearlAddition = Main.getInstance().getScoreboardConfig().getString("scoreboard.enderpearl-addition"); + String seconds = String.valueOf(Main.getInstance().getEnderpearlManager().getPearlCooldown(player)); + s = s.replace(PEARL_PLACEHOLDER, pearlAddition.replace("", seconds)); + } else if (profile.getState() == ProfileState.PLAYING && profile.getFFA() != null) { + s = s.replace("", String.valueOf(profile.getKitData().get(profile.getFFA()).kills())) + .replace("", String.valueOf(profile.getKitData().get(profile.getFFA()).deaths())) + .replace("", String.valueOf(profile.getKitData().get(profile.getFFA()).killstreak())); + } + + return CC.translate(s) + .replace("", String.valueOf(Bukkit.getOnlinePlayers().size())) + .replace("", String.valueOf(PlayerCache.getInFFA())); + } +} diff --git a/src/main/java/dev/lugami/otaku/commands/FFACommand.java b/src/main/java/dev/lugami/otaku/commands/FFACommand.java new file mode 100644 index 0000000..52669a2 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/FFACommand.java @@ -0,0 +1,18 @@ +package dev.lugami.otaku.commands; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "ffa") +public class FFACommand { + + public void execute(Player player) { + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&b/ffa join &7")); + player.sendMessage(CC.translate("&b/ffa leave")); + if (player.hasPermission("otaku.admin")) player.sendMessage(CC.translate("&b/ffa setspawn")); + player.sendMessage(CC.CHAT_BAR); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/FFAJoinCommand.java b/src/main/java/dev/lugami/otaku/commands/FFAJoinCommand.java new file mode 100644 index 0000000..1bc3166 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/FFAJoinCommand.java @@ -0,0 +1,28 @@ +package dev.lugami.otaku.commands; + +import com.qrakn.honcho.command.CPL; +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.events.FFAJoinEvent; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = {"ffa join", "ffa enter"}) +public class FFAJoinCommand { + + public void execute(Player player, @CPL("kit") String kit) { + if (Kit.getByName(kit) == null) { + player.sendMessage(CC.RED + "A kit with that name does not exist."); + return; + } + if (Profile.getOrCreate(player).getState() != ProfileState.PLAYING) { + FFAJoinEvent event = new FFAJoinEvent(player, Kit.getByName(kit)); + event.call(); + } else { + player.sendMessage(CC.RED + "You're already on the FFA."); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/FFAQuitCommand.java b/src/main/java/dev/lugami/otaku/commands/FFAQuitCommand.java new file mode 100644 index 0000000..ca84308 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/FFAQuitCommand.java @@ -0,0 +1,27 @@ +package dev.lugami.otaku.commands; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.Main; +import dev.lugami.otaku.events.FFAQuitEvent; +import dev.lugami.otaku.hotbar.Hotbar; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import org.bukkit.entity.Player; + +@CommandMeta(label = {"ffa leave", "ffa quit", "spawn"}) +public class FFAQuitCommand { + + public void execute(Player player) { + if (Profile.getOrCreate(player).getState() == ProfileState.PLAYING) { + FFAQuitEvent event = new FFAQuitEvent(player); + event.call(); + } else { + if (Hotbar.setup(player) && Main.getInstance().getEssentials().getSpawn() != null) { + Main.getInstance().getEssentials().teleportToSpawn(player); + Main.getInstance().getServer().getLogger().info("Player " + player.getName() + " was setupped correctly!"); + Profile.getOrCreate(player).setState(ProfileState.LOBBY); + } + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/FFASetSpawnCommand.java b/src/main/java/dev/lugami/otaku/commands/FFASetSpawnCommand.java new file mode 100644 index 0000000..014f563 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/FFASetSpawnCommand.java @@ -0,0 +1,15 @@ +package dev.lugami.otaku.commands; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.Main; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "ffa setspawn", permission = "otaku.admin") +public class FFASetSpawnCommand { + + public void execute(Player player) { + Main.getInstance().getEssentials().setSpawn(player.getLocation()); + player.sendMessage(CC.GREEN + "The spawn was set!"); + } +} diff --git a/src/main/java/dev/lugami/otaku/commands/MainMenuCommand.java b/src/main/java/dev/lugami/otaku/commands/MainMenuCommand.java new file mode 100644 index 0000000..98d68cc --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/MainMenuCommand.java @@ -0,0 +1,14 @@ +package dev.lugami.otaku.commands; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.menu.MainMenu; +import org.bukkit.entity.Player; + +@CommandMeta(label = {"menu", "mainmenu"}) +public class MainMenuCommand { + + public void execute(Player player) { + new MainMenu().openMenu(player); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/ReKitCommand.java b/src/main/java/dev/lugami/otaku/commands/ReKitCommand.java new file mode 100644 index 0000000..4dc9370 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/ReKitCommand.java @@ -0,0 +1,22 @@ +package dev.lugami.otaku.commands; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.events.FFAReKitEvent; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "rekit") +public class ReKitCommand { + + public void execute(Player player) { + Profile profile = Profile.getOrCreate(player); + if (profile.getState() != ProfileState.PLAYING || profile.getFFA() == null) { + player.sendMessage(CC.RED + "You're not playing on the FFA"); + return; + } + (new FFAReKitEvent(player, profile.getFFA(), false)).call(); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitCommand.java new file mode 100644 index 0000000..6cd5afe --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitCommand.java @@ -0,0 +1,22 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "kit", permission = "otaku.kit") +public class KitCommand { + + public void execute(Player player) { + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&b/kit create &7")); + player.sendMessage(CC.translate("&b/kit delete &7")); + player.sendMessage(CC.translate("&b/kit getloadout &7")); + player.sendMessage(CC.translate("&b/kit setloadout &7")); + player.sendMessage(CC.translate("&b/kit seticon &7")); + player.sendMessage(CC.translate("&b/kit setlocation &7")); + player.sendMessage(CC.translate("&b/kits")); + player.sendMessage(CC.CHAT_BAR); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitCreateCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitCreateCommand.java new file mode 100644 index 0000000..5b48d30 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitCreateCommand.java @@ -0,0 +1,26 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CPL; +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "kit create", permission = "otaku.kit.create") +public class KitCreateCommand { + + public void execute(Player player, @CPL("name") String kitName) { + if (Kit.getByName(kitName) != null) { + player.sendMessage(CC.RED + "A kit with that name already exists."); + return; + } + + Kit kit = new Kit(kitName); + kit.save(); + + Kit.getKits().add(kit); + + player.sendMessage(CC.GREEN + "You created a new kit."); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitDeleteCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitDeleteCommand.java new file mode 100644 index 0000000..adefd61 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitDeleteCommand.java @@ -0,0 +1,20 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "kit delete", permission = "otaku.kit.delete") +public class KitDeleteCommand { + public void execute(Player player, Kit kit) { + if (kit == null) { + player.sendMessage(CC.RED + "A kit with that name does not exist."); + return; + } + + kit.delete(); + + player.sendMessage(CC.GREEN + "You removed a kit."); + } +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitGetLoadoutCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitGetLoadoutCommand.java new file mode 100644 index 0000000..c13620e --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitGetLoadoutCommand.java @@ -0,0 +1,25 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CPL; +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "kit getloadout", permission = "otaku.kit.getloadout") +public class KitGetLoadoutCommand { + + public void execute(Player player, @CPL("kit") String kit) { + if (Kit.getByName(kit) == null) { + player.sendMessage(CC.RED + "A kit with that name does not exist."); + return; + } + + player.getInventory().setArmorContents(Kit.getByName(kit).getKitLoadout().getArmor()); + player.getInventory().setContents(Kit.getByName(kit).getKitLoadout().getContents()); + player.updateInventory(); + + player.sendMessage(CC.GREEN + "You received the kit's loadout."); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitSetIconCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitSetIconCommand.java new file mode 100644 index 0000000..98acfba --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitSetIconCommand.java @@ -0,0 +1,24 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CPL; +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "kit seticon", permission = "otaku.kit.seticon") +public class KitSetIconCommand { + + public void execute(Player player, @CPL("kit") String kit) { + if (Kit.getByName(kit) == null) { + player.sendMessage(CC.RED + "A kit with that name does not exist."); + return; + } + + Kit.getByName(kit).setDisplayIcon(player.getItemInHand()); + Kit.getByName(kit).save(); + + player.sendMessage(CC.GREEN + "You updated the kit's icon."); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitSetLoadoutCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitSetLoadoutCommand.java new file mode 100644 index 0000000..0771ee4 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitSetLoadoutCommand.java @@ -0,0 +1,25 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CPL; +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.CC; +import org.bukkit.entity.Player; + +@CommandMeta(label = "kit setloadout", permission = "otaku.kit.setloadout") +public class KitSetLoadoutCommand { + + public void execute(Player player, @CPL("kit") String kit) { + if (Kit.getByName(kit) == null) { + player.sendMessage(CC.RED + "A kit with that name does not exist."); + return; + } + + Kit.getByName(kit).getKitLoadout().setArmor(player.getInventory().getArmorContents()); + Kit.getByName(kit).getKitLoadout().setContents(player.getInventory().getContents()); + Kit.getByName(kit).save(); + + player.sendMessage(CC.GREEN + "You updated the kit's loadout."); + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitSetLocationCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitSetLocationCommand.java new file mode 100644 index 0000000..4eda5bd --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitSetLocationCommand.java @@ -0,0 +1,26 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CPL; +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.LocationUtil; +import org.bukkit.entity.Player; + +import java.util.Objects; + +@CommandMeta(label = "kit setlocation", permission = "otaku.kit.setlocation") +public class KitSetLocationCommand { + + public void execute(Player player, @CPL("kit") String kit) { + if (Kit.getByName(kit) == null) { + player.sendMessage(CC.RED + "A kit with that name does not exist."); + return; + } else { + Kit.getByName(kit).setLocation(player.getLocation()); + player.sendMessage(CC.GREEN + "The location for " + kit + " has been set!"); + Kit.getByName(kit).save(); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/commands/kit/KitsCommand.java b/src/main/java/dev/lugami/otaku/commands/kit/KitsCommand.java new file mode 100644 index 0000000..a82be5b --- /dev/null +++ b/src/main/java/dev/lugami/otaku/commands/kit/KitsCommand.java @@ -0,0 +1,19 @@ +package dev.lugami.otaku.commands.kit; + +import com.qrakn.honcho.command.CommandMeta; +import dev.lugami.otaku.kit.Kit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +@CommandMeta(label = "kits", permission = "otaku.admin.kit") +public class KitsCommand { + + public void execute(CommandSender sender) { + sender.sendMessage(ChatColor.GOLD + "Kits: "); + + for (Kit kit : Kit.getKits()) { + sender.sendMessage("- " + kit.getName()); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/essentials/Essentials.java b/src/main/java/dev/lugami/otaku/essentials/Essentials.java new file mode 100644 index 0000000..aff4bb8 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/essentials/Essentials.java @@ -0,0 +1,124 @@ +package dev.lugami.otaku.essentials; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.essentials.event.SpawnTeleportEvent; +import dev.lugami.otaku.utils.LocationUtil; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; + +import java.io.IOException; + +public class Essentials { + + private final Main plugin; + @Getter + private Location spawn; + + public Essentials(Main plugin) { + this.plugin = plugin; + this.spawn = LocationUtil.deserialize(plugin.getMainConfig().getStringOrDefault("ESSENTIAL.SPAWN_LOCATION", null)); + plugin.getServer().getPluginManager().registerEvents(new EssentialsListener(), plugin); + } + + public void setSpawn(Location location) { + spawn = location; + + if (spawn == null) { + plugin.getMainConfig().getConfiguration().set("ESSENTIAL.SPAWN_LOCATION", null); + } else { + plugin.getMainConfig().getConfiguration().set("ESSENTIAL.SPAWN_LOCATION", LocationUtil.serialize(this.spawn)); + } + + try { + plugin.getMainConfig().getConfiguration().save(plugin.getMainConfig().getFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void teleportToSpawn(Player player) { + Location location = spawn == null ? plugin.getServer().getWorlds().get(0).getSpawnLocation() : spawn; + + SpawnTeleportEvent event = new SpawnTeleportEvent(player, location); + event.call(); + + if (!event.isCancelled() && event.getLocation() != null) { + player.teleport(location); + player.getLocation().setPitch(location.getPitch()); + player.getLocation().setYaw(location.getYaw()); + } + } + + public void clearEntities(World world) { + int removed = 0; + + for (Entity entity : world.getEntities()) { + if (entity instanceof Item) { + removed++; + entity.remove(); + continue; + } + if (entity.getType() == EntityType.PLAYER) { + continue; + } + + removed++; + entity.remove(); + } + for (Chunk chunk : world.getLoadedChunks()) { + if (!chunk.isLoaded()) { + chunk.load(); + } + for (Entity entity : chunk.getEntities()) { + if (entity.getType() == EntityType.PLAYER) { + continue; + } + if (entity instanceof Item) { + removed++; + entity.remove(); + continue; + } + + removed++; + entity.remove(); + } + } + Bukkit.getLogger().info("Cleared up " + removed + " entities on world \"" + world.getName() + "\""); + } + + public int clearEntities(World world, EntityType... excluded) { + int removed = 0; + + entityLoop: + for (Entity entity : world.getEntities()) { + if (entity instanceof Item) { + removed++; + entity.remove(); + continue; + } + + for (EntityType type : excluded) { + if (entity.getType() == EntityType.PLAYER) { + continue entityLoop; + } + + if (entity.getType() == type) { + continue entityLoop; + } + } + + removed++; + entity.remove(); + } + + return removed; + } + +} diff --git a/src/main/java/dev/lugami/otaku/essentials/EssentialsListener.java b/src/main/java/dev/lugami/otaku/essentials/EssentialsListener.java new file mode 100644 index 0000000..67b3c87 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/essentials/EssentialsListener.java @@ -0,0 +1,116 @@ +package dev.lugami.otaku.essentials; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.hotbar.Hotbar; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.CC; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; +import org.bukkit.event.world.ChunkUnloadEvent; + +import java.util.Arrays; +import java.util.List; + +public class EssentialsListener implements Listener { + + private static List BLOCKED_COMMANDS = Arrays.asList( + "//calc", + "//eval", + "//solve", + "/bukkit:", + "/me", + "/pl", + "/plugins", + "/bukkit:me", + "/minecraft:", + "/minecraft:me", + "/version", + "/ver" + ); + + @EventHandler(priority = EventPriority.LOWEST) + public void onCommandProcess(PlayerCommandPreprocessEvent event) { + Player player = event.getPlayer(); + String[] commandParts = event.getMessage().substring(1).split(" "); // Split the command into individual words + + for (String blockedCommand : BLOCKED_COMMANDS) { + for (String part : commandParts) { + if (part.startsWith(blockedCommand)) { + // Check for exact matches only + if (part.equalsIgnoreCase(blockedCommand)) { + if (blockedCommand.equalsIgnoreCase("/version") || blockedCommand.equalsIgnoreCase("/ver")) { + if (event.getPlayer().isOp()) { + return; + } + } + + player.sendMessage(CC.RED + "You cannot perform this command."); + event.setCancelled(true); + return; + } + } + } + } + } + + @EventHandler + public void onChunkUnload(ChunkUnloadEvent e) { + e.setCancelled(true); + } + + @EventHandler + public void onPlayerDropItemEvent(PlayerDropItemEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + + if (profile.getState() != ProfileState.PLAYING) { + if (event.getPlayer().getGameMode() != GameMode.CREATIVE || !event.getPlayer().isOp()) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerItemDamageEvent(PlayerItemDamageEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + + if (profile.getState() == ProfileState.LOBBY) { + event.setCancelled(true); + } + } + + @EventHandler + public void onEntityDamageEvent(EntityDamageEvent event) { + if (event.getEntity() instanceof Player) { + Profile profile = Profile.getOrCreate((Player) event.getEntity()); + + if (profile.getState() == ProfileState.LOBBY) { + event.setCancelled(true); + + if (event.getCause() == EntityDamageEvent.DamageCause.VOID) { + if (Hotbar.setup((Player) event.getEntity()) && Main.getInstance().getEssentials().getSpawn() != null) { + Main.getInstance().getEssentials().teleportToSpawn((Player) event.getEntity()); + Main.getInstance().getServer().getLogger().info("Player " + event.getEntity().getName() + " was setupped correctly!"); + Profile.getOrCreate((Player) event.getEntity()).setState(ProfileState.LOBBY); + } + } + } else { + Kit kit = profile.getFFA(); + if (kit.getKitRules().isNoDamage()) { + event.setDamage(0.0); + } else if (kit.getKitRules().isNoFall() && event.getCause() == EntityDamageEvent.DamageCause.VOID) { + event.setCancelled(true); + } + } + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/essentials/event/SpawnTeleportEvent.java b/src/main/java/dev/lugami/otaku/essentials/event/SpawnTeleportEvent.java new file mode 100644 index 0000000..77d3144 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/essentials/event/SpawnTeleportEvent.java @@ -0,0 +1,22 @@ +package dev.lugami.otaku.essentials.event; + +import dev.lugami.otaku.utils.BaseEvent; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +@Getter +public class SpawnTeleportEvent extends BaseEvent implements Cancellable { + + private final Player player; + @Setter private Location location; + @Setter private boolean cancelled; + + public SpawnTeleportEvent(Player player, Location location) { + this.player = player; + this.location = location; + } + +} diff --git a/src/main/java/dev/lugami/otaku/events/FFAJoinEvent.java b/src/main/java/dev/lugami/otaku/events/FFAJoinEvent.java new file mode 100644 index 0000000..6fd3cd8 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/events/FFAJoinEvent.java @@ -0,0 +1,17 @@ +package dev.lugami.otaku.events; + +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.PlayerEvent; +import lombok.Getter; +import org.bukkit.entity.Player; + +@Getter +public class FFAJoinEvent extends PlayerEvent { + + private Kit kit; + + public FFAJoinEvent(Player player, Kit k) { + super(player); + this.kit = k; + } +} diff --git a/src/main/java/dev/lugami/otaku/events/FFAQuitEvent.java b/src/main/java/dev/lugami/otaku/events/FFAQuitEvent.java new file mode 100644 index 0000000..566e306 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/events/FFAQuitEvent.java @@ -0,0 +1,11 @@ +package dev.lugami.otaku.events; + +import dev.lugami.otaku.utils.PlayerEvent; +import org.bukkit.entity.Player; + +public class FFAQuitEvent extends PlayerEvent { + + public FFAQuitEvent(Player player) { + super(player); + } +} diff --git a/src/main/java/dev/lugami/otaku/events/FFAReKitEvent.java b/src/main/java/dev/lugami/otaku/events/FFAReKitEvent.java new file mode 100644 index 0000000..72ba8da --- /dev/null +++ b/src/main/java/dev/lugami/otaku/events/FFAReKitEvent.java @@ -0,0 +1,31 @@ +package dev.lugami.otaku.events; + +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.utils.PlayerEvent; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +@Getter +public class FFAReKitEvent extends PlayerEvent implements Cancellable { + + private final Kit kit; + private boolean cancelled; + private boolean bypassCooldown; + + public FFAReKitEvent(Player player, Kit k, boolean bypass) { + super(player); + this.kit = k; + this.bypassCooldown = bypass; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean b) { + cancelled = b; + } +} diff --git a/src/main/java/dev/lugami/otaku/hotbar/Hotbar.java b/src/main/java/dev/lugami/otaku/hotbar/Hotbar.java new file mode 100644 index 0000000..5710d54 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/hotbar/Hotbar.java @@ -0,0 +1,69 @@ +package dev.lugami.otaku.hotbar; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.PlayerUtil; +import lombok.Getter; +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +public class Hotbar { + + @Getter + private static final Map items = new HashMap<>(); + + public static void init() { + FileConfiguration config = Main.getInstance().getMainConfig().getConfiguration(); + + for (HotbarItem hotbarItem : HotbarItem.values()) { + try { + String path = "HOTBAR_ITEMS." + hotbarItem.name() + "."; + + ItemBuilder builder = new ItemBuilder(Material.valueOf(config.getString(path + "MATERIAL"))); + builder.durability(config.getInt(path + "DURABILITY")); + builder.name(config.getString(path + "NAME")); + builder.lore(config.getStringList(path + "LORE")); + + items.put(hotbarItem, builder.build()); + } catch (Exception e) { + System.out.println("Failed to parse item " + hotbarItem.name()); + } + } + } + + public static boolean setup(Player player) { + Profile profile = Profile.getOrCreate(player); + + ItemStack[] itemStacks = new ItemStack[9]; + Arrays.fill(itemStacks, null); + try { + PlayerUtil.reset(player); + itemStacks[Main.getInstance().getMainConfig().getInteger("HOTBAR_ITEMS.MAIN_MENU.SLOT")] = items.get(HotbarItem.MAIN_MENU); + for (int i = 0; i < 9; i++) { + player.getInventory().setItem(i, itemStacks[i]); + } + player.updateInventory();player.updateInventory(); + return true; + } catch (Exception ex) { + return false; + } + } + + public static HotbarItem fromItemStack(ItemStack itemStack) { + for (Map.Entry entry : Hotbar.getItems().entrySet()) { + if (entry.getValue() != null && entry.getValue().equals(itemStack)) { + return entry.getKey(); + } + } + + return null; + } + +} diff --git a/src/main/java/dev/lugami/otaku/hotbar/HotbarItem.java b/src/main/java/dev/lugami/otaku/hotbar/HotbarItem.java new file mode 100644 index 0000000..9ea6659 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/hotbar/HotbarItem.java @@ -0,0 +1,18 @@ +package dev.lugami.otaku.hotbar; + +import lombok.Getter; +import lombok.Setter; + +import java.util.regex.Pattern; + +public enum HotbarItem { + MAIN_MENU("menu"); + + @Getter private String command; + @Getter @Setter private Pattern pattern; + + HotbarItem(String command) { + this.command = command; + } + +} diff --git a/src/main/java/dev/lugami/otaku/kit/Kit.java b/src/main/java/dev/lugami/otaku/kit/Kit.java new file mode 100644 index 0000000..7873a15 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/kit/Kit.java @@ -0,0 +1,122 @@ +package dev.lugami.otaku.kit; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.utils.FFACache; +import dev.lugami.otaku.utils.InventoryUtil; +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.LocationUtil; +import dev.lugami.otaku.utils.config.BasicConfigurationFile; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.inventory.ItemStack; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +@Getter +public class Kit { + + @Getter private static final List kits = new ArrayList<>(); + private final String name; + @Setter private boolean enabled; + @Setter private ItemStack displayIcon; + private final KitLoadout kitLoadout = new KitLoadout(); + private final KitRules kitRules = new KitRules(); + @Setter private Location location = null; + + public Kit(String name) { + this.name = name; + this.displayIcon = new ItemStack(Material.DIAMOND_SWORD); + } + + public ItemStack getDisplayIcon() { + return this.displayIcon.clone(); + } + + public static void saveAll() { + for (Kit kit : getKits()) kit.save(); + } + + public void save() { + String path = "kits." + name; + + BasicConfigurationFile configFile = Main.getInstance().getKitsConfig(); + configFile.getConfiguration().set(path + ".enabled", enabled); + configFile.getConfiguration().set(path + ".icon.material", displayIcon.getType().name()); + configFile.getConfiguration().set(path + ".icon.durability", displayIcon.getDurability()); + configFile.getConfiguration().set(path + ".loadout.armor", InventoryUtil.serializeInventory(kitLoadout.getArmor())); + configFile.getConfiguration().set(path + ".loadout.contents", InventoryUtil.serializeInventory(kitLoadout.getContents())); + configFile.getConfiguration().set(path + ".rules.noDamage", kitRules.isNoDamage()); + configFile.getConfiguration().set(path + ".rules.noFall", kitRules.isNoFall()); + configFile.getConfiguration().set(path + ".rules.enderpearlCooldown", kitRules.isEnderpearlCooldown()); + configFile.getConfiguration().set(path + ".location", LocationUtil.serialize(location)); + + try { + configFile.getConfiguration().save(configFile.getFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void delete() { + kits.remove(this); + String path = "kits." + name; + + BasicConfigurationFile configFile = Main.getInstance().getKitsConfig(); + configFile.getConfiguration().set(path, null); + + try { + configFile.getConfiguration().save(configFile.getFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void init() { + FileConfiguration config = Main.getInstance().getKitsConfig().getConfiguration(); + if (!kits.isEmpty()) { + kits.clear(); + } + if (config.getConfigurationSection("kits").getKeys(false) == null) return; + for (String key : config.getConfigurationSection("kits").getKeys(false)) { + String path = "kits." + key; + + Kit kit = new Kit(key); + kit.setEnabled(config.getBoolean(path + ".enabled")); + + kit.setDisplayIcon(new ItemBuilder(Material.valueOf(config.getString(path + ".icon.material"))) + .durability(config.getInt(path + ".icon.durability")) + .build()); + + if (config.contains(path + ".loadout.armor")) { + kit.getKitLoadout().setArmor(InventoryUtil.deserializeInventory(config.getString(path + ".loadout.armor"))); + } + + if (config.contains(path + ".loadout.contents")) { + kit.getKitLoadout().setContents(InventoryUtil.deserializeInventory(config.getString(path + ".loadout.contents"))); + } + + kit.getKitRules().setNoDamage(config.getBoolean(path + ".rules.noDamage")); + kit.getKitRules().setNoFall(config.getBoolean(path + ".rules.noFall")); + kit.getKitRules().setEnderpearlCooldown(config.getBoolean(path + ".rules.enderpearlCooldown")); + kit.setLocation(LocationUtil.deserialize(config.getString(path + ".location"))); + kits.add(kit); + FFACache.getFFAList().put(kit, new ArrayList<>()); + } + } + + public static Kit getByName(String name) { + for (Kit kit : kits) { + if (kit.getName().equalsIgnoreCase(name)) { + return kit; + } + } + + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/kit/KitLoadout.java b/src/main/java/dev/lugami/otaku/kit/KitLoadout.java new file mode 100644 index 0000000..65c4e3b --- /dev/null +++ b/src/main/java/dev/lugami/otaku/kit/KitLoadout.java @@ -0,0 +1,32 @@ +package dev.lugami.otaku.kit; + +import lombok.Data; +import org.bukkit.inventory.ItemStack; + +/** + * s/o Praxi for this class. + */ +@Data +public class KitLoadout { + + private String customName = "Default"; + private ItemStack[] armor; + private ItemStack[] contents; + + public KitLoadout() { + this.armor = new ItemStack[4]; + this.contents = new ItemStack[36]; + } + + public KitLoadout(String customName) { + this.customName = customName; + this.armor = new ItemStack[4]; + this.contents = new ItemStack[36]; + } + + public KitLoadout(ItemStack[] armor, ItemStack[] contents) { + this.armor = armor; + this.contents = contents; + } + +} diff --git a/src/main/java/dev/lugami/otaku/kit/KitRules.java b/src/main/java/dev/lugami/otaku/kit/KitRules.java new file mode 100644 index 0000000..ad11b3a --- /dev/null +++ b/src/main/java/dev/lugami/otaku/kit/KitRules.java @@ -0,0 +1,13 @@ +package dev.lugami.otaku.kit; + +import lombok.Getter; +import lombok.Setter; + +@Getter @Setter +public class KitRules { + + private boolean noDamage; + private boolean noFall; + private boolean enderpearlCooldown; + +} diff --git a/src/main/java/dev/lugami/otaku/kit/menu/KitSelectMenu.java b/src/main/java/dev/lugami/otaku/kit/menu/KitSelectMenu.java new file mode 100644 index 0000000..2b02134 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/kit/menu/KitSelectMenu.java @@ -0,0 +1,80 @@ +package dev.lugami.otaku.kit.menu; + +import dev.lugami.otaku.Constants; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.FFACache; +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.NumberUtils; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import lombok.AllArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class KitSelectMenu extends Menu { + + @Override + public String getTitle(Player player) { + return CC.translate("&bSelect a kit"); + } + + @Override + public int getSize() { + return 9 * (3 + NumberUtils.cutDecimal((double) ((Kit.getKits().size() - 1) / 7))); + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + for (int i = 0; i < getSize(); i++) { + buttons.put(i, Constants.getPlaceholder()); + } + int i = 9; + for (Kit kit : Kit.getKits()) { + if (NumberUtils.isInMultiplicationTableOfNumber(i, 9) || NumberUtils.isInMultiplicationTableOfNumber(i - 1, 9)) i++; + buttons.put(i, new SelectKitButton(kit)); + i++; + } + return buttons; + } + + @AllArgsConstructor + private static class SelectKitButton extends Button { + + private Kit kit; + + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add("&fFighting: &b" + FFACache.getFFAList().get(kit).size()); + + return new ItemBuilder(kit.getDisplayIcon()) + .name("&b" + kit.getName()) + .lore(lore) + .build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + Profile profile = Profile.getOrCreate(player); + + if (profile == null) { + return; + } + + player.closeInventory(); + player.chat("/ffa join " + kit.getName()); + } + + } + + +} diff --git a/src/main/java/dev/lugami/otaku/listener/FFAListener.java b/src/main/java/dev/lugami/otaku/listener/FFAListener.java new file mode 100644 index 0000000..3b1a66c --- /dev/null +++ b/src/main/java/dev/lugami/otaku/listener/FFAListener.java @@ -0,0 +1,197 @@ +package dev.lugami.otaku.listener; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.events.FFAJoinEvent; +import dev.lugami.otaku.events.FFAQuitEvent; +import dev.lugami.otaku.events.FFAReKitEvent; +import dev.lugami.otaku.hotbar.Hotbar; +import dev.lugami.otaku.hotbar.HotbarItem; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.kit.KitLoadout; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.profile.data.ProfileKitData; +import dev.lugami.otaku.utils.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +public class FFAListener implements Listener { + + @EventHandler + public void joinFFA(FFAJoinEvent event) { + Player player = event.getPlayer(); + if (event.getKit().getLocation() != null) { + FFACache.getFFAList().get(event.getKit()).add(player); + setupFFA(player, event.getKit()); + Profile.getOrCreate(player).setState(ProfileState.PLAYING); + } else { + player.sendMessage(CC.RED + "The spawn location for this kit is not set!"); + } + } + + private boolean setupFFA(Player player, Kit kit) { + try { + Location location = new Location(kit.getLocation().getWorld(), kit.getLocation().getX(), kit.getLocation().getY() + 2.0, kit.getLocation().getZ(), kit.getLocation().getYaw(), kit.getLocation().getPitch()); + player.teleport(location); + for (Player player1 : Bukkit.getOnlinePlayers()) { + if (!FFACache.getFFAList().get(kit).contains(player1)) { + player.hidePlayer(player1); + player1.hidePlayer(player); + } else { + player.showPlayer(player1); + player1.showPlayer(player); + } + } + player.updateInventory(); + return setupKit(player, kit); + } catch (Exception ex) { + ex.printStackTrace(); + return false; + } + } + + private boolean setupKit(Player player, Kit kit) { + try { + PlayerUtil.reset(player); + KitLoadout kitLoadout = kit.getKitLoadout(); + player.getInventory().setArmorContents(kitLoadout.getArmor()); + player.getInventory().setContents(kitLoadout.getContents()); + player.updateInventory(); + return true; + } catch (Exception ex) { + ex.printStackTrace(); + return false; + } + } + + @EventHandler + public void quitFFA(FFAQuitEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + if (Main.getInstance().getCombatManager().isInCombat(event.getPlayer())) { + event.getPlayer().sendMessage(CC.RED + "You're still in combat!" + CC.GRAY + " (Remaining: " + Main.getInstance().getCombatManager().getCombatTime(event.getPlayer()) + "s)"); + } else { + FFACache.getFFAList().get(profile.getFFA()).remove(event.getPlayer()); + if (Hotbar.setup(event.getPlayer()) && Main.getInstance().getEssentials().getSpawn() != null) { + Main.getInstance().getEssentials().teleportToSpawn(event.getPlayer()); + Main.getInstance().getServer().getLogger().info("Player " + event.getPlayer().getName() + " was setupped correctly!"); + Profile.getOrCreate(event.getPlayer()).setState(ProfileState.LOBBY); + } + } + } + + @EventHandler + public void reKit(FFAReKitEvent event) { + if (event.isBypassCooldown()) { + setupKit(event.getPlayer(), event.getKit()); + } else if (!event.isCancelled()) { + if (Profile.getOrCreate(event.getPlayer()).getState() != ProfileState.PLAYING) { + event.setCancelled(true); + event.getPlayer().sendMessage(CC.RED + "You're not playing on the FFA."); + } + if (Profile.getOrCreate(event.getPlayer()).getReKitCooldown() != null && !Profile.getOrCreate(event.getPlayer()).getReKitCooldown().hasExpired()) { + event.setCancelled(true); + event.getPlayer().sendMessage(CC.translate(CC.RED + "You're still on cooldown. &7(Cooldown: " + Profile.getOrCreate(event.getPlayer()).getReKitCooldown().getTimeLeft() + ")")); + } else { + setupKit(event.getPlayer(), event.getKit()); + Profile.getOrCreate(event.getPlayer()).setReKitCooldown(new Cooldown(60_000)); + } + } + } + + @EventHandler + public void death(PlayerDeathEvent event) { + event.setDeathMessage(null); + Player player = event.getEntity(); + player.spigot().respawn(); + Profile profile = Profile.getOrCreate(player); + Player killer = PlayerUtil.getLastAttacker(player); + ItemStack[] contents = event.getDrops().toArray(new ItemStack[0]); + ItemStack[] killerContents = killer != null ? killer.getInventory().getContents() : null; + if (profile.getState() == ProfileState.PLAYING && event.getEntity() != null) { + for (Player player1 : FFACache.getFFAList().get(profile.getFFA())) { + LightningUtil.spawnLightning(player1, player.getLocation()); + player1.sendMessage(CC.translate("&a" + player.getName() + " [" + PlayerUtil.getRemainingPotions(contents) + "] &7died" + (killer != null ? " to &c" + killer.getName() + " [" + PlayerUtil.getRemainingPotions(killerContents) + "]&7." : "&7."))); + } + PlayerUtil.reset(player); + if (player.isDead()) { + player.spigot().respawn(); + } + if (Main.getInstance().getCombatManager().isInCombat(player)) { + Main.getInstance().getCombatManager().setInCombat(player, false); + } + event.getDrops().clear(); + if (killer != null) { + Profile profile1 = Profile.getOrCreate(killer); + ProfileKitData profileKitData = profile1.getKitData().get(profile1.getFFA()); + profileKitData.kills(profileKitData.kills() + 1); + profileKitData.killstreak(profileKitData.killstreak() + 1); + profile1.save(); + if (Main.getInstance().getCombatManager().isInCombat(killer)) { + Main.getInstance().getCombatManager().setInCombat(killer, false); + } + } + ProfileKitData profileKitData = profile.getKitData().get(profile.getFFA()); + profileKitData.deaths(profileKitData.deaths() + 1); + profileKitData.killstreak(0); + profile.save(); + TaskUtil.runLater(new BukkitRunnable() { + @Override + public void run() { + if (setupFFA(player, profile.getFFA())) { + } else this.run(); + if (killer != null && Profile.getOrCreate(killer).getSettings().autoRekit()) { + (new FFAReKitEvent(killer, profile.getFFA(), true)).call(); + } + } + }, 1L); + } + } + + @EventHandler + public void items(PlayerInteractEvent event) { + if (event.getItem() != null && (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK)) { + Player player = event.getPlayer(); + + HotbarItem hotbarItem = Hotbar.fromItemStack(event.getItem()); + + if (hotbarItem != null) { + if (hotbarItem.getCommand() != null) { + event.setCancelled(true); + player.chat("/" + hotbarItem.getCommand()); + } + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onPlayerInteractEvent(PlayerInteractEvent event) { + Player player = event.getPlayer(); + ItemStack itemStack = event.getItem(); + + if (itemStack != null && (event.getAction() == Action.RIGHT_CLICK_AIR || + event.getAction() == Action.RIGHT_CLICK_BLOCK)) { + if (itemStack.getType() == Material.ENDER_PEARL && event.getClickedBlock() == null) { + if (Profile.getOrCreate(player).getFFA().getKitRules().isEnderpearlCooldown()) { + if (Main.getInstance().getEnderpearlManager().isPearlCooldown(player)) { + event.getPlayer().sendMessage(CC.RED + "You're still in cooldown!" + CC.GRAY + " (Remaining: " + Main.getInstance().getEnderpearlManager().getPearlCooldown(event.getPlayer()) + "s)"); + event.setCancelled(true); + } else { + Main.getInstance().getEnderpearlManager().setPearlCooldown(player, true); + } + } + } + } + } + + +} diff --git a/src/main/java/dev/lugami/otaku/listener/Listeners.java b/src/main/java/dev/lugami/otaku/listener/Listeners.java new file mode 100644 index 0000000..419c6cb --- /dev/null +++ b/src/main/java/dev/lugami/otaku/listener/Listeners.java @@ -0,0 +1,158 @@ +package dev.lugami.otaku.listener; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.hotbar.Hotbar; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.PlayerCache; +import dev.lugami.otaku.utils.PlayerUtil; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; + +public class Listeners implements Listener { + + @EventHandler + public void drop(PlayerDropItemEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + ItemStack droppedItem = event.getItemDrop().getItemStack(); + + if (isSword(droppedItem.getType()) && profile.getSettings().dropProtect()) { + event.setCancelled(true); + event.getPlayer().sendMessage(CC.RED + "You cannot drop this item."); + } + } + + @EventHandler + public void block(BlockBreakEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + if (profile != null) { + if (event.getPlayer().getGameMode() != GameMode.CREATIVE) event.setCancelled(true); + } + } + + @EventHandler + public void block2(BlockPlaceEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + if (profile != null && !event.getPlayer().isOp()) { + if (event.getPlayer().getGameMode() != GameMode.CREATIVE) event.setCancelled(true); + } + } + + + @EventHandler + public void soup(PlayerInteractEvent event) { + Player p = event.getPlayer(); + ItemStack item = event.getItem(); + Action a = event.getAction(); + + if (item == null) return; + if (item.getType() != Material.MUSHROOM_SOUP) return; + if (!a.equals(Action.RIGHT_CLICK_AIR) && !a.equals(Action.RIGHT_CLICK_BLOCK)) return; + + if (p.getHealth() < 20.0D || p.getFoodLevel() < 20) { + event.setCancelled(true); + if (p.getHealth() < 20.0D) p.setHealth(Math.min(p.getHealth() + 7D, 20.0D)); + else if (p.getFoodLevel() < 20) p.setFoodLevel(Math.min(p.getFoodLevel() + 7, 20)); + item.setType(Material.BOWL); + } + } + + @EventHandler + public void onPlayerItemConsume(PlayerItemConsumeEvent event) { + ItemStack item = event.getItem(); + if (item == null) { + return; + } + + Material type = item.getType(); + Player player = event.getPlayer(); + if (type.getId() == 373) { + Main.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Main.getInstance(), () -> { + player.setItemInHand(new ItemStack(Material.AIR)); + player.updateInventory(); + }, 1L); + } + } + + @EventHandler + public void joinServer(PlayerJoinEvent event) { + if (Hotbar.setup(event.getPlayer()) && Main.getInstance().getEssentials().getSpawn() != null) { + Main.getInstance().getEssentials().teleportToSpawn(event.getPlayer()); + PlayerCache.getPlayerCache().put(event.getPlayer().getName(), event.getPlayer().getUniqueId()); + Main.getInstance().getServer().getLogger().info("Player " + event.getPlayer().getName() + " was setupped correctly!"); + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerItemDamageEvent(PlayerItemDamageEvent event) { + Profile profile = Profile.getOrCreate(event.getPlayer()); + + if (profile.getState() == ProfileState.LOBBY) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onEntityDamageByEntityMonitor(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player) { + Player victim = (Player) event.getEntity(); + Player attacker = null; + + if (event.getDamager() instanceof Player) { + attacker = (Player) event.getDamager(); + } else if (event.getDamager() instanceof Projectile) { + Projectile projectile = (Projectile) event.getDamager(); + + if (projectile.getShooter() instanceof Player) { + attacker = (Player) projectile.getShooter(); + } + } + + if (attacker != null) { + PlayerUtil.setLastAttacker(victim, attacker); + if (attacker instanceof Player && attacker != victim) { + Main.getInstance().getCombatManager().setCombatTime(victim, 15); + Main.getInstance().getCombatManager().setCombatTime(attacker, 15); + Main.getInstance().getCombatManager().setInCombat(victim, true); + Main.getInstance().getCombatManager().setInCombat(attacker, true); + } + } + } + } + + @EventHandler + public void hunger(FoodLevelChangeEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + Profile profile = Profile.getOrCreate(player); + if (profile.getState() != ProfileState.PLAYING) { + event.setFoodLevel(20); + } + } + } + + private boolean isSword(Material m) { + switch (m) { + case WOOD_SWORD: + case STONE_SWORD: + case GOLD_SWORD: + case IRON_SWORD: + case DIAMOND_SWORD: return true; + default: return false; + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/menu/MainMenu.java b/src/main/java/dev/lugami/otaku/menu/MainMenu.java new file mode 100644 index 0000000..6576a98 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/menu/MainMenu.java @@ -0,0 +1,88 @@ +package dev.lugami.otaku.menu; + +import dev.lugami.otaku.Constants; +import dev.lugami.otaku.kit.menu.KitSelectMenu; +import dev.lugami.otaku.profile.menu.SettingsMenu; +import dev.lugami.otaku.stats.StatsMenu; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.PlayerCache; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; + +public class MainMenu extends Menu { + + @Override + public String getTitle(Player player) { + return CC.translate("&bMain Menu"); + } + + @Override + public int getSize() { + return 27; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + for (int i = 0; i < getSize(); i++) { + buttons.put(i, Constants.getPlaceholder()); + } + buttons.put(11, new SelectKitButton()); + buttons.put(13, new StatsButton()); + buttons.put(15, new SettingsButton()); + return buttons; + } + + + private static class SelectKitButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.DIAMOND_SWORD).name(CC.translate("&bJoin FFA")).lore(CC.translate("&7Play with other &b" + PlayerCache.getInFFA() + " &7players!")).build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + new KitSelectMenu().openMenu(player); + } + } + + private static class SettingsButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.ITEM_FRAME).name(CC.translate("&bSettings")).lore(CC.translate("&7Customize your FFA settings!")).build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + //player.sendMessage("WIP"); + //TODO: Check if settings works fine. + new SettingsMenu().openMenu(player); + } + } + + private static class StatsButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.EMERALD).name(CC.translate("&bStats")).lore(CC.translate("&7See your personal stats!")).build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + //player.sendMessage("WIP"); + //TODO: Check if settings works fine. + new StatsMenu(player).openMenu(player); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/profile/Profile.java b/src/main/java/dev/lugami/otaku/profile/Profile.java new file mode 100644 index 0000000..3ba7fd3 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/Profile.java @@ -0,0 +1,130 @@ +package dev.lugami.otaku.profile; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.profile.data.ProfileKitData; +import dev.lugami.otaku.profile.data.ProfileSettings; +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.Cooldown; +import dev.lugami.otaku.utils.FFACache; +import lombok.Data; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; + +import java.io.IOException; +import java.util.*; + +@Data +public class Profile { + + @Getter + private static List profiles = new ArrayList<>(); + + private Player player; + private ProfileState state; + private Map kitData; + private ProfileSettings settings; + private Cooldown reKitCooldown; + + public Profile(UUID uuid) { + player = Bukkit.getPlayer(uuid); + state = ProfileState.LOBBY; + kitData = new HashMap<>(); + settings = new ProfileSettings(); + reKitCooldown = new Cooldown(0); + load(); + for (Kit kit : Kit.getKits()) { + kitData.putIfAbsent(kit, new ProfileKitData()); + } + profiles.add(this); + } + + public static Profile getByPlayer(Player p) { + for (Profile profile : profiles) { + if (profile.getPlayer() == p) { + return profile; + } + } + return null; + } + + public static Profile getOrCreate(Player p) { + if (getByPlayer(p) == null) { + return new Profile(p.getUniqueId()); + } else { + return getByPlayer(p); + } + } + + public static Profile getByUUID(UUID p) { + for (Profile profile : profiles) { + if (profile.getPlayer().getUniqueId() == p) { + return profile; + } + } + return null; + } + + public Kit getFFA() { + if (getState() == ProfileState.PLAYING) { + for (Kit kit : FFACache.getFFAList().keySet()) { + if (FFACache.getFFAList().get(kit).contains(player)) { + return kit; + } + } + } else { + return null; + } + return null; + } + + void load() { + ConfigurationSection mainSection = Main.getInstance().getProfileConfig().getConfiguration().getConfigurationSection("stats." + getPlayer().getName()); + for (Kit kit : Kit.getKits()) { + if (mainSection.getConfigurationSection(kit.getName()) != null) { + ConfigurationSection kitSection = mainSection.getConfigurationSection(kit.getName()); + ProfileKitData profileKitData = new ProfileKitData(); + profileKitData.kills(kitSection.getInt("kills", 0)); + profileKitData.deaths(kitSection.getInt("deaths", 0)); + profileKitData.killstreak(kitSection.getInt("killstreak", 0)); + kitData.put(kit, profileKitData); + } + } + settings.scoreboard(Main.getInstance().getProfileConfig().getConfiguration().getBoolean("settings." + getPlayer().getName() + ".scoreboard", true)); + settings.autoRekit(Main.getInstance().getProfileConfig().getConfiguration().getBoolean("settings." + getPlayer().getName() + ".autoRekit", true)); + settings.dropProtect(Main.getInstance().getProfileConfig().getConfiguration().getBoolean("settings." + getPlayer().getName() + ".dropProtect", true)); + } + + public void save() { + for (Kit kit : Kit.getKits()) { + ProfileKitData profileKitData = kitData.get(kit); + if (profileKitData == null) profileKitData = new ProfileKitData(); + Main.getInstance().getProfileConfig().getConfiguration().set("stats." + getPlayer().getName() + "." + kit.getName() + ".kills", profileKitData.kills()); + Main.getInstance().getProfileConfig().getConfiguration().set("stats." + getPlayer().getName() + "." + kit.getName() + ".deaths", profileKitData.deaths()); + Main.getInstance().getProfileConfig().getConfiguration().set("stats." + getPlayer().getName() + "." + kit.getName() + ".killstreak", profileKitData.killstreak()); + } + Main.getInstance().getProfileConfig().getConfiguration().set("settings." + getPlayer().getName() + ".scoreboard", settings.scoreboard()); + Main.getInstance().getProfileConfig().getConfiguration().set("settings." + getPlayer().getName() + ".autoRekit", settings.autoRekit()); + Main.getInstance().getProfileConfig().getConfiguration().set("settings." + getPlayer().getName() + ".dropProtect", settings.dropProtect()); + try { + Main.getInstance().getProfileConfig().getConfiguration().save(Main.getInstance().getProfileConfig().getFile()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void removeProfile(Profile profile) { + profiles.remove(profile); + } + + public static void removeAll() { + profiles.clear(); + } + + public static void saveAll() { + for (Profile profile : profiles) profile.save(); + } + +} diff --git a/src/main/java/dev/lugami/otaku/profile/ProfileListener.java b/src/main/java/dev/lugami/otaku/profile/ProfileListener.java new file mode 100644 index 0000000..d523b2e --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/ProfileListener.java @@ -0,0 +1,32 @@ +package dev.lugami.otaku.profile; + +import dev.lugami.otaku.profile.data.ProfileState; +import dev.lugami.otaku.utils.FFACache; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +public class ProfileListener implements Listener { + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + event.setJoinMessage(null); + Profile profile = new Profile(event.getPlayer().getUniqueId()); + profile.load(); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + event.setQuitMessage(null); + Profile profile = Profile.getOrCreate(event.getPlayer()); + if (profile.getState() == ProfileState.PLAYING) { + FFACache.getFFAList().get(profile.getFFA()).remove(profile.getPlayer()); + } + profile.save(); + Profile.removeProfile(profile); + } + + + +} diff --git a/src/main/java/dev/lugami/otaku/profile/data/ProfileKitData.java b/src/main/java/dev/lugami/otaku/profile/data/ProfileKitData.java new file mode 100644 index 0000000..11fa7b2 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/data/ProfileKitData.java @@ -0,0 +1,13 @@ +package dev.lugami.otaku.profile.data; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data @Accessors(fluent = true) +public class ProfileKitData { + + private int kills; + private int deaths; + private int killstreak; + +} diff --git a/src/main/java/dev/lugami/otaku/profile/data/ProfileSettings.java b/src/main/java/dev/lugami/otaku/profile/data/ProfileSettings.java new file mode 100644 index 0000000..fd7b391 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/data/ProfileSettings.java @@ -0,0 +1,13 @@ +package dev.lugami.otaku.profile.data; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data @Accessors(fluent = true) +public class ProfileSettings { + + private boolean scoreboard = true; + private boolean autoRekit = true; + private boolean dropProtect = true; + +} diff --git a/src/main/java/dev/lugami/otaku/profile/data/ProfileState.java b/src/main/java/dev/lugami/otaku/profile/data/ProfileState.java new file mode 100644 index 0000000..a4427de --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/data/ProfileState.java @@ -0,0 +1,8 @@ +package dev.lugami.otaku.profile.data; + +public enum ProfileState { + + LOBBY, + PLAYING + +} diff --git a/src/main/java/dev/lugami/otaku/profile/menu/SettingsButton.java b/src/main/java/dev/lugami/otaku/profile/menu/SettingsButton.java new file mode 100644 index 0000000..39f3b18 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/menu/SettingsButton.java @@ -0,0 +1,56 @@ +package dev.lugami.otaku.profile.menu; + +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.TextSplitter; +import dev.lugami.otaku.utils.menu.Button; +import lombok.AllArgsConstructor; +import org.apache.commons.lang.StringEscapeUtils; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +public abstract class SettingsButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder itemBuilder = new ItemBuilder(isEnabled(player) ? getEnabledItem(player) : getDisabledItem(player)); + + List lore = new ArrayList<>(); + lore.add(""); + lore.addAll(TextSplitter.split(40, getDescription(), CC.GRAY, " ")); + lore.add(""); + lore.add((isEnabled(player) ? CC.GREEN + StringEscapeUtils.unescapeJava(" ■ ") : CC.GRAY + StringEscapeUtils.unescapeJava(" ■ ")) + "&7" + getEnabledOption()); + lore.add((!isEnabled(player) ? CC.RED + StringEscapeUtils.unescapeJava(" ■ ") : CC.GRAY + StringEscapeUtils.unescapeJava(" ■ ")) + "&7" + getDisabledOption()); + lore.add(""); + lore.add("&eClick to change."); + + return itemBuilder.name(getOptionName()) + .lore(lore) + .build(); + } + + public abstract ItemStack getEnabledItem(Player player); + + public abstract ItemStack getDisabledItem(Player player); + + public abstract String getOptionName(); + + public abstract String getDescription(); + + public abstract String getEnabledOption(); + + public abstract String getDisabledOption(); + + public abstract boolean isEnabled(Player player); + + @Override + public boolean shouldUpdate(Player player, ClickType clickType) { + return true; + } + +} diff --git a/src/main/java/dev/lugami/otaku/profile/menu/SettingsMenu.java b/src/main/java/dev/lugami/otaku/profile/menu/SettingsMenu.java new file mode 100644 index 0000000..1de0a4a --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/menu/SettingsMenu.java @@ -0,0 +1,37 @@ +package dev.lugami.otaku.profile.menu; + +import dev.lugami.otaku.Constants; +import dev.lugami.otaku.profile.menu.buttons.AutoReKitButton; +import dev.lugami.otaku.profile.menu.buttons.DropProtectButton; +import dev.lugami.otaku.profile.menu.buttons.ScoreboardButton; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +public class SettingsMenu extends Menu { + @Override + public String getTitle(Player player) { + return CC.translate("&bSettings"); + } + + @Override + public int getSize() { + return 27; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + for (int i = 0; i < getSize(); i++) { + buttons.put(i, Constants.getPlaceholder()); + } + buttons.put(10, new ScoreboardButton()); + buttons.put(11, new AutoReKitButton()); + buttons.put(12, new DropProtectButton()); + return buttons; + } +} diff --git a/src/main/java/dev/lugami/otaku/profile/menu/buttons/AutoReKitButton.java b/src/main/java/dev/lugami/otaku/profile/menu/buttons/AutoReKitButton.java new file mode 100644 index 0000000..82b90e1 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/menu/buttons/AutoReKitButton.java @@ -0,0 +1,59 @@ +package dev.lugami.otaku.profile.menu.buttons; + +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.menu.SettingsButton; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +public class AutoReKitButton extends SettingsButton { + + @Override + public ItemStack getEnabledItem(Player player) { + return new ItemBuilder(Material.GLASS_BOTTLE).build(); + } + + @Override + public ItemStack getDisabledItem(Player player) { + return new ItemBuilder(Material.GLASS_BOTTLE).build(); + } + + @Override + public String getOptionName() { + return "&b&lAuto Re-Kit"; + } + + @Override + public String getDescription() { + return "If this is enabled, you'll auto re-kit when you kill someone."; + } + + @Override + public String getEnabledOption() { + return "Enable auto re-kit"; + } + + @Override + public String getDisabledOption() { + return "Disable auto re-kit"; + } + + @Override + public boolean isEnabled(Player player) { + Profile profile = Profile.getOrCreate(player); + return profile.getSettings().autoRekit(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + Profile profile = Profile.getOrCreate(player); + profile.getSettings().autoRekit(!profile.getSettings().autoRekit()); + boolean enabled = profile.getSettings().autoRekit(); + player.sendMessage(CC.translate(enabled ? "&aEnabled auto re-kit!" : "&cDisabled auto re-kit!")); + playSuccess(player); + } + +} diff --git a/src/main/java/dev/lugami/otaku/profile/menu/buttons/DropProtectButton.java b/src/main/java/dev/lugami/otaku/profile/menu/buttons/DropProtectButton.java new file mode 100644 index 0000000..d70b1bc --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/menu/buttons/DropProtectButton.java @@ -0,0 +1,59 @@ +package dev.lugami.otaku.profile.menu.buttons; + +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.menu.SettingsButton; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +public class DropProtectButton extends SettingsButton { + + @Override + public ItemStack getEnabledItem(Player player) { + return new ItemBuilder(Material.DIAMOND_SWORD).build(); + } + + @Override + public ItemStack getDisabledItem(Player player) { + return new ItemBuilder(Material.DIAMOND_SWORD).build(); + } + + @Override + public String getOptionName() { + return "&b&lDrop Protect"; + } + + @Override + public String getDescription() { + return "If this is enabled, you won't be able to drop weapons in FFA."; + } + + @Override + public String getEnabledOption() { + return "Enable drop protect"; + } + + @Override + public String getDisabledOption() { + return "Disable drop protect"; + } + + @Override + public boolean isEnabled(Player player) { + Profile profile = Profile.getOrCreate(player); + return profile.getSettings().dropProtect(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + Profile profile = Profile.getOrCreate(player); + profile.getSettings().dropProtect(!profile.getSettings().dropProtect()); + boolean enabled = profile.getSettings().dropProtect(); + player.sendMessage(CC.translate(enabled ? "&aEnabled drop protect!" : "&cDisabled drop protect!")); + playSuccess(player); + } + +} diff --git a/src/main/java/dev/lugami/otaku/profile/menu/buttons/ScoreboardButton.java b/src/main/java/dev/lugami/otaku/profile/menu/buttons/ScoreboardButton.java new file mode 100644 index 0000000..af13574 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/profile/menu/buttons/ScoreboardButton.java @@ -0,0 +1,57 @@ +package dev.lugami.otaku.profile.menu.buttons; + +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.menu.SettingsButton; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +public class ScoreboardButton extends SettingsButton { + @Override + public ItemStack getEnabledItem(Player player) { + return new ItemBuilder(Material.ITEM_FRAME).build(); + } + + @Override + public ItemStack getDisabledItem(Player player) { + return new ItemBuilder(Material.ITEM_FRAME).build(); + } + + @Override + public String getOptionName() { + return "&b&lShow Scoreboard"; + } + + @Override + public String getDescription() { + return "If this is enabled, you'll see a sidebar showing useful information."; + } + + @Override + public String getEnabledOption() { + return "Enable scoreboard"; + } + + @Override + public String getDisabledOption() { + return "Disable scoreboard"; + } + + @Override + public boolean isEnabled(Player player) { + Profile profile = Profile.getOrCreate(player); + return profile.getSettings().scoreboard(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + Profile profile = Profile.getOrCreate(player); + profile.getSettings().scoreboard(!profile.getSettings().scoreboard()); + boolean enabled = profile.getSettings().scoreboard(); + player.sendMessage(CC.translate(enabled ? "&aEnabled scoreboard!" : "&cDisabled scoreboard!")); + playSuccess(player); + } +} diff --git a/src/main/java/dev/lugami/otaku/stats/StatsMenu.java b/src/main/java/dev/lugami/otaku/stats/StatsMenu.java new file mode 100644 index 0000000..8c6c5fa --- /dev/null +++ b/src/main/java/dev/lugami/otaku/stats/StatsMenu.java @@ -0,0 +1,83 @@ +package dev.lugami.otaku.stats; + +import dev.lugami.otaku.Constants; +import dev.lugami.otaku.kit.Kit; +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import lombok.AllArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.beans.ConstructorProperties; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class StatsMenu extends Menu { + private final Player target; + + @Override + public String getTitle(Player player) { + return "&7" + target.getName() + "'s Statistics"; + } + + @Override + public int getSize(){ + int i = 3; + if (Kit.getKits().size() - 1 > 7) { + i = 4; + } + if (Kit.getKits().size() - 1 > 14) { + i = 5; + } + return 9*i; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + for (int i = 0; i < getSize(); i++) { + buttons.put(i, Constants.getPlaceholder()); + } + final int[] i = {10}; + Kit.getKits().forEach(kit -> { + if (!kit.isEnabled()) return; + while (i[0] == 17 || i[0] == 18 || i[0] == 26 || i[0] == 27 || i[0] == 36 || i[0] == 37) i[0]++; + buttons.put(i[0]++, new KitStatsButton(kit)); + }); + + return buttons; + } + + @ConstructorProperties({"target"}) + public StatsMenu(final Player target) { + this.target = target; + } + + @AllArgsConstructor + private class KitStatsButton extends Button { + + private final Kit kit; + + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + Profile profile = Profile.getOrCreate(target); + lore.add(CC.MENU_BAR); + lore.add("&8 • &bKills: &f" + profile.getKitData().get(kit).kills()); + lore.add("&8 • &bDeaths: &f" + profile.getKitData().get(kit).deaths()); + lore.add("&8 • &bKillstreak: &f" + profile.getKitData().get(kit).killstreak()); + lore.add(CC.MENU_BAR); + + return new ItemBuilder(kit.getDisplayIcon()) + .name("&b" + kit.getName() + " &7⏐ &fStats") + .lore(lore) + .build(); + } + + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/BaseEvent.java b/src/main/java/dev/lugami/otaku/utils/BaseEvent.java new file mode 100644 index 0000000..1fd4743 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/BaseEvent.java @@ -0,0 +1,25 @@ +package dev.lugami.otaku.utils; + +import dev.lugami.otaku.Main; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BaseEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + public void call() { + Main.getInstance().getServer().getPluginManager().callEvent(this); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/CC.java b/src/main/java/dev/lugami/otaku/utils/CC.java new file mode 100644 index 0000000..6560f1c --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/CC.java @@ -0,0 +1,116 @@ +package dev.lugami.otaku.utils; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; + +import java.util.*; + +public class CC { + + private static final Map MAP; + + public static final String BLUE; + public static final String AQUA; + public static final String YELLOW; + public static final String RED; + public static final String GRAY; + public static final String GOLD; + public static final String GREEN; + public static final String WHITE; + public static final String BLACK; + public static final String BOLD; + public static final String ITALIC; + public static final String UNDER_LINE; + public static final String STRIKE_THROUGH; + public static final String RESET; + public static final String MAGIC; + public static final String DARK_BLUE; + public static final String DARK_AQUA; + public static final String DARK_GRAY; + public static final String DARK_GREEN; + public static final String DARK_PURPLE; + public static final String DARK_RED; + public static final String PINK; + public static final String MENU_BAR; + public static final String CHAT_BAR; + public static final String SB_BAR; + + static { + MAP = new HashMap<>(); + MAP.put("pink", ChatColor.LIGHT_PURPLE); + MAP.put("orange", ChatColor.GOLD); + MAP.put("purple", ChatColor.DARK_PURPLE); + + for (ChatColor chatColor : ChatColor.values()) { + MAP.put(chatColor.name().toLowerCase().replace("_", ""), chatColor); + } + + BLUE = ChatColor.BLUE.toString(); + AQUA = ChatColor.AQUA.toString(); + YELLOW = ChatColor.YELLOW.toString(); + RED = ChatColor.RED.toString(); + GRAY = ChatColor.GRAY.toString(); + GOLD = ChatColor.GOLD.toString(); + GREEN = ChatColor.GREEN.toString(); + WHITE = ChatColor.WHITE.toString(); + BLACK = ChatColor.BLACK.toString(); + BOLD = ChatColor.BOLD.toString(); + ITALIC = ChatColor.ITALIC.toString(); + UNDER_LINE = ChatColor.UNDERLINE.toString(); + STRIKE_THROUGH = ChatColor.STRIKETHROUGH.toString(); + RESET = ChatColor.RESET.toString(); + MAGIC = ChatColor.MAGIC.toString(); + DARK_BLUE = ChatColor.DARK_BLUE.toString(); + DARK_AQUA = ChatColor.DARK_AQUA.toString(); + DARK_GRAY = ChatColor.DARK_GRAY.toString(); + DARK_GREEN = ChatColor.DARK_GREEN.toString(); + DARK_PURPLE = ChatColor.DARK_PURPLE.toString(); + DARK_RED = ChatColor.DARK_RED.toString(); + PINK = ChatColor.LIGHT_PURPLE.toString(); + MENU_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "------------------------"; + CHAT_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "------------------------------------------------"; + SB_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "----------------------"; + } + + public static Set getColorNames() { + return MAP.keySet(); + } + + public static ChatColor getColorFromName(String name) { + if (MAP.containsKey(name.trim().toLowerCase())) { + return MAP.get(name.trim().toLowerCase()); + } + ChatColor color; + try { + color = ChatColor.valueOf(name.toUpperCase().replace(" ", "_")); + } catch (Exception e) { + return null; + } + return color; + } + + public static String translate(String in) { + return ChatColor.translateAlternateColorCodes('&', in); + } + + public static List translate(List lines) { + List toReturn = new ArrayList<>(); + + for (String line : lines) { + toReturn.add(ChatColor.translateAlternateColorCodes('&', line)); + } + + return toReturn; + } + + public static List translate(String[] lines) { + List toReturn = new ArrayList<>(); + for (String line : lines) { + if (line != null) { + toReturn.add(ChatColor.translateAlternateColorCodes('&', line)); + } + } + return toReturn; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/CombatManager.java b/src/main/java/dev/lugami/otaku/utils/CombatManager.java new file mode 100644 index 0000000..a4ab111 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/CombatManager.java @@ -0,0 +1,60 @@ +package dev.lugami.otaku.utils; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class CombatManager extends BukkitRunnable { + + private final Set combatSet = new HashSet<>(); + private final Map timeMap = new HashMap<>(); + private int count = 0; + + public void setInCombat(Player player, boolean inCombat) { + if (inCombat) { + combatSet.add(player); + timeMap.put(player, 15.0); + } else { + combatSet.remove(player); + timeMap.remove(player); + } + } + + public void setCombatTime(Player player, double time) { + timeMap.put(player, Math.round(time * 10.0) / 10.0); + } + + public boolean isInCombat(Player player) { + return combatSet.contains(player); + } + + public double getCombatTime(Player player) { + return Math.round(timeMap.getOrDefault(player, 0.0) * 10.0) / 10.0; + } + + @Override + public void run() { + count++; + + for (Player player : Bukkit.getOnlinePlayers()) { + if (isInCombat(player)) { + double remainingTime = getCombatTime(player) - 0.1; // Adjust the decrement value as needed + setCombatTime(player, remainingTime); + + if (remainingTime <= 0) { + player.sendMessage(CC.translate("&aYou are no longer in combat!")); + setInCombat(player, false); + } + } + } + + if (count == 160) { + count = 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/Cooldown.java b/src/main/java/dev/lugami/otaku/utils/Cooldown.java new file mode 100644 index 0000000..f67860b --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/Cooldown.java @@ -0,0 +1,40 @@ +package dev.lugami.otaku.utils; + +import lombok.Data; + +@Data +public class Cooldown { + + private long start = System.currentTimeMillis(); + private long expire; + private boolean notified; + + public Cooldown(long duration) { + this.expire = this.start + duration; + + if (duration == 0) { + this.notified = true; + } + } + + public long getPassed() { + return System.currentTimeMillis() - this.start; + } + + public long getRemaining() { + return this.expire - System.currentTimeMillis(); + } + + public boolean hasExpired() { + return System.currentTimeMillis() - this.expire >= 0; + } + + public String getTimeLeft() { + if (this.getRemaining() >= 60_000) { + return TimeUtil.millisToRoundedTime(this.getRemaining()); + } else { + return TimeUtil.millisToSeconds(this.getRemaining()); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/EnderpearlManager.java b/src/main/java/dev/lugami/otaku/utils/EnderpearlManager.java new file mode 100644 index 0000000..ace0681 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/EnderpearlManager.java @@ -0,0 +1,64 @@ +package dev.lugami.otaku.utils; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * same thing as dev.lugami.otaku.utils.CombatManager but for pearls + */ +public class EnderpearlManager extends BukkitRunnable { + + private final Set pearl = new HashSet<>(); + private final Map timeMap = new HashMap<>(); + private int count = 0; + + public void setPearlCooldown(Player player, boolean pearlCooldown) { + if (pearlCooldown) { + pearl.add(player); + timeMap.put(player, 15.0); + } else { + pearl.remove(player); + timeMap.remove(player); + } + } + + public void setCooldownTime(Player player, double time) { + timeMap.put(player, Math.round(time * 10.0) / 10.0); + } + + public boolean isPearlCooldown(Player player) { + return pearl.contains(player); + } + + public double getPearlCooldown(Player player) { + return Math.round(timeMap.getOrDefault(player, 0.0) * 10.0) / 10.0; + } + + @Override + public void run() { + count++; + + for (Player player : Bukkit.getOnlinePlayers()) { + if (isPearlCooldown(player)) { + double remainingTime = getPearlCooldown(player) - 0.1; // Adjust the decrement value as needed + setCooldownTime(player, remainingTime); + + if (remainingTime <= 0) { + player.sendMessage(CC.translate("&aYour enderpearl cooldown ended!")); + setPearlCooldown(player, false); + } + } + } + + if (count == 160) { + count = 0; + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/FFACache.java b/src/main/java/dev/lugami/otaku/utils/FFACache.java new file mode 100644 index 0000000..667d592 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/FFACache.java @@ -0,0 +1,16 @@ +package dev.lugami.otaku.utils; + +import dev.lugami.otaku.kit.Kit; +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class FFACache { + + @Getter + private static Map> FFAList = new HashMap<>(); + +} diff --git a/src/main/java/dev/lugami/otaku/utils/InventoryUtil.java b/src/main/java/dev/lugami/otaku/utils/InventoryUtil.java new file mode 100644 index 0000000..2a4d272 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/InventoryUtil.java @@ -0,0 +1,300 @@ +package dev.lugami.otaku.utils; + +import dev.lugami.otaku.Main; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.*; + +public class InventoryUtil { + + public static ItemStack[] fixInventoryOrder(ItemStack[] source) { + ItemStack[] fixed = new ItemStack[36]; + + System.arraycopy(source, 0, fixed, 27, 9); + System.arraycopy(source, 9, fixed, 0, 27); + + return fixed; + } + + public static String serializeInventory(ItemStack[] source) { + StringBuilder builder = new StringBuilder(); + + for (ItemStack itemStack : source) { + builder.append(serializeItemStack(itemStack)); + builder.append(";"); + } + + return builder.toString(); + } + + public static ItemStack[] deserializeInventory(String source) { + List items = new ArrayList<>(); + String[] split = source.split(";"); + + for (String piece : split) { + items.add(deserializeItemStack(piece)); + } + + return items.toArray(new ItemStack[items.size()]); + } + + public static String serializeEffects(List source) { + StringBuilder builder = new StringBuilder(); + if (source.size() == 0) return null; + + for (PotionEffect potionEffect : source) { + String potionString = serializeEffect(potionEffect); + if (potionString == null || potionString == "null") continue; + + builder.append(potionString); + builder.append(";"); + } + + return builder.toString(); + } + + public static List deserializeEffects(String source) { + List items = new ArrayList<>(); + + if (source.equalsIgnoreCase("")) + return null; + + String[] split = source.split(";"); + + for (String piece : split) { + items.add(deserializeEffect(piece)); + } + + return items; + } + + public static String serializeItemStack(ItemStack item) { + StringBuilder builder = new StringBuilder(); + + if (item == null) { + return "null"; + } + + String isType = String.valueOf(item.getType().getId()); + builder.append("t@").append(isType); + + if (item.getDurability() != 0) { + String isDurability = String.valueOf(item.getDurability()); + builder.append(":d@").append(isDurability); + } + + if (item.getAmount() != 1) { + String isAmount = String.valueOf(item.getAmount()); + builder.append(":a@").append(isAmount); + } + + Map enchantments = item.getEnchantments(); + + if (enchantments.size() > 0) { + for (Map.Entry enchantment : enchantments.entrySet()) { + builder.append(":e@").append(enchantment.getKey().getId()).append("@").append(enchantment.getValue()); + } + } + + if (item.hasItemMeta()) { + ItemMeta itemMeta = item.getItemMeta(); + + if (itemMeta.hasDisplayName()) { + builder.append(":dn@").append(itemMeta.getDisplayName()); + } + + if (itemMeta.hasLore()) { + builder.append(":l@").append(itemMeta.getLore()); + } + } + +// if (item.getType() == Material.POTION) { +// Potion potion = Potion.fromItemStack(item); +// +// builder.append(":pd@") +// .append(potion.getType().getDamageValue()) +// .append("-") +// .append(potion.getLevel()); +// +// for (PotionEffect effect : potion.getEffects()) { +// builder.append("=") +// .append(effect.getType().getId()) +// .append("-") +// .append(effect.getDuration()) +// .append("-") +// .append(effect.getAmplifier()); +// } +// } + + return builder.toString(); + } + + public static ItemStack deserializeItemStack(String in) { + ItemStack item = null; + ItemMeta meta = null; + + if (in.equals("null")) { + return new ItemStack(Material.AIR); + } + + String[] split = in.split(":"); + + for (String itemInfo : split) { + String[] itemAttribute = itemInfo.split("@"); + String attributeId = itemAttribute[0]; + + switch (attributeId) { + case "t": { + item = new ItemStack(Material.getMaterial(Integer.valueOf(itemAttribute[1]))); + meta = item.getItemMeta(); + break; + } + case "d": { + if (item != null) { + item.setDurability(Short.valueOf(itemAttribute[1])); + break; + } + break; + } + case "a": { + if (item != null) { + item.setAmount(Integer.valueOf(itemAttribute[1])); + break; + } + break; + } + case "e": { + if (item != null) { + item.addUnsafeEnchantment( + Enchantment.getById(Integer.valueOf(itemAttribute[1])), + Integer.valueOf(itemAttribute[2]) + ); + break; + } + break; + } + case "dn": { + if (meta != null) { + meta.setDisplayName(itemAttribute[1]); + break; + } + break; + } + case "l": { + itemAttribute[1] = itemAttribute[1].replace("[", ""); + itemAttribute[1] = itemAttribute[1].replace("]", ""); + List lore = Arrays.asList(itemAttribute[1].split(",")); + + for (int x = 0; x < lore.size(); ++x) { + String s = lore.get(x); + + if (s != null) { + if (s.toCharArray().length != 0) { + if (s.charAt(0) == ' ') { + s = s.replaceFirst(" ", ""); + } + + lore.set(x, s); + } + } + } + + if (meta != null) { + meta.setLore(lore); + break; + } + + break; + } +// case "pd": { +// if (item != null && item.getType() == Material.POTION) { +// String[] effectsList = itemAttribute[1].split("="); +// String[] potionData = effectsList[0].split("-"); +// +// Potion potion = new Potion(PotionType.getByDamageValue(Integer.valueOf(potionData[0])), +// Integer.valueOf(potionData[1])); +// potion.setSplash(item.getDurability() >= 16000); +// +// PotionMeta potionMeta = (PotionMeta) item.getItemMeta(); +// +// for (int i = 1; i < effectsList.length; i++) { +// String[] effectData = effectsList[1].split("-"); +// +// PotionEffect potionEffect = new PotionEffect(PotionEffectType.getById( +// Integer.valueOf(effectData[0])), Double.valueOf(effectData[1]).intValue(), +// Integer.valueOf(effectData[2]), false +// ); +// +// potionMeta.addCustomEffect(potionEffect, true); +// } +// +// item = potion.toItemStack(item.getAmount()); +// item.setItemMeta(potionMeta); +// } +// +// break; +// } + } + } + + if (meta != null && (meta.hasDisplayName() || meta.hasLore())) { + item.setItemMeta(meta); + } + + return item; + } + + public static String serializeEffect(PotionEffect item) { + StringBuilder builder = new StringBuilder(); + + if (item == null) { + return "null"; + } + + builder.append("t@").append(item.getType().getName()); + builder.append(":d@").append(item.getDuration()); + builder.append(":a@").append(item.getAmplifier()); + + return builder.toString(); + } + + public static PotionEffect deserializeEffect(String in) { + PotionEffect effect = null; + PotionEffectType type = null; + int duration = 0; + int amplifier = 0; + + String[] split = in.split(":"); + + for (String itemInfo : split) { + String[] itemAttribute = itemInfo.split("@"); + String attributeId = itemAttribute[0]; + + switch (attributeId) { + case "t": { + type = PotionEffectType.getByName(itemAttribute[1]); + break; + } + case "d": { + duration = Integer.parseInt(itemAttribute[1]); + break; + } + case "a": { + amplifier = Integer.parseInt(itemAttribute[1]); + break; + } + } + } + + effect = new PotionEffect(type, duration, amplifier); + + return effect; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/ItemBuilder.java b/src/main/java/dev/lugami/otaku/utils/ItemBuilder.java new file mode 100644 index 0000000..f64fdfd --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/ItemBuilder.java @@ -0,0 +1,122 @@ +package dev.lugami.otaku.utils; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.ArrayList; +import java.util.List; + +public class ItemBuilder implements Listener { + + private ItemStack is; + + public ItemBuilder(Material mat) { + is = new ItemStack(mat); + } + + public ItemBuilder(ItemStack is) { + this.is = is; + } + + public ItemBuilder amount(int amount) { + is.setAmount(amount); + return this; + } + + public ItemBuilder name(String name) { + ItemMeta meta = is.getItemMeta(); + meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + is.setItemMeta(meta); + return this; + } + + public ItemBuilder lore(String name) { + ItemMeta meta = is.getItemMeta(); + List lore = meta.getLore(); + + if (lore == null) { + lore = new ArrayList<>(); + } + + lore.add(ChatColor.translateAlternateColorCodes('&', name)); + meta.setLore(lore); + + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder lore(String... lore) { + List toSet = new ArrayList<>(); + ItemMeta meta = is.getItemMeta(); + + for (String string : lore) { + toSet.add(ChatColor.translateAlternateColorCodes('&', string)); + } + + meta.setLore(toSet); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder lore(List lore) { + List toSet = new ArrayList<>(); + ItemMeta meta = is.getItemMeta(); + + for (String string : lore) { + toSet.add(ChatColor.translateAlternateColorCodes('&', string)); + } + + meta.setLore(toSet); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder durability(int durability) { + is.setDurability((short) durability); + return this; + } + + public ItemBuilder enchantment(Enchantment enchantment, int level) { + is.addUnsafeEnchantment(enchantment, level); + return this; + } + + public ItemBuilder enchantment(Enchantment enchantment) { + is.addUnsafeEnchantment(enchantment, 1); + return this; + } + + public ItemBuilder type(Material material) { + is.setType(material); + return this; + } + + public ItemBuilder clearLore() { + ItemMeta meta = is.getItemMeta(); + + meta.setLore(new ArrayList<>()); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder clearEnchantments() { + for (Enchantment e : is.getEnchantments().keySet()) { + is.removeEnchantment(e); + } + + return this; + } + + public ItemStack build() { + return is; + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/ItemUtil.java b/src/main/java/dev/lugami/otaku/utils/ItemUtil.java new file mode 100644 index 0000000..e4364e4 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/ItemUtil.java @@ -0,0 +1,160 @@ +package dev.lugami.otaku.utils; + +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.Inventory; +import java.util.List; +import java.util.Collection; +import java.util.LinkedList; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.meta.ItemMeta; +import java.util.Arrays; +import org.bukkit.inventory.ItemStack; +import org.bukkit.Material; + +public final class ItemUtil +{ + private ItemUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + public static String formatMaterial(final Material material) { + String name = material.toString(); + name = name.replace('_', ' '); + String result = "" + name.charAt(0); + for (int i = 1; i < name.length(); ++i) { + if (name.charAt(i - 1) == ' ') { + result += name.charAt(i); + } + else { + result += Character.toLowerCase(name.charAt(i)); + } + } + return result; + } + + public static ItemStack enchantItem(final ItemStack itemStack, final ItemEnchant... enchantments) { + Arrays.asList(enchantments).forEach(enchantment -> itemStack.addUnsafeEnchantment(enchantment.enchantment, enchantment.level)); + return itemStack; + } + + public static ItemStack createItem(final Material material, final String name) { + final ItemStack item = new ItemStack(material); + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(name); + item.setItemMeta(meta); + return item; + } + + public static ItemStack createItem(final Material material, final String name, final int amount) { + final ItemStack item = new ItemStack(material, amount); + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(name); + item.setItemMeta(meta); + return item; + } + + public static ItemStack createItem(final Material material, final String name, final int amount, final short damage) { + final ItemStack item = new ItemStack(material, amount, damage); + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(name); + item.setItemMeta(meta); + return item; + } + + public static ItemStack hideEnchants(final ItemStack item) { + final ItemMeta meta = item.getItemMeta(); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + return item; + } + + public static ItemStack setUnbreakable(final ItemStack item) { + final ItemMeta meta = item.getItemMeta(); + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + return item; + } + + public static ItemStack renameItem(final ItemStack item, final String name) { + final ItemMeta meta = item.getItemMeta(); + meta.setDisplayName(name); + item.setItemMeta(meta); + return item; + } + + public static ItemStack reloreItem(final ItemStack item, final String... lores) { + return reloreItem(ReloreType.OVERWRITE, item, lores); + } + + public static ItemStack reloreItem(final ReloreType type, final ItemStack item, final String... lores) { + final ItemMeta meta = item.getItemMeta(); + List lore = (List)meta.getLore(); + if (lore == null) { + lore = new LinkedList(); + } + switch (type) { + case APPEND: { + lore.addAll(Arrays.asList(lores)); + meta.setLore(lore); + break; + } + case PREPEND: { + final List nLore = new LinkedList(Arrays.asList(lores)); + nLore.addAll(lore); + meta.setLore(nLore); + break; + } + case OVERWRITE: { + meta.setLore(Arrays.asList(lores)); + break; + } + } + item.setItemMeta(meta); + return item; + } + + public static void removeItems(final Inventory inventory, final ItemStack item, int amount) { + for (int size = inventory.getSize(), slot = 0; slot < size; ++slot) { + final ItemStack is = inventory.getItem(slot); + if (is != null && item.getType() == is.getType() && item.getDurability() == is.getDurability()) { + final int newAmount = is.getAmount() - amount; + if (newAmount > 0) { + is.setAmount(newAmount); + } + else { + inventory.setItem(slot, new ItemStack(Material.AIR)); + amount = -newAmount; + if (amount == 0) { + break; + } + } + } + } + } + + public static ItemStack addItemFlag(final ItemStack item, final ItemFlag flag) { + final ItemMeta meta = item.getItemMeta(); + meta.addItemFlags(new ItemFlag[] { flag }); + item.setItemMeta(meta); + return item; + } + + public enum ReloreType + { + OVERWRITE, + PREPEND, + APPEND; + } + + public static class ItemEnchant + { + private final Enchantment enchantment; + private final int level; + + public ItemEnchant(final Enchantment enchantment, final int level) { + this.enchantment = enchantment; + this.level = level; + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/LightningUtil.java b/src/main/java/dev/lugami/otaku/utils/LightningUtil.java new file mode 100644 index 0000000..381dc14 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/LightningUtil.java @@ -0,0 +1,55 @@ +package dev.lugami.otaku.utils; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketContainer; +import lombok.SneakyThrows; +import lombok.experimental.UtilityClass; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Player; + +import java.util.concurrent.ThreadLocalRandom; + +/** + * This Project is property of Refine Development © 2021 + * Redistribution of this Project is not allowed + * + * @author Drizzy + * Created: 9/27/2021 + * Project: Array + */ + +@UtilityClass +public class LightningUtil { + + /** + * Lightning through Protocol Lib cuz we care about the + * environment + * + * @param location {@link Location} where the lightning should spawn + */ + @SneakyThrows + public void spawnLightning(Player player, Location location) { + try { + PacketContainer lightningPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY_WEATHER); + + lightningPacket.getModifier().writeDefaults(); + lightningPacket.getIntegers().write(0, 128); + lightningPacket.getIntegers().write(4, 1); + lightningPacket.getIntegers().write(1, (int) (location.getX() * 32.0)); + lightningPacket.getIntegers().write(2, (int) (location.getY() * 32.0)); + lightningPacket.getIntegers().write(3, (int) (location.getZ() * 32.0)); + + ProtocolLibrary.getProtocolManager().sendServerPacket(player, lightningPacket); + + float thunderSoundPitch = 0.8f + ThreadLocalRandom.current().nextFloat() * 0.2f; + float explodeSoundPitch = 0.5f + ThreadLocalRandom.current().nextFloat() * 0.2f; + + player.playSound(location, Sound.AMBIENCE_THUNDER, 10000.0f, thunderSoundPitch); + player.playSound(location, Sound.EXPLODE, 2.0f, explodeSoundPitch); + } catch (Exception ex) { + ex.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/LocationUtil.java b/src/main/java/dev/lugami/otaku/utils/LocationUtil.java new file mode 100644 index 0000000..04d1e1a --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/LocationUtil.java @@ -0,0 +1,43 @@ +package dev.lugami.otaku.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +public class LocationUtil { + + public static Location[] getFaces(Location start) { + Location[] faces = new Location[4]; + faces[0] = new Location(start.getWorld(), start.getX() + 1, start.getY(), start.getZ()); + faces[1] = new Location(start.getWorld(), start.getX() - 1, start.getY(), start.getZ()); + faces[2] = new Location(start.getWorld(), start.getX(), start.getY() + 1, start.getZ()); + faces[3] = new Location(start.getWorld(), start.getX(), start.getY() - 1, start.getZ()); + return faces; + } + + public static String serialize(Location location) { + if (location == null) { + return "null"; + } + + return location.getWorld().getName() + ":" + location.getX() + ":" + location.getY() + ":" + location.getZ() + + ":" + location.getYaw() + ":" + location.getPitch(); + } + + public static Location deserialize(String source) { + if (source == null || source.equalsIgnoreCase("null")) { + return null; + } + + String[] split = source.split(":"); + World world = Bukkit.getServer().getWorld(split[0]); + + if (world == null) { + return null; + } + + return new Location(world, Double.parseDouble(split[1]), Double.parseDouble(split[2]), + Double.parseDouble(split[3]), Float.parseFloat(split[4]), Float.parseFloat(split[5])); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/NumberUtils.java b/src/main/java/dev/lugami/otaku/utils/NumberUtils.java new file mode 100644 index 0000000..346201a --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/NumberUtils.java @@ -0,0 +1,33 @@ +package dev.lugami.otaku.utils; + +import com.google.gson.Gson; + +import java.math.RoundingMode; +import java.text.DecimalFormat; + +public class NumberUtils { + + @lombok.Getter + public static Gson gson = new Gson(); + + public static Integer cutDecimal(Double d) { + DecimalFormat df = new DecimalFormat("#"); + df.setRoundingMode(RoundingMode.DOWN); + return Integer.parseInt(df.format(d)); + } + + public static boolean isDivisibleByNumber(int number, int divisible) { + int sumOfDigits = 0; + while (number > 0) { + sumOfDigits += number % 10; + number /= 10; + } + + return sumOfDigits % divisible == 0; + } + + public static boolean isInMultiplicationTableOfNumber(int number, int divisible) { + return number % divisible == 0; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/PlayerCache.java b/src/main/java/dev/lugami/otaku/utils/PlayerCache.java new file mode 100644 index 0000000..6ddf40e --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/PlayerCache.java @@ -0,0 +1,55 @@ +package dev.lugami.otaku.utils; + +import dev.lugami.otaku.profile.Profile; +import dev.lugami.otaku.profile.data.ProfileState; +import lombok.Getter; +import org.bukkit.Bukkit; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class PlayerCache { + + @Getter + private static final Map playerCache = new HashMap<>(); + + public static UUID getUUID(String name) { + UUID uuid = null; + if (getPlayerCache().containsKey(name)) { + uuid = getPlayerCache().get(name); + } + return uuid; + } + + public static int getInFFA() { + int i = 0; + for (Profile profile : Profile.getProfiles()) if (profile.getState() == ProfileState.PLAYING) i++; + return i; + } + + public static String getName(UUID uuid) { + for (UUID cachedUUID : playerCache.values()) { + if (cachedUUID.equals(uuid)) { + String name = playerCache.entrySet() + .stream() + .filter(entry -> entry.getValue().equals(uuid)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(null); + + if (name == null) { + try { + name = Bukkit.getOfflinePlayer(uuid).getName(); + } catch (IllegalArgumentException ignored) { + } + } + + return name; + } + } + + return null; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/PlayerEvent.java b/src/main/java/dev/lugami/otaku/utils/PlayerEvent.java new file mode 100644 index 0000000..5565b0d --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/PlayerEvent.java @@ -0,0 +1,27 @@ +package dev.lugami.otaku.utils; + +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.util.UUID; + +@Getter +public class PlayerEvent extends BaseEvent { + private Player player; + + public PlayerEvent(Player player) { + this(player, false); + } + + public PlayerEvent(Player player, boolean async) { + this.player = player; + } + + public Player getPlayer() { + return player; + } + + public UUID getUniqueId() { + return player.getUniqueId(); + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/PlayerUtil.java b/src/main/java/dev/lugami/otaku/utils/PlayerUtil.java new file mode 100644 index 0000000..1b1ee2c --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/PlayerUtil.java @@ -0,0 +1,89 @@ +package dev.lugami.otaku.utils; + +import dev.lugami.otaku.Main; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.spigotmc.AsyncCatcher; + +import java.util.UUID; + +public class PlayerUtil { + + public static void setLastAttacker(Player victim, Player attacker) { + victim.setMetadata("lastAttacker", new FixedMetadataValue(Main.getInstance(), attacker.getUniqueId())); + } + + public static Player getLastAttacker(Player victim) { + if (victim.hasMetadata("lastAttacker")) { + return Bukkit.getPlayer((UUID) victim.getMetadata("lastAttacker").get(0).value()); + } else { + return null; + } + } + + public static void denyMovement(Player player) { + player.setFlying(false); + player.setWalkSpeed(0.0F); + player.setFoodLevel(0); + player.setSprinting(false); + player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 200)); + } + + public static void allowMovement(Player player) { + player.setFlying(false); + player.setWalkSpeed(0.2F); + player.setFoodLevel(20); + player.setSprinting(true); + player.removePotionEffect(PotionEffectType.JUMP); + } + + public static void reset(Player player) { + reset(player, true); + } + + public static void reset(Player player, boolean resetHeldSlot) { + AsyncCatcher.enabled = false; + if (!player.hasMetadata("frozen")) { + player.setWalkSpeed(0.2F); + player.setFlySpeed(0.1F); + } + + player.setHealth(20.0D); + player.setSaturation(20.0F); + player.setFallDistance(0.0F); + player.setFoodLevel(20); + player.setFireTicks(0); + player.setMaximumNoDamageTicks(20); + player.setExp(0.0F); + player.setLevel(0); + player.setAllowFlight(false); + player.setFlying(false); + player.setGameMode(GameMode.SURVIVAL); + player.getInventory().setArmorContents(new ItemStack[4]); + player.getInventory().setContents(new ItemStack[36]); + player.getActivePotionEffects().forEach(effect -> player.removePotionEffect(effect.getType())); + + if (resetHeldSlot) player.getInventory().setHeldItemSlot(0); + + player.updateInventory(); + } + + public static int getRemainingPotions(ItemStack[] contents) { + int amount = 0; + + for (ItemStack itemStack : contents) { + if (itemStack != null && itemStack.getType() == Material.POTION && itemStack.getDurability() == 16421) { + amount++; + } + } + + return amount; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/TaskUtil.java b/src/main/java/dev/lugami/otaku/utils/TaskUtil.java new file mode 100644 index 0000000..cc42989 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/TaskUtil.java @@ -0,0 +1,77 @@ +package dev.lugami.otaku.utils; + +import dev.lugami.otaku.Main; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class TaskUtil { + + private static final ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(8); + + public static void scheduleAtFixedRateOnPool(Runnable runnable, long delay, long period, TimeUnit timeUnit) { + scheduledThreadPoolExecutor.scheduleAtFixedRate(runnable, delay, period, timeUnit); + } + + public static void scheduleOnPool(Runnable runnable, long delay, TimeUnit timeUnit) { + scheduledThreadPoolExecutor.schedule(runnable, delay, timeUnit); + } + + public static void executeWithPool(Runnable runnable) { + scheduledThreadPoolExecutor.execute(runnable); + } + + public static void run(Runnable runnable) { + Main.getInstance().getServer().getScheduler().runTask(Main.getInstance(), runnable); + } + + public static void runAsync(Runnable runnable) { + try { + Main.getInstance().getServer().getScheduler().runTaskAsynchronously(Main.getInstance(), runnable); + } catch (IllegalStateException e) { + Main.getInstance().getServer().getScheduler().runTask(Main.getInstance(), runnable); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + + public static void runTimer(Runnable runnable, long delay, long timer) { + Main.getInstance().getServer().getScheduler().runTaskTimer(Main.getInstance(), runnable, delay, timer); + } + + public static int runTimer(BukkitRunnable runnable, long delay, long timer) { + runnable.runTaskTimer(Main.getInstance(), delay, timer); + return runnable.getTaskId(); + } + + public static void runLater(Runnable runnable, long delay) { + Main.getInstance().getServer().getScheduler().runTaskLater(Main.getInstance(), runnable, delay); + } + + public static void runLaterAsync(Runnable runnable, long delay) { + try { + Main.getInstance().getServer().getScheduler().runTaskLaterAsynchronously(Main.getInstance(), runnable, delay); + } catch (IllegalStateException e) { + Main.getInstance().getServer().getScheduler().runTaskLater(Main.getInstance(), runnable, delay); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + + public static void runTimerAsync(Runnable runnable, long delay, long timer) { + try { + Main.getInstance().getServer().getScheduler().runTaskTimerAsynchronously(Main.getInstance(), runnable, delay, timer); + } catch (IllegalStateException e) { + Main.getInstance().getServer().getScheduler().runTaskTimer(Main.getInstance(), runnable, delay, timer); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } + } + + public static void runTimerAsync(BukkitRunnable runnable, long delay, long timer) { + Main.getInstance().getServer().getScheduler().runTaskTimerAsynchronously(Main.getInstance(), runnable, delay, timer); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/TextSplitter.java b/src/main/java/dev/lugami/otaku/utils/TextSplitter.java new file mode 100644 index 0000000..8a902d8 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/TextSplitter.java @@ -0,0 +1,50 @@ +package dev.lugami.otaku.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class TextSplitter { + + public static List split(int length, List lines, String linePrefix, String wordSuffix) { + StringBuilder builder = new StringBuilder(); + + for (String line : lines) { + builder.append(line.trim()); + builder.append(" "); + } + + return split(length, builder.substring(0, builder.length() - 1), linePrefix, wordSuffix); + } + + public static List split(int length, String text, String linePrefix, String wordSuffix) { + if (text.length() <= length) { + return Collections.singletonList(linePrefix + text); + } + + List lines = new ArrayList<>(); + String[] split = text.split(" "); + StringBuilder builder = new StringBuilder(linePrefix); + + for (int i = 0; i < split.length; ++i) { + if (builder.length() + split[i].length() >= length) { + lines.add(builder.toString()); + builder = new StringBuilder(linePrefix); + } + + builder.append(split[i]); + builder.append(wordSuffix); + + if (i == split.length - 1) { + builder.replace(builder.length() - wordSuffix.length(), builder.length(), ""); + } + } + + if (builder.length() != 0) { + lines.add(builder.toString()); + } + + return lines; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/TimeUtil.java b/src/main/java/dev/lugami/otaku/utils/TimeUtil.java new file mode 100644 index 0000000..e09740b --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/TimeUtil.java @@ -0,0 +1,146 @@ +package dev.lugami.otaku.utils; + +import java.sql.Timestamp; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class TimeUtil { + + private static final String HOUR_FORMAT = "%02d:%02d:%02d"; + private static final String MINUTE_FORMAT = "%02d:%02d"; + + private TimeUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + public static String millisToTimer(long millis) { + long seconds = millis / 1000L; + + if (seconds > 3600L) { + return String.format(HOUR_FORMAT, seconds / 3600L, seconds % 3600L / 60L, seconds % 60L); + } else { + return String.format(MINUTE_FORMAT, seconds / 60L, seconds % 60L); + } + } + + /** + * Return the amount of seconds from milliseconds. + * Note: We explicitly use 1000.0F (float) instead of 1000L (long). + * + * @param millis the amount of time in milliseconds + * @return the seconds + */ + public static String millisToSeconds(long millis) { + return new DecimalFormat("#0.0").format(millis / 1000.0F); + } + + public static String dateToString(Date date, String secondaryColor) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + return new SimpleDateFormat("MMM dd yyyy " + (secondaryColor == null ? "" : secondaryColor) + + "(hh:mm aa zz)").format(date); + } + + public static Timestamp addDuration(long duration) { + return truncateTimestamp(new Timestamp(System.currentTimeMillis() + duration)); + } + + public static Timestamp truncateTimestamp(Timestamp timestamp) { + if (timestamp.toLocalDateTime().getYear() > 2037) { + timestamp.setYear(2037); + } + + return timestamp; + } + + public static Timestamp addDuration(Timestamp timestamp) { + return truncateTimestamp(new Timestamp(System.currentTimeMillis() + timestamp.getTime())); + } + + public static Timestamp fromMillis(long millis) { + return new Timestamp(millis); + } + + public static Timestamp getCurrentTimestamp() { + return new Timestamp(System.currentTimeMillis()); + } + + public static String millisToRoundedTime(long millis) { + millis += 1L; + + long seconds = millis / 1000L; + long minutes = seconds / 60L; + long hours = minutes / 60L; + long days = hours / 24L; + long weeks = days / 7L; + long months = weeks / 4L; + long years = months / 12L; + + if (years > 0) { + return years + " year" + (years == 1 ? "" : "s"); + } else if (months > 0) { + return months + " month" + (months == 1 ? "" : "s"); + } else if (weeks > 0) { + return weeks + " week" + (weeks == 1 ? "" : "s"); + } else if (days > 0) { + return days + " day" + (days == 1 ? "" : "s"); + } else if (hours > 0) { + return hours + " hour" + (hours == 1 ? "" : "s"); + } else if (minutes > 0) { + return minutes + " minute" + (minutes == 1 ? "" : "s"); + } else { + return seconds + " second" + (seconds == 1 ? "" : "s"); + } + } + + public static long parseTime(String time) { + long totalTime = 0L; + boolean found = false; + Matcher matcher = Pattern.compile("\\d+\\D+").matcher(time); + + while (matcher.find()) { + String s = matcher.group(); + Long value = Long.parseLong(s.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)")[0]); + String type = s.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)")[1]; + + switch (type) { + case "s": + totalTime += value; + found = true; + break; + case "m": + totalTime += value * 60; + found = true; + break; + case "h": + totalTime += value * 60 * 60; + found = true; + break; + case "d": + totalTime += value * 60 * 60 * 24; + found = true; + break; + case "w": + totalTime += value * 60 * 60 * 24 * 7; + found = true; + break; + case "M": + totalTime += value * 60 * 60 * 24 * 30; + found = true; + break; + case "y": + totalTime += value * 60 * 60 * 24 * 365; + found = true; + break; + } + } + + return !found ? -1 : totalTime * 1000; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/board/Assemble.java b/src/main/java/dev/lugami/otaku/utils/board/Assemble.java new file mode 100644 index 0000000..cc45af9 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/Assemble.java @@ -0,0 +1,107 @@ +package dev.lugami.otaku.utils.board; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import dev.lugami.otaku.utils.board.event.AssembleBoardCreateEvent; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.plugin.java.JavaPlugin; + +@Getter @Setter +public class Assemble { + + private JavaPlugin plugin; + private AssembleAdapter adapter; + private Map boards; + private AssembleThread thread; + private AssembleListener listeners; + private long ticks = 2; + private boolean hook = false; + private AssembleStyle assembleStyle = AssembleStyle.MODERN; + private boolean debugMode = true; + + public Assemble(JavaPlugin plugin, AssembleAdapter adapter, long ticks, boolean hook, AssembleStyle style, boolean debug) { + if (plugin == null) { + throw new RuntimeException("Assemble can not be instantiated without a plugin instance!"); + } + + this.plugin = plugin; + this.adapter = adapter; + this.boards = new ConcurrentHashMap<>(); + this.ticks = ticks; + this.hook = hook; + this.assembleStyle = style; + this.debugMode = debug; + + this.setup(); + } + + public Assemble(JavaPlugin plugin, AssembleAdapter adapter) { + if (plugin == null) { + throw new RuntimeException("Assemble can not be instantiated without a plugin instance!"); + } + + this.plugin = plugin; + this.adapter = adapter; + this.boards = new ConcurrentHashMap<>(); + + this.setup(); + } + + public void setup() { + //Register Events + this.listeners = new AssembleListener(this); + this.plugin.getServer().getPluginManager().registerEvents(listeners, this.plugin); + + //Ensure that the thread has stopped running + if (this.thread != null) { + this.thread.stop(); + this.thread = null; + } + + //Register new boards for existing online players + for (Player player : Bukkit.getOnlinePlayers()) { + //Make sure it doesn't double up + AssembleBoardCreateEvent createEvent = new AssembleBoardCreateEvent(player); + + Bukkit.getPluginManager().callEvent(createEvent); + if (createEvent.isCancelled()) { + return; + } + + getBoards().putIfAbsent(player.getUniqueId(), new AssembleBoard(player, this)); + } + + //Start Thread + this.thread = new AssembleThread(this); + } + + public void cleanup() { + if (this.thread != null) { + this.thread.stop(); + this.thread = null; + } + + if (listeners != null) { + HandlerList.unregisterAll(listeners); + listeners = null; + } + + for (UUID uuid : getBoards().keySet()) { + Player player = Bukkit.getPlayer(uuid); + + if (player == null || !player.isOnline()) { + continue; + } + + getBoards().remove(uuid); + player.setScoreboard(Bukkit.getScoreboardManager().getNewScoreboard()); + } + } + + +} diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleAdapter.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleAdapter.java new file mode 100644 index 0000000..5c7fde0 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleAdapter.java @@ -0,0 +1,12 @@ +package dev.lugami.otaku.utils.board; + +import java.util.List; +import org.bukkit.entity.Player; + +public interface AssembleAdapter { + + String getTitle(Player player); + + List getLines(Player player); + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleBoard.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleBoard.java new file mode 100644 index 0000000..4f83250 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleBoard.java @@ -0,0 +1,97 @@ +package dev.lugami.otaku.utils.board; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import dev.lugami.otaku.utils.board.event.AssembleBoardCreatedEvent; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +public class AssembleBoard { + + // We assign a unique identifier (random string of ChatColor values) + // to each board entry to: bypass the 32 char limit, using + // a team's prefix & suffix and a team entry's display name, and to + // track the order of entries; + @Getter private final List entries = new ArrayList<>(); + @Getter private final List identifiers = new ArrayList<>(); + @Getter private final UUID uuid; + + @Getter private Assemble assemble; + + public AssembleBoard(Player player, Assemble assemble) { + this.uuid = player.getUniqueId(); + this.assemble = assemble; + this.setup(player); + } + + public Scoreboard getScoreboard() { + Player player = Bukkit.getPlayer(getUuid()); + if (getAssemble().isHook() || player.getScoreboard() != Bukkit.getScoreboardManager().getMainScoreboard()) { + return player.getScoreboard(); + } else { + return Bukkit.getScoreboardManager().getNewScoreboard(); + } + } + + public Objective getObjective() { + Scoreboard scoreboard = getScoreboard(); + if (scoreboard.getObjective("Assemble") == null) { + Objective objective = scoreboard.registerNewObjective("Assemble", "dummy"); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + objective.setDisplayName(getAssemble().getAdapter().getTitle(Bukkit.getPlayer(getUuid()))); + return objective; + } else { + return scoreboard.getObjective("Assemble"); + } + } + + + private void setup(Player player) { + Scoreboard scoreboard = getScoreboard(); + player.setScoreboard(scoreboard); + getObjective(); + + //Send Update + AssembleBoardCreatedEvent createdEvent = new AssembleBoardCreatedEvent(this); + Bukkit.getPluginManager().callEvent(createdEvent); + } + + public AssembleBoardEntry getEntryAtPosition(int pos) { + if (pos >= this.entries.size()) { + return null; + } else { + return this.entries.get(pos); + } + } + + public String getUniqueIdentifier(int position) { + String identifier = getRandomChatColor(position) + ChatColor.WHITE; + + while (this.identifiers.contains(identifier)) { + identifier = identifier + getRandomChatColor(position) + ChatColor.WHITE; + } + + // This is rare, but just in case, make the method recursive + if (identifier.length() > 16) { + return this.getUniqueIdentifier(position); + } + + // Add our identifier to the list so there are no duplicates + this.identifiers.add(identifier); + + return identifier; + } + + // Gets a random ChatColor and returns the String value of it + private static String getRandomChatColor(int position) { + return ChatColor.values()[position].toString(); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleBoardEntry.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleBoardEntry.java new file mode 100644 index 0000000..9d56d71 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleBoardEntry.java @@ -0,0 +1,98 @@ +package dev.lugami.otaku.utils.board; + +import lombok.Setter; +import org.bukkit.ChatColor; +import org.bukkit.scoreboard.Score; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +public class AssembleBoardEntry { + + private final AssembleBoard board; + @Setter private String text, identifier; + private Team team; + private int position; + + public AssembleBoardEntry(AssembleBoard board, String text, int position) { + this.board = board; + this.text = text; + this.position = position; + this.identifier = this.board.getUniqueIdentifier(position); + + this.setup(); + } + + public void setup() { + final Scoreboard scoreboard = this.board.getScoreboard(); + + if (scoreboard == null) { + return; + } + + String teamName = this.identifier; + + // This shouldn't happen, but just in case + if (teamName.length() > 16) { + teamName = teamName.substring(0, 16); + } + + Team team = scoreboard.getTeam(teamName); + + // Register the team if it does not exist + if (team == null) { + team = scoreboard.registerNewTeam(teamName); + } + + // Add the entry to the team + if (team.getEntries() == null || team.getEntries().isEmpty() || !team.getEntries().contains(this.identifier)) { + team.addEntry(this.identifier); + } + + // Add the entry if it does not exist + if (!this.board.getEntries().contains(this)) { + this.board.getEntries().add(this); + } + + this.team = team; + } + + public void send(int position) { + if (this.text.length() > 16) { + String prefix = this.text.substring(0, 16); + String suffix; + + if (prefix.charAt(15) == ChatColor.COLOR_CHAR) { + prefix = prefix.substring(0, 15); + suffix = this.text.substring(15, this.text.length()); + } else if (prefix.charAt(14) == ChatColor.COLOR_CHAR) { + prefix = prefix.substring(0, 14); + suffix = this.text.substring(14, this.text.length()); + } else { + if (ChatColor.getLastColors(prefix).equalsIgnoreCase(ChatColor.getLastColors(this.identifier))) { + suffix = this.text.substring(16, this.text.length()); + } else { + suffix = ChatColor.getLastColors(prefix) + this.text.substring(16, this.text.length()); + } + } + + if (suffix.length() > 16) { + suffix = suffix.substring(0, 16); + } + + this.team.setPrefix(prefix); + this.team.setSuffix(suffix); + } else { + this.team.setPrefix(this.text); + this.team.setSuffix(""); + } + + Score score = this.board.getObjective().getScore(this.identifier); + score.setScore(position); + } + + public void remove() { + this.board.getIdentifiers().remove(this.identifier); + this.board.getScoreboard().resetScores(this.identifier); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleException.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleException.java new file mode 100644 index 0000000..8d04b70 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleException.java @@ -0,0 +1,9 @@ +package dev.lugami.otaku.utils.board; + +public class AssembleException extends RuntimeException { + + public AssembleException(String message) { + super(message); + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleListener.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleListener.java new file mode 100644 index 0000000..bc5b7ba --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleListener.java @@ -0,0 +1,47 @@ +package dev.lugami.otaku.utils.board; + + +import dev.lugami.otaku.utils.board.event.AssembleBoardCreateEvent; +import dev.lugami.otaku.utils.board.event.AssembleBoardDestroyEvent; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +@Getter +public class AssembleListener implements Listener { + + private Assemble assemble; + + public AssembleListener(Assemble assemble) { + this.assemble = assemble; + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent event) { + AssembleBoardCreateEvent createEvent = new AssembleBoardCreateEvent(event.getPlayer()); + + Bukkit.getPluginManager().callEvent(createEvent); + if (createEvent.isCancelled()) { + return; + } + + getAssemble().getBoards().put(event.getPlayer().getUniqueId(), new AssembleBoard(event.getPlayer(), getAssemble())); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + AssembleBoardDestroyEvent destroyEvent = new AssembleBoardDestroyEvent(event.getPlayer()); + + Bukkit.getPluginManager().callEvent(destroyEvent); + if (destroyEvent.isCancelled()) { + return; + } + + getAssemble().getBoards().remove(event.getPlayer().getUniqueId()); + event.getPlayer().setScoreboard(Bukkit.getScoreboardManager().getMainScoreboard()); + } + + +} diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleStyle.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleStyle.java new file mode 100644 index 0000000..27375df --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleStyle.java @@ -0,0 +1,20 @@ +package dev.lugami.otaku.utils.board; + +import lombok.Getter; + +@Getter +public enum AssembleStyle { + + KOHI(true, 15), + VIPER(true, -1), + MODERN(false, 1), + MODIFIED(false, 0); + + private boolean decending; + private int startNumber; + + AssembleStyle(boolean decending, int startNumber) { + this.decending = decending; + this.startNumber = startNumber; + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/board/AssembleThread.java b/src/main/java/dev/lugami/otaku/utils/board/AssembleThread.java new file mode 100644 index 0000000..a9b2bf8 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/AssembleThread.java @@ -0,0 +1,112 @@ +package dev.lugami.otaku.utils.board; + +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; + +import java.util.Collections; +import java.util.List; + +public class AssembleThread extends Thread { + + private Assemble assemble; + + AssembleThread(Assemble assemble) { + this.assemble = assemble; + this.start(); + } + + @Override + public void run() { + while(true) { + //Tick + try { + tick(); + } catch (Exception e) { + e.printStackTrace(); + } + //Thread Sleep + try { + sleep(assemble.getTicks() * 50); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + private void tick() { + for (Player player : this.assemble.getPlugin().getServer().getOnlinePlayers()) { + try { + AssembleBoard board = this.assemble.getBoards().get(player.getUniqueId()); + + if (board == null) { + continue; + } + + Scoreboard scoreboard = board.getScoreboard(); + Objective objective = board.getObjective(); + + + if (scoreboard == null || objective == null) { + continue; + } + + String title = ChatColor.translateAlternateColorCodes('&', this.assemble.getAdapter().getTitle(player)); + + if (!objective.getDisplayName().equals(title)) { + objective.setDisplayName(title); + } + + List newLines = this.assemble.getAdapter().getLines(player); + + + if (newLines == null || newLines.isEmpty()) { + board.getEntries().forEach(AssembleBoardEntry::remove); + board.getEntries().clear(); + } else { + if (this.assemble.getAdapter().getLines(player).size() > 15) { + newLines = this.assemble.getAdapter().getLines(player).subList(0, 15); + } + + if (!this.assemble.getAssembleStyle().isDecending()) { + Collections.reverse(newLines); + } + + if (board.getEntries().size() > newLines.size()) { + for (int i = newLines.size(); i < board.getEntries().size(); i++) { + AssembleBoardEntry entry = board.getEntryAtPosition(i); + + if (entry != null) { + entry.remove(); + } + } + } + + int cache = this.assemble.getAssembleStyle().getStartNumber(); + for (int i = 0; i < newLines.size(); i++) { + AssembleBoardEntry entry = board.getEntryAtPosition(i); + + String line = ChatColor.translateAlternateColorCodes('&', newLines.get(i)); + + if (entry == null) { + entry = new AssembleBoardEntry(board, line, i); + } + + entry.setText(line); + entry.setup(); + entry.send( + this.assemble.getAssembleStyle().isDecending() ? cache-- : cache++ + ); + } + } + + if (player.getScoreboard() != scoreboard && !assemble.isHook()) { + player.setScoreboard(scoreboard); + } + } catch(Exception e) { + throw new AssembleException("There was an error updating " + player.getName() + "'s scoreboard."); + } + } + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardCreateEvent.java b/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardCreateEvent.java new file mode 100644 index 0000000..986d414 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardCreateEvent.java @@ -0,0 +1,31 @@ +package dev.lugami.otaku.utils.board.event; + +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter +public class AssembleBoardCreateEvent extends Event implements Cancellable { + + @Getter + public static HandlerList handlerList = new HandlerList(); + + private Player player; + private boolean cancelled = false; + + public AssembleBoardCreateEvent(Player player) { + this.player = player; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } + + @Override + public HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardCreatedEvent.java b/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardCreatedEvent.java new file mode 100644 index 0000000..b89fe10 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardCreatedEvent.java @@ -0,0 +1,25 @@ +package dev.lugami.otaku.utils.board.event; + +import dev.lugami.otaku.utils.board.AssembleBoard; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter @Setter +public class AssembleBoardCreatedEvent extends Event { + + @Getter public static HandlerList handlerList = new HandlerList(); + + private boolean cancelled = false; + private final AssembleBoard board; + + public AssembleBoardCreatedEvent(AssembleBoard board) { + this.board = board; + } + + @Override + public HandlerList getHandlers() { + return handlerList; + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardDestroyEvent.java b/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardDestroyEvent.java new file mode 100644 index 0000000..40a19c2 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/board/event/AssembleBoardDestroyEvent.java @@ -0,0 +1,31 @@ +package dev.lugami.otaku.utils.board.event; + +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +@Getter +public class AssembleBoardDestroyEvent extends Event implements Cancellable { + + @Getter + public static HandlerList handlerList = new HandlerList(); + + private Player player; + private boolean cancelled = false; + + public AssembleBoardDestroyEvent(Player player) { + this.player = player; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } + + @Override + public HandlerList getHandlers() { + return handlerList; + } +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/callback/Callback.java b/src/main/java/dev/lugami/otaku/utils/callback/Callback.java new file mode 100644 index 0000000..c6c503e --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/callback/Callback.java @@ -0,0 +1,12 @@ +package dev.lugami.otaku.utils.callback; + +import java.io.Serializable; + +public interface Callback extends Serializable { + + /** + * A callback for running a task on a set of data. + */ + void callback(); + +} diff --git a/src/main/java/dev/lugami/otaku/utils/callback/ReturnableTypeCallback.java b/src/main/java/dev/lugami/otaku/utils/callback/ReturnableTypeCallback.java new file mode 100644 index 0000000..c44d8b2 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/callback/ReturnableTypeCallback.java @@ -0,0 +1,7 @@ +package dev.lugami.otaku.utils.callback; + +public interface ReturnableTypeCallback { + + T call(); + +} diff --git a/src/main/java/dev/lugami/otaku/utils/callback/TypeCallback.java b/src/main/java/dev/lugami/otaku/utils/callback/TypeCallback.java new file mode 100644 index 0000000..cee4b53 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/callback/TypeCallback.java @@ -0,0 +1,14 @@ +package dev.lugami.otaku.utils.callback; + +import java.io.Serializable; + +public interface TypeCallback extends Serializable { + + /** + * A callback for running a task on a set of data. + * + * @param data the data needed to run the task. + */ + void callback(T data); + +} diff --git a/src/main/java/dev/lugami/otaku/utils/config/AbstractConfigurationFile.java b/src/main/java/dev/lugami/otaku/utils/config/AbstractConfigurationFile.java new file mode 100644 index 0000000..3e320f0 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/config/AbstractConfigurationFile.java @@ -0,0 +1,36 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package dev.lugami.otaku.utils.config; + +import java.util.List; + +import lombok.Getter; +import org.bukkit.plugin.java.JavaPlugin; + +@Getter +public abstract class AbstractConfigurationFile { + public static final String FILE_EXTENSION = ".yml"; + private final JavaPlugin plugin; + private final String name; + + public AbstractConfigurationFile(JavaPlugin plugin, String name) { + this.plugin = plugin; + this.name = name; + } + + public abstract String getString(String var1); + + public abstract String getStringOrDefault(String var1, String var2); + + public abstract int getInteger(String var1); + + public abstract double getDouble(String var1); + + public abstract Object get(String var1); + + public abstract List getStringList(String var1); + +} diff --git a/src/main/java/dev/lugami/otaku/utils/config/BasicConfigurationFile.java b/src/main/java/dev/lugami/otaku/utils/config/BasicConfigurationFile.java new file mode 100644 index 0000000..e379e93 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/config/BasicConfigurationFile.java @@ -0,0 +1,65 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package dev.lugami.otaku.utils.config; + +import java.io.File; +import java.util.List; +import org.bukkit.ChatColor; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +public class BasicConfigurationFile extends AbstractConfigurationFile { + private final File file; + private final YamlConfiguration configuration; + + public BasicConfigurationFile(JavaPlugin plugin, String name, boolean overwrite) { + super(plugin, name); + this.file = new File(plugin.getDataFolder(), name + ".yml"); + plugin.saveResource(name + ".yml", overwrite); + this.configuration = YamlConfiguration.loadConfiguration(this.file); + } + + public BasicConfigurationFile(JavaPlugin plugin, String name) { + this(plugin, name, false); + } + + public String getString(String path) { + return this.configuration.contains(path) ? ChatColor.translateAlternateColorCodes('&', this.configuration.getString(path)) : null; + } + + public String getStringOrDefault(String path, String or) { + String toReturn = this.getString(path); + return toReturn == null ? or : toReturn; + } + + public int getInteger(String path) { + return this.configuration.contains(path) ? this.configuration.getInt(path) : 0; + } + + public boolean getBoolean(String path) { + return this.configuration.contains(path) && this.configuration.getBoolean(path); + } + + public double getDouble(String path) { + return this.configuration.contains(path) ? this.configuration.getDouble(path) : 0.0; + } + + public Object get(String path) { + return this.configuration.contains(path) ? this.configuration.get(path) : null; + } + + public List getStringList(String path) { + return this.configuration.contains(path) ? this.configuration.getStringList(path) : null; + } + + public File getFile() { + return this.file; + } + + public YamlConfiguration getConfiguration() { + return this.configuration; + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/config/ConfigUtil.java b/src/main/java/dev/lugami/otaku/utils/config/ConfigUtil.java new file mode 100644 index 0000000..af8c141 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/config/ConfigUtil.java @@ -0,0 +1,13 @@ +package dev.lugami.otaku.utils.config; + +public class ConfigUtil { + + public static void save(BasicConfigurationFile config) { + try { + config.getConfiguration().save(config.getFile()); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/config/LanguageConfigurationFile.java b/src/main/java/dev/lugami/otaku/utils/config/LanguageConfigurationFile.java new file mode 100644 index 0000000..15c8424 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/config/LanguageConfigurationFile.java @@ -0,0 +1,241 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package dev.lugami.otaku.utils.config; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.bukkit.ChatColor; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +public class LanguageConfigurationFile extends AbstractConfigurationFile { + private static final LanguageConfigurationFileLocale DEFAULT_LOCALE; + private final Map configurations; + + public LanguageConfigurationFile(JavaPlugin plugin, String name, boolean overwrite) { + super(plugin, name); + this.configurations = new HashMap(); + LanguageConfigurationFileLocale[] var4 = LanguageConfigurationFileLocale.values(); + int var5 = var4.length; + + for(int var6 = 0; var6 < var5; ++var6) { + LanguageConfigurationFileLocale locale = var4[var6]; + File file = new File(plugin.getDataFolder(), name + "_" + locale.getAbbreviation() + ".yml"); + String path = name + "_" + locale.getAbbreviation() + ".yml"; + if (plugin.getResource(path) != null) { + plugin.saveResource(path, overwrite); + this.configurations.put(locale, YamlConfiguration.loadConfiguration(file)); + } + } + + } + + public LanguageConfigurationFile(JavaPlugin plugin, String name) { + this(plugin, name, false); + } + + public List replace(List list, int position, Object argument) { + List toReturn = new ArrayList(); + Iterator var5 = list.iterator(); + + while(var5.hasNext()) { + String string = (String)var5.next(); + toReturn.add(string.replace("{" + position + "}", argument.toString())); + } + + return toReturn; + } + + public List replace(List list, int position, Object... arguments) { + return this.replace(list, 0, position, arguments); + } + + public List replace(List list, int index, int position, Object... arguments) { + List toReturn = new ArrayList(); + Iterator var6 = list.iterator(); + + while(var6.hasNext()) { + String string = (String)var6.next(); + + for(int i = 0; i < arguments.length; ++i) { + toReturn.add(string.replace("{" + position + "}", arguments[index + i].toString())); + } + } + + return toReturn; + } + + public List getStringListWithArgumentsOrRemove(String path, LanguageConfigurationFileLocale locale, Object... arguments) { + List toReturn = new ArrayList(); + Iterator var5 = this.getStringList(path, locale).iterator(); + + while(true) { + label35: + while(var5.hasNext()) { + String string = (String)var5.next(); + + for(int i = 0; i < arguments.length; ++i) { + if (string.contains("{" + i + "}")) { + Object object = arguments[i]; + if (object == null) { + continue label35; + } + + if (object instanceof List) { + Iterator var9 = ((List)object).iterator(); + + while(var9.hasNext()) { + Object obj = var9.next(); + if (obj instanceof String) { + toReturn.add((String)obj); + } + } + continue label35; + } + + string = string.replace("{" + i + "}", object.toString()); + } + } + + toReturn.add(string); + } + + return toReturn; + } + } + + public int indexOf(List list, int position) { + for(int i = 0; i < list.size(); ++i) { + if (((String)list.get(i)).contains("{" + position + "}")) { + return i; + } + } + + return -1; + } + + public String getString(String path, LanguageConfigurationFileLocale locale) { + if (!this.configurations.containsKey(locale)) { + return locale == DEFAULT_LOCALE ? null : this.getString(path, DEFAULT_LOCALE); + } else { + YamlConfiguration configuration = (YamlConfiguration)this.configurations.get(locale); + return configuration.contains(path) ? ChatColor.translateAlternateColorCodes('&', configuration.getString(path)) : null; + } + } + + public String getString(String path, LanguageConfigurationFileLocale locale, Object... arguments) { + String toReturn = this.getString(path, locale); + if (toReturn == null) { + return null; + } else { + for(int i = 0; i < arguments.length; ++i) { + toReturn = toReturn.replace("{" + i + "}", arguments[i].toString()); + } + + return toReturn; + } + } + + public String getString(String path) { + return this.getString(path, DEFAULT_LOCALE); + } + + public String getStringOrDefault(String path, String or, LanguageConfigurationFileLocale locale) { + String toReturn = this.getString(path, locale); + return toReturn == null ? or : toReturn; + } + + public String getStringOrDefault(String path, String or) { + return this.getStringOrDefault(path, or, DEFAULT_LOCALE); + } + + public int getInteger(String path) { + throw new UnsupportedOperationException(""); + } + + /** @deprecated */ + @Deprecated + public double getDouble(String path) { + throw new UnsupportedOperationException(""); + } + + /** @deprecated */ + @Deprecated + public Object get(String path) { + throw new UnsupportedOperationException(""); + } + + public List getStringList(String path, LanguageConfigurationFileLocale locale, Object... arguments) { + List toReturn = new ArrayList(); + Iterator var5 = this.getStringList(path, locale).iterator(); + + while(true) { + label30: + while(var5.hasNext()) { + String line = (String)var5.next(); + + for(int i = 0; i < arguments.length; ++i) { + Object object = arguments[i]; + if (object instanceof List && line.contains("{" + i + "}")) { + Iterator var9 = ((List)object).iterator(); + + while(var9.hasNext()) { + Object obj = var9.next(); + if (obj instanceof String) { + toReturn.add(line.replace("{" + i + "}", "") + obj); + } + } + continue label30; + } + + line = line.replace("{" + i + "}", arguments[i].toString()); + } + + toReturn.add(line); + } + + return toReturn; + } + } + + public List getStringList(String path, LanguageConfigurationFileLocale locale) { + if (!this.configurations.containsKey(locale)) { + return locale == DEFAULT_LOCALE ? null : this.getStringList(path, DEFAULT_LOCALE); + } else { + YamlConfiguration configuration = (YamlConfiguration)this.configurations.get(locale); + if (!configuration.contains(path)) { + return Collections.emptyList(); + } else { + List toReturn = new ArrayList(); + Iterator var5 = configuration.getStringList(path).iterator(); + + while(var5.hasNext()) { + String string = (String)var5.next(); + toReturn.add(ChatColor.translateAlternateColorCodes('&', string)); + } + + return toReturn; + } + } + } + + public List getStringList(String path) { + return this.getStringList(path, DEFAULT_LOCALE); + } + + public Map getConfigurations() { + return this.configurations; + } + + static { + DEFAULT_LOCALE = LanguageConfigurationFileLocale.ENGLISH; + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/config/LanguageConfigurationFileLocale.java b/src/main/java/dev/lugami/otaku/utils/config/LanguageConfigurationFileLocale.java new file mode 100644 index 0000000..40a945c --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/config/LanguageConfigurationFileLocale.java @@ -0,0 +1,52 @@ +// +// Source code recreated from a .class file by IntelliJ IDEA +// (powered by FernFlower decompiler) +// + +package dev.lugami.otaku.utils.config; + +public enum LanguageConfigurationFileLocale { + ENGLISH("en"), + EXPLICIT("ex"), + FRENCH("fr"), + SPANISH("es"), + PORTUGUESE("pt"); + + private final String abbreviation; + + private LanguageConfigurationFileLocale(String abbreviation) { + this.abbreviation = abbreviation; + } + + public static LanguageConfigurationFileLocale getByAbbreviation(String abbreviation) { + LanguageConfigurationFileLocale[] var1 = values(); + int var2 = var1.length; + + for(int var3 = 0; var3 < var2; ++var3) { + LanguageConfigurationFileLocale locale = var1[var3]; + if (locale.getAbbreviation().equalsIgnoreCase(abbreviation)) { + return locale; + } + } + + return ENGLISH; + } + + public static LanguageConfigurationFileLocale getByName(String name) { + LanguageConfigurationFileLocale[] var1 = values(); + int var2 = var1.length; + + for(int var3 = 0; var3 < var2; ++var3) { + LanguageConfigurationFileLocale locale = var1[var3]; + if (locale.name().equalsIgnoreCase(name)) { + return locale; + } + } + + return ENGLISH; + } + + public String getAbbreviation() { + return this.abbreviation; + } +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/Button.java b/src/main/java/dev/lugami/otaku/utils/menu/Button.java new file mode 100644 index 0000000..2a15c39 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/Button.java @@ -0,0 +1,54 @@ +package dev.lugami.otaku.utils.menu; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +public abstract class Button { + + public static Button placeholder(final Material material, final byte data, String... title) { + return (new Button() { + public ItemStack getButtonItem(Player player) { + ItemStack it = new ItemStack(material, 1, data); + ItemMeta meta = it.getItemMeta(); + + meta.setDisplayName(StringUtils.join(title)); + it.setItemMeta(meta); + + return it; + } + }); + } + + public static void playFail(Player player) { + player.playSound(player.getLocation(), Sound.DIG_GRASS, 20F, 0.1F); + + } + + public static void playSuccess(Player player) { + player.playSound(player.getLocation(), Sound.NOTE_PIANO, 20F, 15F); + } + + public static void playNeutral(Player player) { + player.playSound(player.getLocation(), Sound.CLICK, 20F, 1F); + } + + public abstract ItemStack getButtonItem(Player player); + + public void clicked(Player player, ClickType clickType) {} + + public void clicked(Player player, int slot, ClickType clickType, int hotbarSlot) {} + + public boolean shouldCancel(Player player, ClickType clickType) { + return true; + } + + public boolean shouldUpdate(Player player, ClickType clickType) { + return false; + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/menu/Menu.java b/src/main/java/dev/lugami/otaku/utils/menu/Menu.java new file mode 100644 index 0000000..9eaee98 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/Menu.java @@ -0,0 +1,142 @@ +package dev.lugami.otaku.utils.menu; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.utils.CC; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.HashMap; +import java.util.Map; + +@Getter +@Setter +public abstract class Menu { + + public static Map currentlyOpenedMenus = new HashMap<>(); + + @Getter protected Main plugin = Main.getInstance(); + private Map buttons = new HashMap<>(); + private boolean autoUpdate = false; + private boolean updateAfterClick = true; + private boolean closedByMenu = false; + private boolean placeholder = false; + private dev.lugami.otaku.utils.menu.Button placeholderButton = dev.lugami.otaku.utils.menu.Button.placeholder(Material.STAINED_GLASS_PANE, (byte) 15, " "); + + private ItemStack createItemStack(Player player, Button button) { + ItemStack item = button.getButtonItem(player); + + if (item.getType() != Material.SKULL_ITEM) { + ItemMeta meta = item.getItemMeta(); + + if (meta != null && meta.hasDisplayName()) { + meta.setDisplayName(meta.getDisplayName() + "§b§c§d§e"); + } + + item.setItemMeta(meta); + } + + return item; + } + + public void openMenu(final Player player) { + this.buttons = this.getButtons(player); + + Menu previousMenu = Menu.currentlyOpenedMenus.get(player.getName()); + Inventory inventory = null; + int size = this.getSize() == -1 ? this.size(this.buttons) : this.getSize(); + boolean update = false; + String title = CC.translate(this.getTitle(player)); + + if (title.length() > 32) { + title = title.substring(0, 32); + } + + if (player.getOpenInventory() != null) { + if (previousMenu == null) { + player.closeInventory(); + } else { + int previousSize = player.getOpenInventory().getTopInventory().getSize(); + + if (previousSize == size && player.getOpenInventory().getTopInventory().getTitle().equals(title)) { + inventory = player.getOpenInventory().getTopInventory(); + update = true; + } else { + previousMenu.setClosedByMenu(true); + /** + * I FUCKING LOVE YOU NMS <3 + * (no more mouse position resetting every time you open a menu.) + */ + ((CraftPlayer) player).getHandle().p(); + } + } + } + + if (inventory == null) { + inventory = Bukkit.createInventory(player, size, title); + } + + inventory.setContents(new ItemStack[inventory.getSize()]); + + currentlyOpenedMenus.put(player.getName(), this); + + for (Map.Entry buttonEntry : this.buttons.entrySet()) { + inventory.setItem(buttonEntry.getKey(), createItemStack(player, buttonEntry.getValue())); + } + + if (this.isPlaceholder()) { + for (int index = 0; index < size; index++) { + if (this.buttons.get(index) == null) { + this.buttons.put(index, this.placeholderButton); + inventory.setItem(index, this.placeholderButton.getButtonItem(player)); + } + } + } + + if (update) { + player.updateInventory(); + } else { + player.openInventory(inventory); + } + + this.onOpen(player); + this.setClosedByMenu(false); + } + + public int size(Map buttons) { + int highest = 0; + + for (int buttonValue : buttons.keySet()) { + if (buttonValue > highest) { + highest = buttonValue; + } + } + + return (int) (Math.ceil((highest + 1) / 9D) * 9D); + } + + public int getSize() { + return -1; + } + + public int getSlot(int x, int y) { + return ((9 * y) + x); + } + + public abstract String getTitle(Player player); + + public abstract Map getButtons(Player player); + + public void onOpen(Player player) { + } + + public void onClose(Player player) { + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/MenuListener.java b/src/main/java/dev/lugami/otaku/utils/menu/MenuListener.java new file mode 100644 index 0000000..37163ac --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/MenuListener.java @@ -0,0 +1,91 @@ +package dev.lugami.otaku.utils.menu; + +import dev.lugami.otaku.Main; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; + +public class MenuListener implements Listener { + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onButtonPress(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Menu openMenu = Menu.currentlyOpenedMenus.get(player.getName()); + + if (openMenu != null) { + if (event.getSlot() != event.getRawSlot()) { + if ((event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT)) { + event.setCancelled(true); + } + + return; + } + + if (openMenu.getButtons().containsKey(event.getSlot())) { + Button button = openMenu.getButtons().get(event.getSlot()); + boolean cancel = button.shouldCancel(player, event.getClick()); + + if (!cancel && (event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT)) { + event.setCancelled(true); + + if (event.getCurrentItem() != null) { + player.getInventory().addItem(event.getCurrentItem()); + } + } else { + event.setCancelled(cancel); + } + + button.clicked(player, event.getClick()); + button.clicked(player, event.getSlot(), event.getClick(), event.getHotbarButton()); + + if (Menu.currentlyOpenedMenus.containsKey(player.getName())) { + Menu newMenu = Menu.currentlyOpenedMenus.get(player.getName()); + + if (newMenu == openMenu) { + boolean buttonUpdate = button.shouldUpdate(player, event.getClick()); + + if (buttonUpdate) { + openMenu.setClosedByMenu(true); + newMenu.openMenu(player); + } + } + } else if (button.shouldUpdate(player, event.getClick())) { + openMenu.setClosedByMenu(true); + openMenu.openMenu(player); + } + + if (event.isCancelled()) { + Bukkit.getScheduler().runTaskLater(Main.getInstance(), player::updateInventory, 1L); + } + } else { + if (event.getCurrentItem() != null) { + event.setCancelled(true); + } + + if ((event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT)) { + event.setCancelled(true); + } + } + } + } + + @EventHandler(priority = EventPriority.HIGH) + public void onInventoryClose(InventoryCloseEvent event) { + Player player = (Player) event.getPlayer(); + Menu openMenu = Menu.currentlyOpenedMenus.get(player.getName()); + + if (openMenu != null) { + openMenu.onClose(player); + + Menu.currentlyOpenedMenus.remove(player.getName()); + } + } + +} \ No newline at end of file diff --git a/src/main/java/dev/lugami/otaku/utils/menu/button/BackButton.java b/src/main/java/dev/lugami/otaku/utils/menu/button/BackButton.java new file mode 100644 index 0000000..9a4fba1 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/button/BackButton.java @@ -0,0 +1,37 @@ +package dev.lugami.otaku.utils.menu.button; + +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import lombok.AllArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +@AllArgsConstructor +public class BackButton extends Button { + + private Menu back; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.REDSTONE) + .name(CC.RED + CC.BOLD + "Back") + .lore(Arrays.asList( + CC.RED + "Click here to return to", + CC.RED + "the previous menu.") + ) + .build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + Button.playNeutral(player); + back.openMenu(player); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/button/ConfirmationButton.java b/src/main/java/dev/lugami/otaku/utils/menu/button/ConfirmationButton.java new file mode 100644 index 0000000..8fdd507 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/button/ConfirmationButton.java @@ -0,0 +1,54 @@ +package dev.lugami.otaku.utils.menu.button; + +import dev.lugami.otaku.utils.callback.TypeCallback; +import lombok.AllArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +@AllArgsConstructor +public class ConfirmationButton extends Button { + + private boolean confirm; + private TypeCallback callback; + private boolean closeAfterResponse; + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack itemStack = new ItemStack(Material.WOOL, 1, this.confirm ? ((byte) 5) : ((byte) 14)); + ItemMeta itemMeta = itemStack.getItemMeta(); + + itemMeta.setDisplayName(this.confirm ? ChatColor.GREEN + "Confirm" : ChatColor.RED + "Cancel"); + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + + @Override + public void clicked(Player player, ClickType clickType) { + if (this.confirm) { + player.playSound(player.getLocation(), Sound.NOTE_PIANO, 20f, 0.1f); + } else { + player.playSound(player.getLocation(), Sound.DIG_GRAVEL, 20f, 0.1F); + } + + if (this.closeAfterResponse) { + Menu menu = Menu.currentlyOpenedMenus.get(player.getName()); + + if (menu != null) { + menu.setClosedByMenu(true); + } + + player.closeInventory(); + } + + this.callback.callback(this.confirm); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/button/DisplayButton.java b/src/main/java/dev/lugami/otaku/utils/menu/button/DisplayButton.java new file mode 100644 index 0000000..72ee643 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/button/DisplayButton.java @@ -0,0 +1,34 @@ +package dev.lugami.otaku.utils.menu.button; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import dev.lugami.otaku.utils.menu.Button; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +@Getter +@Setter +public class DisplayButton extends Button { + + private ItemStack itemStack; + private boolean cancel; + + @Override + public ItemStack getButtonItem(Player player) { + if (this.itemStack == null) { + return new ItemStack(Material.AIR); + } else { + return this.itemStack; + } + } + + @Override + public boolean shouldCancel(Player player, ClickType clickType) { + return this.cancel; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/button/JumpToMenuButton.java b/src/main/java/dev/lugami/otaku/utils/menu/button/JumpToMenuButton.java new file mode 100644 index 0000000..61106e3 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/button/JumpToMenuButton.java @@ -0,0 +1,29 @@ +package dev.lugami.otaku.utils.menu.button; + +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +public class JumpToMenuButton extends Button { + + private Menu menu; + private ItemStack itemStack; + + public JumpToMenuButton(Menu menu, ItemStack itemStack) { + this.menu = menu; + this.itemStack = itemStack; + } + + @Override + public ItemStack getButtonItem(Player player) { + return itemStack; + } + + @Override + public void clicked(Player player, ClickType clickType) { + menu.openMenu(player); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/menus/ConfirmMenu.java b/src/main/java/dev/lugami/otaku/utils/menu/menus/ConfirmMenu.java new file mode 100644 index 0000000..5c1c9be --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/menus/ConfirmMenu.java @@ -0,0 +1,53 @@ +package dev.lugami.otaku.utils.menu.menus; + +import dev.lugami.otaku.utils.callback.TypeCallback; +import dev.lugami.otaku.utils.menu.button.ConfirmationButton; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +public class ConfirmMenu extends Menu { + + private String title; + private TypeCallback response; + private boolean closeAfterResponse; + private Button[] centerButtons; + + public ConfirmMenu(String title, TypeCallback response, boolean closeAfter, Button... centerButtons) { + this.title = title; + this.response = response; + this.closeAfterResponse = closeAfter; + this.centerButtons = centerButtons; + } + + @Override + public Map getButtons(Player player) { + HashMap buttons = new HashMap<>(); + + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + buttons.put(getSlot(x, y), new ConfirmationButton(true, response, closeAfterResponse)); + buttons.put(getSlot(8 - x, y), new ConfirmationButton(false, response, closeAfterResponse)); + } + } + + if (centerButtons != null) { + for (int i = 0; i < centerButtons.length; i++) { + if (centerButtons[i] != null) { + buttons.put(getSlot(4, i), centerButtons[i]); + } + } + } + + return buttons; + } + + @Override + public String getTitle(Player player) { + return title; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/FilterablePaginatedMenu.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/FilterablePaginatedMenu.java new file mode 100644 index 0000000..3c69f8d --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/FilterablePaginatedMenu.java @@ -0,0 +1,40 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import lombok.Getter; +import lombok.Setter; +import dev.lugami.otaku.utils.menu.Button; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class FilterablePaginatedMenu extends PaginatedMenu { + + @Getter private final List> filters; + @Getter @Setter private int scrollIndex = 0; + + { + filters = generateFilters(); + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + buttons.put(7, new PageFilterButton<>(this)); + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + return getFilteredButtons(player); + } + + public abstract Map getFilteredButtons(Player player); + + public List> generateFilters() { + return new ArrayList<>(); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/JumpToPageButton.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/JumpToPageButton.java new file mode 100644 index 0000000..54f4283 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/JumpToPageButton.java @@ -0,0 +1,46 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import lombok.AllArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; + +@AllArgsConstructor +public class JumpToPageButton extends Button { + + private int page; + private PaginatedMenu menu; + private boolean current; + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack itemStack = new ItemStack(this.current ? Material.ENCHANTED_BOOK : Material.BOOK, this.page); + ItemMeta itemMeta = itemStack.getItemMeta(); + + itemMeta.setDisplayName(ChatColor.YELLOW + "Page " + this.page); + + if (this.current) { + itemMeta.setLore(Arrays.asList( + "", + ChatColor.GREEN + "Current page" + )); + } + + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + + @Override + public void clicked(Player player, ClickType clickType) { + this.menu.modPage(player, this.page - this.menu.getPage()); + Button.playNeutral(player); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageButton.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageButton.java new file mode 100644 index 0000000..1084d86 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageButton.java @@ -0,0 +1,90 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import dev.lugami.otaku.utils.ItemBuilder; +import lombok.AllArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +@AllArgsConstructor +public class PageButton extends Button { + + private int mod; + private PaginatedMenu menu; + + @Override + public ItemStack getButtonItem(Player player) { + if (this.mod > 0) { + if (hasNext(player)) { + return new ItemBuilder(Material.REDSTONE_TORCH_ON) + .name(ChatColor.GREEN + "Next Page") + .lore(Arrays.asList( + ChatColor.YELLOW + "Click here to jump", + ChatColor.YELLOW + "to the next page." + )) + .build(); + } else { + return new ItemBuilder(Material.LEVER) + .name(ChatColor.GRAY + "Next Page") + .lore(Arrays.asList( + ChatColor.YELLOW + "There is no available", + ChatColor.YELLOW + "next page." + )) + .build(); + } + } else { + if (hasPrevious(player)) { + return new ItemBuilder(Material.REDSTONE_TORCH_ON) + .name(ChatColor.GREEN + "Previous Page") + .lore(Arrays.asList( + ChatColor.YELLOW + "Click here to jump", + ChatColor.YELLOW + "to the previous page." + )) + .build(); + } else { + return new ItemBuilder(Material.LEVER) + .name(ChatColor.GRAY + "Previous Page") + .lore(Arrays.asList( + ChatColor.YELLOW + "There is no available", + ChatColor.YELLOW + "previous page." + )) + .build(); + } + } + } + + @Override + public void clicked(Player player, ClickType clickType) { + if (this.mod > 0) { + if (hasNext(player)) { + this.menu.modPage(player, this.mod); + Button.playNeutral(player); + } else { + Button.playFail(player); + } + } else { + if (hasPrevious(player)) { + this.menu.modPage(player, this.mod); + Button.playNeutral(player); + } else { + Button.playFail(player); + } + } + } + + private boolean hasNext(Player player) { + int pg = this.menu.getPage() + this.mod; + return this.menu.getPages(player) >= pg; + } + + private boolean hasPrevious(Player player) { + int pg = this.menu.getPage() + this.mod; + return pg > 0; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageFilter.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageFilter.java new file mode 100644 index 0000000..6cfd6c6 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageFilter.java @@ -0,0 +1,25 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +import java.util.function.Predicate; + +@RequiredArgsConstructor +public class PageFilter { + + @Getter private final String name; + @Getter @Setter private boolean enabled; + private final Predicate predicate; + + public boolean test(T t) { + return !enabled || predicate.test(t); + } + + @Override + public boolean equals(Object object) { + return object instanceof PageFilter && ((PageFilter) object).getName().equals(name); + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageFilterButton.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageFilterButton.java new file mode 100644 index 0000000..9d9b45c --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageFilterButton.java @@ -0,0 +1,85 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import dev.lugami.otaku.utils.CC; +import dev.lugami.otaku.utils.ItemBuilder; +import lombok.AllArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import org.apache.commons.lang.StringEscapeUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +@AllArgsConstructor +public class PageFilterButton extends Button { + + private FilterablePaginatedMenu menu; + + @Override + public ItemStack getButtonItem(Player player) { + if (menu.getFilters() == null || menu.getFilters().isEmpty()) { + return new ItemStack(Material.AIR); + } + + List lore = new ArrayList<>(); + lore.add(CC.MENU_BAR); + + for (PageFilter filter : menu.getFilters()) { + String color; + String decoration = ""; + String icon; + + if (filter.isEnabled()) { + color = ChatColor.GREEN.toString(); + icon = StringEscapeUtils.unescapeJava("\u2713"); + } else { + color = ChatColor.RED.toString(); + icon = StringEscapeUtils.unescapeJava("\u2717"); + } + + if (menu.getFilters().get(menu.getScrollIndex()).equals(filter)) { + decoration = ChatColor.YELLOW + StringEscapeUtils.unescapeJava("» ") + " "; + } + + lore.add(decoration + color + icon + " " + filter.getName()); + } + + lore.add(CC.MENU_BAR); + lore.add("&eLeft click to scroll."); + lore.add("&eRight click to toggle a filter."); + lore.add(CC.MENU_BAR); + + return new ItemBuilder(Material.HOPPER) + .name("&7Filters") + .lore(lore) + .build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + if (menu.getFilters() == null || menu.getFilters().isEmpty()) { + player.sendMessage(ChatColor.RED + "There are no filters."); + } else { + if (clickType == ClickType.LEFT) { + if (menu.getScrollIndex() == menu.getFilters().size() - 1) { + menu.setScrollIndex(0); + } else { + menu.setScrollIndex(menu.getScrollIndex() + 1); + } + } else if (clickType == ClickType.RIGHT) { + PageFilter filter = menu.getFilters().get(menu.getScrollIndex()); + filter.setEnabled(!filter.isEnabled()); + } + } + } + + @Override + public boolean shouldUpdate(Player player, ClickType clickType) { + return true; + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageInfoButton.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageInfoButton.java new file mode 100644 index 0000000..671ecc3 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PageInfoButton.java @@ -0,0 +1,41 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import dev.lugami.otaku.utils.ItemBuilder; +import lombok.AllArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class PageInfoButton extends Button { + + private PaginatedMenu menu; + + @Override + public ItemStack getButtonItem(Player player) { + int pages = menu.getPages(player); + + return new ItemBuilder(Material.PAPER) + .name(ChatColor.GOLD + "Page Info") + .lore( + ChatColor.YELLOW + "You are viewing page #" + menu.getPage() + ".", + ChatColor.YELLOW + (pages == 1 ? "There is 1 page." : "There are " + pages + " pages."), + "", + ChatColor.YELLOW + "Middle click here to", + ChatColor.YELLOW + "view all pages." + ) + .build(); + } + + @Override + public void clicked(Player player, ClickType clickType) { + if (clickType == ClickType.RIGHT) { + new ViewAllPagesMenu(this.menu).openMenu(player); + playNeutral(player); + } + } + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/PaginatedMenu.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PaginatedMenu.java new file mode 100644 index 0000000..c0d71a8 --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/PaginatedMenu.java @@ -0,0 +1,116 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import lombok.Getter; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +public abstract class +PaginatedMenu extends Menu { + + @Getter private int page = 1; + + { + setUpdateAfterClick(false); + } + + @Override + public String getTitle(Player player) { + return getPrePaginatedTitle(player); + } + + /** + * Changes the page number + * + * @param player player viewing the inventory + * @param mod delta to modify the page number by + */ + public final void modPage(Player player, int mod) { + page += mod; + getButtons().clear(); + openMenu(player); + } + + /** + * @param player player viewing the inventory + */ + public final int getPages(Player player) { + int buttonAmount = getAllPagesButtons(player).size(); + + if (buttonAmount == 0) { + return 1; + } + + return (int) Math.ceil(buttonAmount / (double) getMaxItemsPerPage(player)); + } + + @Override + public final Map getButtons(Player player) { + int minIndex = (int) ((double) (page - 1) * getMaxItemsPerPage(player)); + int maxIndex = (int) ((double) (page) * getMaxItemsPerPage(player)); + int topIndex = 0; + + HashMap buttons = new HashMap<>(); + + for (Map.Entry entry : getAllPagesButtons(player).entrySet()) { + int ind = entry.getKey(); + + if (ind >= minIndex && ind < maxIndex) { + ind -= (int) ((double) (getMaxItemsPerPage(player)) * (page - 1)) - 9; + buttons.put(ind, entry.getValue()); + + if (ind > topIndex) { + topIndex = ind; + } + } + } + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + + for (int i = 1; i < 8; i++) { + buttons.put(i, getPlaceholderButton()); + } + + Map global = getGlobalButtons(player); + + if (global != null) { + for (Map.Entry gent : global.entrySet()) { + buttons.put(gent.getKey(), gent.getValue()); + } + } + + return buttons; + } + + public int getMaxItemsPerPage(Player player) { + return 18; + } + + /** + * @param player player viewing the inventory + * + * @return a Map of button that returns items which will be present on all pages + */ + public Map getGlobalButtons(Player player) { + return null; + } + + /** + * @param player player viewing the inventory + * + * @return title of the inventory before the page number is added + */ + public abstract String getPrePaginatedTitle(Player player); + + /** + * @param player player viewing the inventory + * + * @return a map of button that will be paginated and spread across pages + */ + public abstract Map getAllPagesButtons(Player player); + +} diff --git a/src/main/java/dev/lugami/otaku/utils/menu/pagination/ViewAllPagesMenu.java b/src/main/java/dev/lugami/otaku/utils/menu/pagination/ViewAllPagesMenu.java new file mode 100644 index 0000000..6ef2e3d --- /dev/null +++ b/src/main/java/dev/lugami/otaku/utils/menu/pagination/ViewAllPagesMenu.java @@ -0,0 +1,50 @@ +package dev.lugami.otaku.utils.menu.pagination; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import dev.lugami.otaku.utils.menu.Button; +import dev.lugami.otaku.utils.menu.Menu; +import dev.lugami.otaku.utils.menu.button.BackButton; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +@RequiredArgsConstructor +public class ViewAllPagesMenu extends Menu { + + @NonNull + @Getter + PaginatedMenu menu; + + @Override + public String getTitle(Player player) { + return "Jump to page"; + } + + @Override + public Map getButtons(Player player) { + HashMap buttons = new HashMap<>(); + + buttons.put(0, new BackButton(menu)); + + int index = 10; + + for (int i = 1; i <= menu.getPages(player); i++) { + buttons.put(index++, new JumpToPageButton(i, menu, menu.getPage() == i)); + + if ((index - 8) % 9 == 0) { + index += 2; + } + } + + return buttons; + } + + @Override + public boolean isAutoUpdate() { + return true; + } + +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml new file mode 100644 index 0000000..236f8d6 --- /dev/null +++ b/src/main/resources/config.yml @@ -0,0 +1,7 @@ +HOTBAR_ITEMS: + MAIN_MENU: + MATERIAL: "NETHER_STAR" + DURABILITY: 0 + NAME: "&b&lMain Menu" + SLOT: 4 + LORE: [] \ No newline at end of file diff --git a/src/main/resources/kits.yml b/src/main/resources/kits.yml new file mode 100644 index 0000000..77957a6 --- /dev/null +++ b/src/main/resources/kits.yml @@ -0,0 +1 @@ +kits: \ No newline at end of file diff --git a/src/main/resources/profiles.yml b/src/main/resources/profiles.yml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/scoreboard.yml b/src/main/resources/scoreboard.yml new file mode 100644 index 0000000..24fad0f --- /dev/null +++ b/src/main/resources/scoreboard.yml @@ -0,0 +1,29 @@ +scoreboard: + global: + title: "&b&lFFA" + lobby: + - "&7&m---------------------" + - "&bOnline: &f" + - "&bPlaying: &f" + - "" + - "&7&oilovefemboys.xyz" + - "&7&m---------------------" + ffa: + - "&7&m---------------------" + - "&bKills: &f" + - "&bDeaths: &f" + - "&bKillstreak: &f" + - "" + - "" + - "" + - "&7&oilovefemboys.xyz" + - "&7&m---------------------" + profile: + - "&7&m---------------------" + - "&cYour profile was not loaded." + - "&cTry rejoining." + - "" + - "&7&oilovefemboys.xyz" + - "&7&m---------------------" + combat-addition: "&c&lCombat Tag: s" + enderpearl-addition: "&c&lEnderpearl: s" \ No newline at end of file