diff --git a/LandCore/.idea/.gitignore b/LandCore/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/LandCore/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/LandCore/.idea/LandCore.iml b/LandCore/.idea/LandCore.iml new file mode 100644 index 0000000..fa63d4b --- /dev/null +++ b/LandCore/.idea/LandCore.iml @@ -0,0 +1,12 @@ + + + + + + + SPIGOT + + + + + \ No newline at end of file diff --git a/LandCore/.idea/artifacts/LandCore.xml b/LandCore/.idea/artifacts/LandCore.xml new file mode 100644 index 0000000..92e100c --- /dev/null +++ b/LandCore/.idea/artifacts/LandCore.xml @@ -0,0 +1,6 @@ + + + $PROJECT_DIR$/out/artifacts/LandCore + + + \ No newline at end of file diff --git a/LandCore/.idea/compiler.xml b/LandCore/.idea/compiler.xml new file mode 100644 index 0000000..79340ac --- /dev/null +++ b/LandCore/.idea/compiler.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/LandCore/.idea/discord.xml b/LandCore/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/LandCore/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/LandCore/.idea/encodings.xml b/LandCore/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/LandCore/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/LandCore/.idea/inspectionProfiles/Project_Default.xml b/LandCore/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..8fc8123 --- /dev/null +++ b/LandCore/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,19 @@ + + + + \ No newline at end of file diff --git a/LandCore/.idea/jarRepositories.xml b/LandCore/.idea/jarRepositories.xml new file mode 100644 index 0000000..43e93b5 --- /dev/null +++ b/LandCore/.idea/jarRepositories.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LandCore/.idea/jpa-buddy.xml b/LandCore/.idea/jpa-buddy.xml new file mode 100644 index 0000000..966d5f5 --- /dev/null +++ b/LandCore/.idea/jpa-buddy.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/LandCore/.idea/misc.xml b/LandCore/.idea/misc.xml new file mode 100644 index 0000000..8c87c88 --- /dev/null +++ b/LandCore/.idea/misc.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LandCore/.idea/uiDesigner.xml b/LandCore/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/LandCore/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LandCore/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar b/LandCore/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar new file mode 100644 index 0000000..b8e579f Binary files /dev/null and b/LandCore/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar differ diff --git a/LandCore/lib/NickAPI-v6.5.jar b/LandCore/lib/NickAPI-v6.5.jar new file mode 100644 index 0000000..6520100 Binary files /dev/null and b/LandCore/lib/NickAPI-v6.5.jar differ diff --git a/LandCore/lib/ProtocolLib.jar b/LandCore/lib/ProtocolLib.jar new file mode 100644 index 0000000..74682ff Binary files /dev/null and b/LandCore/lib/ProtocolLib.jar differ diff --git a/LandCore/lib/ViaVersion-3.2.1.jar b/LandCore/lib/ViaVersion-3.2.1.jar new file mode 100644 index 0000000..c68ea80 Binary files /dev/null and b/LandCore/lib/ViaVersion-3.2.1.jar differ diff --git a/LandCore/pom.xml b/LandCore/pom.xml new file mode 100644 index 0000000..2c53d52 --- /dev/null +++ b/LandCore/pom.xml @@ -0,0 +1,156 @@ + + + 4.0.0 + + me.devkevin.landcore + LandCore + 1.3-SNAPSHOT + jar + + + 1.8 + UTF-8 + + + + + destroystokyo-releases + https://repo.destroystokyo.com/repository/maven-releases/ + + + destroystokyo-snapshots + https://repo.destroystokyo.com/repository/maven-snapshots/ + + + + + + + + club.inverted + inverted-spigot + 1.8.8-R0.1-SNAPSHOT + system + ${project.basedir}/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar + + + + + org.mongodb + mongo-java-driver + 3.12.11 + compile + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + + xyz.haoshoku.nick + nickapi + 5.0.2-SNAPSHOT + system + ${project.basedir}/lib/NickAPI-v6.5.jar + + + + + org.projectlombok + lombok + 1.18.24 + provided + + + + redis.clients + jedis + 2.9.0 + compile + + + + + com.google.code.gson + gson + 2.8.0 + + + + + org.apache.commons + commons-lang3 + 3.3.2 + + + + + com.googlecode.json-simple + json-simple + 1.1.1 + provided + + + + + ViaVersion-3.2.1 + ViaVersion-3.2.1 + 1.0-SNAPSHOT + system + ${project.basedir}/lib/ViaVersion-3.2.1.jar + + + + + com.comphenix.protocol + ProtocolLib + yes + system + ${project.basedir}/lib/ProtocolLib.jar + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + false + + + + + + + + + src/main/resources + true + + + + \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/LandCore.java b/LandCore/src/main/java/me/devkevin/landcore/LandCore.java new file mode 100644 index 0000000..a30964b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/LandCore.java @@ -0,0 +1,346 @@ +package me.devkevin.landcore; + +import com.google.common.collect.Maps; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import lombok.Getter; +import me.devkevin.landcore.commands.impl.*; +import me.devkevin.landcore.commands.impl.staff.*; +import me.devkevin.landcore.commands.impl.staff.punish.*; +import me.devkevin.landcore.commands.impl.toggle.ToggleGlobalChat; +import me.devkevin.landcore.commands.impl.toggle.ToggleMessagesCommand; +import me.devkevin.landcore.commands.impl.toggle.ToggleSoundsCommand; +import me.devkevin.landcore.disguise.commands.DisguiseCommand; +import me.devkevin.landcore.disguise.manager.DisguiseManager; +import me.devkevin.landcore.disguise.commands.UndisguiseCommand; +import me.devkevin.landcore.disguise.menu.DisguiseMenu; +import me.devkevin.landcore.faction.commands.FactionHelpCommand; +import me.devkevin.landcore.faction.commands.captain.*; +import me.devkevin.landcore.faction.commands.leader.FactionDescriptionCommand; +import me.devkevin.landcore.faction.commands.leader.FactionDisbandCommand; +import me.devkevin.landcore.faction.commands.player.*; +import me.devkevin.landcore.faction.listener.FactionListener; +import me.devkevin.landcore.faction.manager.FactionManager; +import me.devkevin.landcore.gson.CustomLocationTypeAdapterFactory; +import me.devkevin.landcore.gson.ItemStackTypeAdapterFactory; +import me.devkevin.landcore.listeners.*; +import me.devkevin.landcore.listeners.redis.*; +import me.devkevin.landcore.managers.MenuManager; +import me.devkevin.landcore.managers.PlayerManager; +import me.devkevin.landcore.managers.ProfileManager; +import me.devkevin.landcore.managers.StaffManager; +import me.devkevin.landcore.nametag.NameTagAdapter; +import me.devkevin.landcore.nametag.impl.InternalNametag; +import me.devkevin.landcore.player.color.ColorCommand; +import me.devkevin.landcore.player.color.SetColorCommand; +import me.devkevin.landcore.player.color.menu.ColorMenu; +import me.devkevin.landcore.player.grant.procedure.GrantProcedureListener; +import me.devkevin.landcore.player.info.UserCommand; +import me.devkevin.landcore.player.notes.commands.NoteAddCommand; +import me.devkevin.landcore.player.notes.commands.NoteRemoveCommand; +import me.devkevin.landcore.player.notes.commands.NotesCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.player.rank.commands.*; +import me.devkevin.landcore.player.tags.PrefixCommand; +import me.devkevin.landcore.player.tags.menu.PrefixMenu; +import me.devkevin.landcore.punishment.listener.PunishmentListener; +import me.devkevin.landcore.redis.RedisMessenger; +import me.devkevin.landcore.server.ServerSettings; +import me.devkevin.landcore.server.filter.Filter; +import me.devkevin.landcore.storage.database.MongoStorage; +import me.devkevin.landcore.store.StorePCoinMenu; +import me.devkevin.landcore.task.BroadcastTask; +import me.devkevin.landcore.task.GrantDisguiseCheckTask; +import me.devkevin.landcore.utils.inventory.UIListener; +import me.devkevin.landcore.utils.menu.ButtonListener; +import me.devkevin.landcore.utils.menu.MenuUpdateTask; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.packet.PacketAdapter; +import me.devkevin.landcore.utils.packet.PacketListener; +import me.devkevin.landcore.utils.structure.Cuboid; +import net.minecraft.server.v1_8_R3.Packet; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandMap; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.ConfigurationSerialization; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Map; +import java.util.Random; +import java.util.logging.Level; +import java.util.logging.Logger; + +@Getter +public class LandCore extends JavaPlugin { + @Getter + private static LandCore instance; + + public static GsonBuilder GSONBUILDER; + public static Gson GSON; + public static final Random RANDOM = new Random(); + + private ServerSettings serverSettings; + private Filter filter; + private MongoStorage mongoStorage; + + private ProfileManager profileManager; + private StaffManager staffManager; + private PlayerManager playerManager; + private MenuManager menuManager; + private RedisMessenger redisMessenger; + private static Field bukkitCommandMap; + private PrefixMenu prefixMenu; + private ColorMenu colorMenu; + private DisguiseMenu disguiseMenu; + private DisguiseManager disguiseManager; + private PacketListener packetListener; + private FactionManager factionManager; + private StorePCoinMenu storePCoinMenu; + + private static void registerSerializableClass(Class clazz) { + if (ConfigurationSerializable.class.isAssignableFrom(clazz)) { + Class serializable = clazz.asSubclass(ConfigurationSerializable.class); + ConfigurationSerialization.registerClass(serializable); + } + } + + @Override + public void onEnable() { + instance = this; + + LandCore.GSONBUILDER = new GsonBuilder() + .registerTypeAdapterFactory(new CustomLocationTypeAdapterFactory()) + .registerTypeAdapterFactory(new ItemStackTypeAdapterFactory()); + LandCore.GSON = LandCore.GSONBUILDER.create(); + + getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + saveDefaultConfig(); + + registerSerializableClass(Cuboid.class); + + serverSettings = new ServerSettings(this); + filter = new Filter(); + + redisMessenger = new RedisMessenger( + this, + getConfig().getString("redis.host"), + getConfig().getInt("redis.port"), + getConfig().getInt("redis.timeout"), + getConfig().getString("redis.password") + ); + + redisMessenger.registerListeners( + new FreezeListener(this), + new FrozenDisconnectListener(this), + new HelpopListener(this), + new ReportListener(this), + new StaffChatListener(this), + new StaffStreamListener(this), + new RedisServerMonitorListener(this), + new RedisFactionListener(this) + ); + + redisMessenger.initialize(); + mongoStorage = new MongoStorage(this); + + this.disableLoggers(); + this.addServerMonitor(); + + Bukkit.getConsoleSender().sendMessage(CC.SEPARATOR); + Bukkit.getConsoleSender().sendMessage(CC.translate("&eLandCore &8- &b" + getDescription().getVersion())); + Bukkit.getConsoleSender().sendMessage(CC.translate(" ")); + Bukkit.getConsoleSender().sendMessage(CC.translate("&b • &eDeveloper: &eDevKevin")); + Bukkit.getConsoleSender().sendMessage(CC.translate("&b • &eMongo: &f" + (mongoStorage.isConnected() ? "&aenabled" : "&cdisabled"))); + Bukkit.getConsoleSender().sendMessage(CC.translate("&b • &eRedis: &f" + (redisMessenger.isActive() ? "&aenabled" : "&cdisabled"))); + Bukkit.getConsoleSender().sendMessage(CC.SEPARATOR); + + profileManager = new ProfileManager(); + staffManager = new StaffManager(this); + playerManager = new PlayerManager(); + menuManager = new MenuManager(this); + prefixMenu = new PrefixMenu(); + colorMenu = new ColorMenu(); + disguiseMenu = new DisguiseMenu(); + disguiseManager = new DisguiseManager(); + factionManager = new FactionManager(); + storePCoinMenu = new StorePCoinMenu(); + + new InternalNametag(this, new NameTagAdapter()); + //LandSpigot.getInstance().registerPacketHandler(new EntityPacketHandler()); + + Arrays.asList( + new BroadcastCommand(this), + new ClearChatCommand(this), + new IgnoreCommand(this), + new ListCommand(), + new MessageCommand(this), + new RankCommand(this), + new ReplyCommand(this), + new StaffChatCommand(this), + new TeleportCommand(this), + new ToggleMessagesCommand(this), + new ToggleGlobalChat(this), + new ToggleSoundsCommand(this), + new VanishCommand(this), + new ReportCommand(this), + new CheckCommand(this), + new HelpOpCommand(this), + new PingCommand(), + new BanCommand(this), + new MuteCommand(this), + new UnbanCommand(this), + new UnmuteCommand(this), + new WarnCommand(this), + new KickCommand(this), + new MuteChatCommand(this), + new SlowChatCommand(this), + new GameModeCommand(), + new ShutdownCommand(this), + new FreezeCommand(this), + new WhitelistCommand(this), + new GrantCommand(this), + new GrantsCommand(this), + new QuickGrantCommand(this), + new UserCommand(this), + new PlayTimeCommand(this), + new RankListCommand(), + new NoteAddCommand(this), + new NoteRemoveCommand(this), + new NotesCommand(this), + new MisplaceCommand(this), + new PrefixCommand(this), + new ColorCommand(this), + new SetColorCommand(this), + new BuildServerCommand(this), + new TeleportPositionCommand(this), + new FeedCommand(this), + new HealCommand(this), + new AltsCommand(this), + new UndisguiseCommand(this), + new DisguiseCommand(this), + new EnchantCommand(this), + + // factions + new FactionHelpCommand(this), + new FactionAcceptCommand(this), + new FactionCreateCommand(this), + new FactionLeaveCommand(this), + new FactionInfoCommand(this), + new FactionDescriptionCommand(this), + new FactionDisbandCommand(this), + new FactionDemoteCommand(this), + new FactionInviteCommand(this), + new FactionKickCommand(this), + new FactionPasswordCommand(this), + new FactionPromoteCommand(this), + new FactionChatCommand(this), + + new PCoinsCommand(this), + new StoreCommand(this) + ).forEach(command -> registerCommand(command, getName())); + + Arrays.asList( + new PlayerListener(this), + new ButtonListener(), + new MessageListener(this), + new InventoryListener(this), + new HelpCommandListener(this), + new PlayerInteractListener(this), + new UIListener(), + new GrantProcedureListener(this), + new PunishmentListener(), + new FactionListener() + ).forEach(listener -> getServer().getPluginManager().registerEvents(listener, this)); + + getServer().getScheduler().runTaskTimerAsynchronously(this, new BroadcastTask(this), 20 * 120L, 20 * 120L); + new MenuUpdateTask(); + new GrantDisguiseCheckTask(); + + //WindSpigot.getInstance().registerPacketListener(new PacketListener()); + + packetListener = new PacketListener(); + new PlayerPacketListener(this, packetListener); + + Rank.importRanks(); + CC.logConsole(CC.PRIMARY + "[LandCore] " + CC.SECONDARY + "Core has started successfully."); + CC.logConsole(CC.PRIMARY + "[LandCore] " + CC.GREEN + " All databases connected successfully."); + + getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { + factionManager.save(); + }, 0L, 6000L); + } + + @Override + public void onDisable() { + this.getServer().getScheduler().cancelTasks(this); + + Map message = Maps.newHashMap(); + message.put("server", this.getServerName()); + + this.getRedisMessenger().sendOff("server-monitor-remove", message); + + factionManager.save(); + getServer().getOnlinePlayers().parallelStream().forEach(player -> factionManager.savePlayerFaction(player)); + + try { + Thread.sleep(1000L); + } catch (Exception e) { + e.printStackTrace(); + } + + for (Player player : getServer().getOnlinePlayers()) { + player.kickPlayer(CC.RED + "The server is restarting."); + + // remove fake players + LandCore.getInstance().getPlayerManager().getDummyPlayers().remove(player.getUniqueId()); + } + + profileManager.saveProfiles(); + serverSettings.saveConfig(); + + Bukkit.getScheduler().cancelTasks(this); + } + + public String getServerName() { + return getConfig().getString("server_name"); + } + + public String getNetworkName() { + return getConfig().getString("network_name"); + } + + public void registerCommand(Command cmd, String fallbackPrefix) { + try { + if (bukkitCommandMap == null) { + bukkitCommandMap = Bukkit.getServer().getClass().getDeclaredField("commandMap"); + bukkitCommandMap.setAccessible(true); + } + CommandMap commandMap = (CommandMap) bukkitCommandMap.get(Bukkit.getServer()); + commandMap.register(cmd.getName(), fallbackPrefix, cmd); + } catch (Exception e) { + Bukkit.getLogger().info("[LandCore] CommandMap failed to register."); + e.printStackTrace(); + } + } + + private void disableLoggers() { + Logger.getLogger("org.mongodb.driver.connection").setLevel(Level.OFF); + Logger.getLogger("org.mongodb.driver.cluster").setLevel(Level.OFF); + } + + private void addServerMonitor() { + Map message = Maps.newHashMap(); + message.put("server", this.getServerName()); + + this.getRedisMessenger().send("server-monitor-add", message); + } + + public > void registerAdapter(Class classType, PacketAdapter handler) { + packetListener.registerAdapter(classType, handler); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/LandCoreAPI.java b/LandCore/src/main/java/me/devkevin/landcore/LandCoreAPI.java new file mode 100644 index 0000000..7308a30 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/LandCoreAPI.java @@ -0,0 +1,191 @@ +package me.devkevin.landcore; + +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import lombok.Getter; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.PlayerVersion; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.message.CC; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; +import us.myles.ViaVersion.api.Via; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 13:49 + * CorePluginAPI / land.pvp.core / LandCore + */ +@UtilityClass +public class LandCoreAPI { + public final static ItemStack PLACEHOLDER_ITEM = new ItemBuilder(Material.STAINED_GLASS_PANE) + .durability(7) + .name("&a") + .lore(" ") + .hideFlags() + .build(); + + public static String getColorPing(int ping) { + if (ping <= 40) return CC.translate("&a" + ping); + if (ping <= 70) return CC.translate("&e" + ping); + if (ping <= 100) return CC.translate("&6" + ping); + else return CC.translate("&c" + ping); + } + + public static boolean isInteger(String index) { + try { + Integer.parseInt(index); + return true; + } catch (Exception ignored) { + return false; + } + } + + public static void sendToServer(Player player, String server) { + try { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("Connect"); + out.writeUTF(server); + player.sendMessage(CC.translate("&aSending to " + server + "...")); + player.sendPluginMessage(LandCore.getInstance(), "BungeeCord", out.toByteArray()); + } catch (Exception e) { + player.sendMessage(CC.translate("&cAn Error occurred while sending to the server.")); + } + } + + public static int getMaxEnchantLevel(Player player) { + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.hasRank(Rank.DEVELOPER)) return 9999; + if (profile.hasRank(Rank.DEVELOPER)) return 21; + if (profile.hasRank(Rank.DEVELOPER)) return 14; + if (profile.hasRank(Rank.DEVELOPER)) return 7; + + return 5; + } + + public static Enchantment getEnchantmentByName(Object object) { + String value = object.toString().replace("_", "").trim(); + + switch (value.toUpperCase()) { + case "PROT": + case "PROTECTION": + return Enchantment.PROTECTION_ENVIRONMENTAL; + case "UNB": + case "UNBREAKING": + return Enchantment.DURABILITY; + case "FIREP": + case "FP": + case "FIREPROTECTION": + return Enchantment.PROTECTION_FIRE; + case "FEATHERF": + case "FL": + case "FEATHERFALLING": + return Enchantment.PROTECTION_FALL; + case "BLASTP": + case "BP": + case "BLASTPROTECTION": + return Enchantment.PROTECTION_EXPLOSIONS; + case "SHARP": + case "SHARPNESS": + return Enchantment.DAMAGE_ALL; + case "KNOCK": + case "KNOCKBACK": + return Enchantment.KNOCKBACK; + case "FIREA": + case "FA": + case "FIRE": + case "FIREASPECT": + return Enchantment.FIRE_ASPECT; + case "L": + case "LOOT": + case "LOOTING": + return Enchantment.LOOT_BONUS_MOBS; + case "F": + case "FORT": + case "FORTUNE": + return Enchantment.LOOT_BONUS_BLOCKS; + case "ST": + case "SILK": + case "SILKTOUCH": + return Enchantment.SILK_TOUCH; + case "EFF": + case "EFFICIENCY": + return Enchantment.DIG_SPEED; + case "SM": + case "SMITE": + return Enchantment.DAMAGE_UNDEAD; + case "INF": + case "INFINITY": + return Enchantment.ARROW_INFINITE; + case "FLA": + case "FLAME": + return Enchantment.ARROW_FIRE; + case "PUNCH": + return Enchantment.ARROW_KNOCKBACK; + case "POWER": + return Enchantment.ARROW_DAMAGE; + default: + return null; + } + } + + public enum Language { + USE_NUMBERS("USE_NUMBERS", "{prefix} &cPlease use numbers."), + ENCHANT_MUST_HOLD_ITEM("ENCHANT.MUST-HOLD-ITEM", "{prefix} &eYou must hold item in order to enchant."), + ENCHANT_ENCHANT_MUST_BE_POSITIVE("ENCHANT.ENCHANT-MUST-BE-POSITIVE", "{prefix} &eEnchant level must be positive."), + ENCHANT_MAXIMUM_LEVEL_EXCEEDED("ENCHANT.MAXIMUM-LEVEL-EXCEEDED", "{prefix} &eYour maximum level for enchant is &6&e."), + ENCHANT_WRONG_ENCHANTMENT("ENCHANT.WRONG-ENCHANTMENT", "{prefix} &eYou've entered wrong enchantment."), + ENCHANT_ITEM_DOESNT_HAVE_ENCHANT("ENCHANT.ITEM-IS-NOT-ENCHANTED", "{prefix} &eYour item does not have that enchantment."), + ENCHANT_REMOVED("ENCHANT.REMOVED", "{prefix} &eYou've removed &6 &eenchantment from your item."), + ENCHANT_ADDED("ENCHANT.ADDED", "{prefix} &eYou've added &6 &eenchantment to your item."); + + @Getter + private String path; + @Getter + private String value; + @Getter + private List listValue; + + Language(String path, String value) { + this.path = path; + this.value = value; + this.listValue = new ArrayList<>(Collections.singletonList(value)); + } + } + + public PlayerVersion getPlayerVersion(Player player) { + return PlayerVersion.getVersionFromRaw(Via.getAPI().getPlayerVersion(player.getUniqueId())); + } + + public abstract class LandCoreListener implements Listener { + public LandCoreListener(JavaPlugin javaPlugin) { + Bukkit.getServer().getPluginManager().registerEvents(this, javaPlugin); + } + } + + public static String getTodayDate() { + Date todayDate = new Date(); + DateFormat todayDateFormat = new SimpleDateFormat("MMM dd, yyyy"); + todayDateFormat.setTimeZone(TimeZone.getTimeZone("US/Eastern")); + return todayDateFormat.format(todayDate); + } + + public static String getCurrentTime() { + DateFormat dateFormat = new SimpleDateFormat("hh:mm a"); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("US/Eastern")); + dateFormat.setTimeZone(cal.getTimeZone()); + return dateFormat.format(cal.getTime()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/callback/DocumentCallback.java b/LandCore/src/main/java/me/devkevin/landcore/callback/DocumentCallback.java new file mode 100644 index 0000000..0ccf6ec --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/callback/DocumentCallback.java @@ -0,0 +1,7 @@ +package me.devkevin.landcore.callback; + +import org.bson.Document; + +public interface DocumentCallback { + void call(Document document, boolean found); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/callback/WebCallback.java b/LandCore/src/main/java/me/devkevin/landcore/callback/WebCallback.java new file mode 100644 index 0000000..22aed18 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/callback/WebCallback.java @@ -0,0 +1,5 @@ +package me.devkevin.landcore.callback; + +public interface WebCallback { + void callback(String response); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/BaseCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/BaseCommand.java new file mode 100644 index 0000000..16a1a57 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/BaseCommand.java @@ -0,0 +1,66 @@ +package me.devkevin.landcore.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.Collections; + +public abstract class BaseCommand extends Command { + private static final String LINE_SEPARATOR = System.lineSeparator(); + private final Rank requiredRank; + + protected BaseCommand(String name, Rank requiredRank) { + super(name); + this.requiredRank = requiredRank; + } + + protected BaseCommand(String name) { + this(name, Rank.MEMBER); + } + + @Override + public final boolean execute(CommandSender sender, String alias, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (!profile.hasRank(requiredRank)) { + player.sendMessage(CC.RED + "You don't have the required rank to perform this command."); + return true; + } + } + + execute(sender, args); + return true; + } + + protected final void setAliases(String... aliases) { + if (aliases.length > 0) { + setAliases(aliases.length == 1 ? Collections.singletonList(aliases[0]) : Arrays.asList(aliases)); + } + } + + protected final void setUsage(String... uses) { + StringBuilder builder = new StringBuilder(); + + for (int i = 0; i < uses.length; i++) { + String use = uses[i]; + + builder.append(use); + + if (i + 1 != uses.length) { + builder.append(LINE_SEPARATOR); + } + } + + setUsage(builder.toString()); + } + + protected abstract void execute(CommandSender sender, String[] args); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/PlayerCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/PlayerCommand.java new file mode 100644 index 0000000..172761f --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/PlayerCommand.java @@ -0,0 +1,27 @@ +package me.devkevin.landcore.commands; + +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public abstract class PlayerCommand extends BaseCommand { + protected PlayerCommand(String name, Rank requiredRank) { + super(name, requiredRank); + } + + protected PlayerCommand(String name) { + super(name, Rank.MEMBER); + } + + @Override + protected final void execute(CommandSender sender, String[] args) { + if (sender instanceof Player) { + execute((Player) sender, args); + } else { + sender.sendMessage(CC.RED + "Only players can perform this command."); + } + } + + public abstract void execute(Player player, String[] args); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ClearChatCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ClearChatCommand.java new file mode 100644 index 0000000..127d663 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ClearChatCommand.java @@ -0,0 +1,36 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Collections; + +public class ClearChatCommand extends BaseCommand { + private static final String BLANK_MESSAGE = String.join("", Collections.nCopies(150, "§8 §8 §1 §3 §3 §7 §8 §r\n")); + private final LandCore plugin; + + public ClearChatCommand(LandCore plugin) { + super("clearchat", Rank.TRIAL_MOD); + this.plugin = plugin; + setAliases("cc"); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + for (Player player : plugin.getServer().getOnlinePlayers()) { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (!profile.hasStaff()) { + player.sendMessage(BLANK_MESSAGE); + } + } + + plugin.getServer().broadcastMessage(CC.GREEN + "The chat was cleared by " + sender.getName() + "."); + sender.sendMessage(CC.YELLOW + "Don't worry, staff can still see cleared messages."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/EnchantCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/EnchantCommand.java new file mode 100644 index 0000000..3dc7f18 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/EnchantCommand.java @@ -0,0 +1,87 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.LandCoreAPI; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.TaskUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 13/02/2023 @ 19:55 + * EnchantCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class EnchantCommand extends BaseCommand { + private final LandCore plugin; + + public EnchantCommand(LandCore plugin) { + super("enchant", Rank.DEVELOPER); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + TaskUtil.runAsync(() -> { + Player player = (Player) sender; + + if (args.length < 2) { + player.sendMessage(CC.translate("&cCorrect usage: /enchant ")); + return; + } + + ItemStack item = player.getItemInHand(); + + if (item == null || item.getType() == Material.AIR) { + player.sendMessage(LandCoreAPI.Language.ENCHANT_MUST_HOLD_ITEM.toString()); + return; + } + + if (!LandCoreAPI.isInteger(args[1])) { + player.sendMessage(LandCoreAPI.Language.USE_NUMBERS.toString()); + return; + } + + int level = Integer.parseInt(args[1]); + + if (level < 0) { + player.sendMessage(LandCoreAPI.Language.ENCHANT_ENCHANT_MUST_BE_POSITIVE.toString()); + return; + } + + if (level > LandCoreAPI.getMaxEnchantLevel(player)) { + player.sendMessage(LandCoreAPI.Language.ENCHANT_MAXIMUM_LEVEL_EXCEEDED.toString() + .replace("", String.valueOf(LandCoreAPI.getMaxEnchantLevel(player)))); + return; + } + + Enchantment enchantment = LandCoreAPI.getEnchantmentByName(args[0]); + + if (enchantment == null) { + player.sendMessage(LandCoreAPI.Language.ENCHANT_WRONG_ENCHANTMENT.toString()); + return; + } + + if (level == 0) { + if (!item.containsEnchantment(enchantment)) { + player.sendMessage(LandCoreAPI.Language.ENCHANT_ITEM_DOESNT_HAVE_ENCHANT.toString()); + return; + } + + item.removeEnchantment(enchantment); + player.sendMessage(LandCoreAPI.Language.ENCHANT_REMOVED.toString() + .replace("", enchantment.getName().toUpperCase().replace("_", " ") + " " + level)); + return; + } + + item.addUnsafeEnchantment(enchantment, level); + player.sendMessage(LandCoreAPI.Language.ENCHANT_ADDED.toString() + .replace("", enchantment.getName().toUpperCase().replace("_", " "))); + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/FeedCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/FeedCommand.java new file mode 100644 index 0000000..348f027 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/FeedCommand.java @@ -0,0 +1,27 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 07/02/2023 @ 18:07 + * FeedCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class FeedCommand extends PlayerCommand { + private final LandCore plugin; + + public FeedCommand(LandCore plugin) { + super("feed", Rank.ADMIN); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + player.sendMessage(CC.GOLD + CC.B + "You now have full hunger"); + player.setFoodLevel(20); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/HealCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/HealCommand.java new file mode 100644 index 0000000..9a621b8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/HealCommand.java @@ -0,0 +1,27 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 07/02/2023 @ 18:08 + * HealCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class HealCommand extends PlayerCommand { + private final LandCore plugin; + + public HealCommand(LandCore plugin) { + super("heal", Rank.ADMIN); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + player.sendMessage(CC.GOLD + CC.B + "You now have fully healed."); + player.setHealth(player.getMaxHealth()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/HelpOpCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/HelpOpCommand.java new file mode 100644 index 0000000..ee3a8b8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/HelpOpCommand.java @@ -0,0 +1,49 @@ +package me.devkevin.landcore.commands.impl; + +import com.google.common.collect.Maps; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.timer.Timer; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class HelpOpCommand extends PlayerCommand { + private final LandCore plugin; + + public HelpOpCommand(LandCore plugin) { + super("helpop"); + this.plugin = plugin; + setUsage(CC.RED + "/helpop "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(usageMessage); + return; + } + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + Timer cooldownTimer = profile.getReportCooldownTimer(); + + if (cooldownTimer.isActive()) { + player.sendMessage(CC.RED + "You can't request assistance for another " + cooldownTimer.formattedExpiration() + "."); + return; + } + + String request = StringUtil.buildString(args, 0); + + Map requestMap = Maps.newHashMap(); + requestMap.put("server", plugin.getServerName()); + requestMap.put("player", player.getName()); + requestMap.put("request", request); + + plugin.getRedisMessenger().send("help-op", requestMap); + + player.sendMessage(CC.GREEN + "Request sent: " + CC.R + request); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/IgnoreCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/IgnoreCommand.java new file mode 100644 index 0000000..72165d8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/IgnoreCommand.java @@ -0,0 +1,57 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.entity.Player; + +public class IgnoreCommand extends PlayerCommand { + private final LandCore plugin; + + public IgnoreCommand(LandCore plugin) { + super("ignore"); + this.plugin = plugin; + setAliases("unignore"); + setUsage(CC.RED + "Usage: /ignore "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(usageMessage); + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + if (target.getName().equals(player.getName())) { + player.sendMessage(CC.RED + "You can't ignore yourself!"); + return; + } + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasStaff()) { + player.sendMessage(CC.RED + "You can't ignore a staff member. If this staff member is harrassing you " + + "or engaging in other abusive manners, please report this or contact a higher staff member."); + return; + } + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (profile.hasPlayerIgnored(target.getUniqueId())) { + profile.unignore(target.getUniqueId()); + player.sendMessage(CC.GREEN + "No longer ignoring " + target.getName() + "."); + } else { + profile.ignore(target.getUniqueId()); + player.sendMessage(CC.GREEN + "Now ignoring " + target.getName() + "."); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ListCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ListCommand.java new file mode 100644 index 0000000..e190f7a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ListCommand.java @@ -0,0 +1,23 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.utils.PlayerList; +import org.bukkit.command.CommandSender; + +public class ListCommand extends BaseCommand { + public ListCommand() { + super("list"); + setAliases("online", "players", "who"); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + PlayerList onlinePlayerList = PlayerList.newList().sortedByRank(); + + sender.sendMessage(" "); + sender.sendMessage(PlayerList.ORDERED_RANKS); + sender.sendMessage(" "); + sender.sendMessage("(" + onlinePlayerList.size() + ") " + onlinePlayerList.asColoredNames()); + sender.sendMessage(" "); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/MessageCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/MessageCommand.java new file mode 100644 index 0000000..5dd4b98 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/MessageCommand.java @@ -0,0 +1,56 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.event.player.PlayerMessageEvent; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.entity.Player; + +public class MessageCommand extends PlayerCommand { + private final LandCore plugin; + + public MessageCommand(LandCore plugin) { + super("message"); + this.plugin = plugin; + setAliases("msg", "m", "whisper", "w", "tell", "t"); + setUsage(CC.RED + "Usage: /message "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 2) { + player.sendMessage(usageMessage); + return; + } + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getActiveMute() != null) { + if (profile.getActiveMute().isActive()) { + player.sendMessage(CC.RED + "You're muted for another " + profile.getActiveBan().getTimeRemaining() + "."); + } else if (profile.getActiveMute().isPermanent()) { + player.sendMessage(CC.RED + "You're permanently muted."); + } + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasPlayerIgnored(player.getUniqueId())) { + player.sendMessage(CC.RED + "That player is ignoring you!"); + return; + } + + plugin.getServer().getPluginManager().callEvent(new PlayerMessageEvent(player, target, StringUtil.buildString(args, 1))); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PCoinsCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PCoinsCommand.java new file mode 100644 index 0000000..94b2eb7 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PCoinsCommand.java @@ -0,0 +1,105 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.LandCoreAPI; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/03/2023 @ 1:43 + * P_CoinsCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class PCoinsCommand extends BaseCommand { + private final LandCore plugin; + + public PCoinsCommand(LandCore plugin) { + super("pcoin", Rank.MANAGER); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + if (args.length == 3) { + if (args[0].equalsIgnoreCase("set")) { + Player target = Bukkit.getPlayer(args[1]); + + if (target == null) { + sender.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + CoreProfile targetAccount = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (!LandCoreAPI.isInteger(args[2]) || Integer.parseInt(args[2]) < 0) { + sender.sendMessage(CC.RED + "Please use numbers."); + return; + } + + targetAccount.setP_coin(Integer.parseInt(args[2])); + + sender.sendMessage("&eYou have successfully set &6" + targetAccount.getP_coin() + "'s &ePCoins to &6" + target.getName() + "&e.\""); + return; + } + if (args[0].equalsIgnoreCase("add")) { + Player target = Bukkit.getPlayer(args[1]); + + if (target == null) { + sender.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + CoreProfile targetAccount = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (!LandCoreAPI.isInteger(args[2]) || Integer.parseInt(args[2]) <= 0) { + sender.sendMessage(CC.RED + "Please use numbers."); + return; + } + + targetAccount.setP_coin(targetAccount.getP_coin() + Integer.parseInt(args[2])); + + sender.sendMessage("&eYou have successfully added &6" + targetAccount.getP_coin() + "'s &ePCoins to &6" + target.getName() + "&e.\""); + return; + } + if (args[0].equalsIgnoreCase("remove")) { + Player target = Bukkit.getPlayer(args[1]); + + if (target == null) { + sender.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + CoreProfile targetAccount = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (!LandCoreAPI.isInteger(args[2]) || Integer.parseInt(args[2]) <= 0) { + sender.sendMessage(CC.RED + "Please use numbers."); + return; + } + + if (Integer.parseInt(args[2]) > targetAccount.getP_coin()) { + sender.sendMessage(CC.translate("&cInvalid amount.")); + return; + } + + targetAccount.setP_coin(targetAccount.getP_coin() - Integer.parseInt(args[2])); + + sender.sendMessage("&eYou have successfully removed &6" + targetAccount.getP_coin() + "'s &ePCoins to &6" + target.getName() + "&e.\""); + return; + } + } + + sender.sendMessage(" "); + sender.sendMessage(CC.translate("&e&lCoins HELP")); + sender.sendMessage(CC.translate("&e/pcoin set ")); + sender.sendMessage(CC.translate("&e/pcoin add ")); + sender.sendMessage(CC.translate("&e/pcoin remove ")); + sender.sendMessage(" "); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PingCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PingCommand.java new file mode 100644 index 0000000..656681b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PingCommand.java @@ -0,0 +1,29 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCoreAPI; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class PingCommand extends PlayerCommand { + public PingCommand() { + super("ping"); + } + + @Override + public void execute(Player player, String[] args) { + Player target = args.length < 1 || Bukkit.getPlayer(args[0]) == null ? player : Bukkit.getPlayer(args[0]); + int targetPing = target.spigot().getPing(); + + if (target == player) { + player.sendMessage(CC.PRIMARY + "Your ping is " + CC.SECONDARY + LandCoreAPI.getColorPing(targetPing) + CC.PRIMARY + " ms."); + } else { + int difference = targetPing - player.spigot().getPing(); + String name = target.getDisplayName(); + + player.sendMessage(name + CC.PRIMARY + "'s ping is " + CC.SECONDARY + targetPing + CC.PRIMARY + " ms " + + CC.ACCENT + "(" + (difference > 0 ? "+" : "") + LandCoreAPI.getColorPing(difference) + " difference)" + CC.PRIMARY + "."); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PlayTimeCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PlayTimeCommand.java new file mode 100644 index 0000000..dc9fdc6 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/PlayTimeCommand.java @@ -0,0 +1,43 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.utils.message.CC; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.bukkit.Statistic; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/01/2023 @ 1:13 + * PlayTimeCommand / land.pvp.core.commands.impl / LandCore + */ +public class PlayTimeCommand extends PlayerCommand { + private final LandCore plugin; + + public PlayTimeCommand(LandCore plugin) { + super("playtime"); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + if (args.length == 0) { + long time = player.getStatistic(Statistic.PLAY_ONE_TICK); + + player.sendMessage(CC.translate("&eYour playtime is &6" + DurationFormatUtils.formatDurationWords(time * 50L, true, true) + " &eon this server.")); + } else { + Player target = this.plugin.getServer().getPlayer(args[0]); + + if (target == null || !target.isOnline()) { + assert target != null; + player.sendMessage(CC.RED + "No player matching " + CC.YELLOW + target.getName() + CC.RED + " is connected to this server"); + return; + } + + long time = target.getStatistic(Statistic.PLAY_ONE_TICK); + + player.sendMessage(CC.translate(plugin.getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + "'s &eplaytime is &6" + DurationFormatUtils.formatDurationWords(time * 50L, true, true) + " &eon this server.")); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ReplyCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ReplyCommand.java new file mode 100644 index 0000000..4ac6068 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ReplyCommand.java @@ -0,0 +1,55 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.event.player.PlayerMessageEvent; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +public class ReplyCommand extends PlayerCommand { + private final LandCore plugin; + + public ReplyCommand(LandCore plugin) { + super("reply"); + this.plugin = plugin; + setAliases("r"); + setUsage(CC.RED + "Usage: /reply "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(usageMessage); + return; + } + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getActiveMute() != null) { + if (profile.getActiveMute().isActive()) { + player.sendMessage(CC.RED + "You're muted for another " + profile.getActiveBan().getTimeRemaining() + "."); + } else if (profile.getActiveMute().isPermanent()) { + player.sendMessage(CC.RED + "You're permanently muted."); + } + return; + } + + Player target = plugin.getServer().getPlayer(profile.getConverser()); + + if (target == null) { + player.sendMessage(CC.RED + "You are not in a conversation."); + return; + } + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasPlayerIgnored(player.getUniqueId())) { + player.sendMessage(CC.RED + "That player is ignoring you!"); + return; + } + + plugin.getServer().getPluginManager().callEvent(new PlayerMessageEvent(player, target, StringUtil.buildString(args, 0))); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ReportCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ReportCommand.java new file mode 100644 index 0000000..71eaa3c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/ReportCommand.java @@ -0,0 +1,58 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.inventory.menu.impl.ReportMenu; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.entity.Player; + +public class ReportCommand extends PlayerCommand { + private final LandCore plugin; + + public ReportCommand(LandCore plugin) { + super("report"); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /report "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length == 0) { + player.sendMessage(usageMessage); + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + if (player == target) { + player.sendMessage(CC.RED + "You can't report yourself!"); + return; + } + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasStaff()) { + player.sendMessage(CC.RED + "You can't report a staff member. If this staff member is harassing you or" + + " engaging in other abusive manners, please report this or contact a higher staff member."); + return; + } + + if (args.length == 1 || args.length == 2) { + if (target.getName() != null || targetProfile.getName() != null) { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + profile.setReportingPlayerName(target.getName()); + plugin.getMenuManager().getMenu(ReportMenu.class).open(player); + } else { + player.sendMessage(CC.RED + "Error: That player does not exist."); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/StoreCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/StoreCommand.java new file mode 100644 index 0000000..c8bb166 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/StoreCommand.java @@ -0,0 +1,25 @@ +package me.devkevin.landcore.commands.impl; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/03/2023 @ 20:43 + * StoreCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class StoreCommand extends PlayerCommand { + private final LandCore plugin; + + public StoreCommand(LandCore plugin) { + super("store"); + this.plugin = plugin; + setAliases("pstore"); + } + + @Override + public void execute(Player player, String[] args) { + player.openInventory(this.plugin.getStorePCoinMenu().menu(player).getCurrentPage()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/TeleportPositionCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/TeleportPositionCommand.java new file mode 100644 index 0000000..615e8f3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/TeleportPositionCommand.java @@ -0,0 +1,44 @@ +package me.devkevin.landcore.commands.impl; + +import com.google.common.primitives.Ints; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 07/02/2023 @ 18:05 + * TeleportPositionCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class TeleportPositionCommand extends PlayerCommand { + private final LandCore plugin; + + public TeleportPositionCommand(LandCore plugin) { + super("tppos", Rank.DEVELOPER); + this.plugin = plugin; + setAliases("teleportposition"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 3) { + player.sendMessage(CC.RED + "Usage: /tppos "); + return; + } + + Integer x = Ints.tryParse(args[0]); + Integer y = Ints.tryParse(args[1]); + Integer z = Ints.tryParse(args[2]); + + if (x == null || y == null || z == null) { + player.sendMessage(CC.RED + "Location not found."); + return; + } + + player.sendMessage(CC.GRAY + "Teleporting..."); + player.teleport(new Location(player.getWorld(), (double) x, (double) y, (double) z)); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/AltsCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/AltsCommand.java new file mode 100644 index 0000000..1bc4294 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/AltsCommand.java @@ -0,0 +1,60 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.entity.Player; +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 17:25 + * AltsCommand / me.devkevin.landcore.commands.impl.staff / LandCore + */ +public class AltsCommand extends PlayerCommand { + private final LandCore plugin; + + public AltsCommand(LandCore plugin) { + super("alts", Rank.TRIAL_MOD); + this.plugin = plugin; + setAliases("dupeip"); + setUsage(CC.RED + "Usage: /alts "); + } + + @Override + public void execute(Player player, String[] args) { + Player target = plugin.getServer().getPlayer(args[0]); + CoreProfile coreProfile = this.plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (target == null || coreProfile == null) { + player.sendMessage(Messages.PLAYER_NOT_FOUND); + return; + } + + List alts = new ArrayList<>(); + + for (UUID altUUID : coreProfile.getKnownAlts()) { + CoreProfile altProfile = this.plugin.getProfileManager().getProfile(altUUID); + + if (altProfile != null) { + alts.add(altProfile); + } + } + + if (alts.isEmpty()) { + player.sendMessage(CC.RED + "This player has no known alt accounts."); + } else { + StringBuilder builder = new StringBuilder(); + + for (CoreProfile altProfile : alts) { + builder.append(altProfile.getName()); + builder.append(", "); + } + + player.sendMessage(CC.GOLD + "Alts: " + CC.R + builder); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/BroadcastCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/BroadcastCommand.java new file mode 100644 index 0000000..d1b9edd --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/BroadcastCommand.java @@ -0,0 +1,37 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +public class BroadcastCommand extends BaseCommand { + private final LandCore plugin; + + public BroadcastCommand(LandCore plugin) { + super("broadcast", Rank.ADMIN); + this.plugin = plugin; + setAliases("bc"); + setUsage(CC.RED + "Usage: /broadcast [-god]"); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + if (args.length == 0) { + sender.sendMessage(usageMessage); + return; + } + + String message = CC.SECONDARY + "[Alert] " + CC.PRIMARY + + ChatColor.translateAlternateColorCodes('&', StringUtil.buildString(args, 0)).trim(); + + if (message.endsWith(" -god")) { + message = message.substring(12, message.length() - 5).trim(); + } + + plugin.getServer().broadcastMessage(message); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/BuildServerCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/BuildServerCommand.java new file mode 100644 index 0000000..ccc239e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/BuildServerCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.LandCoreAPI; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.rank.Rank; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 07/02/2023 @ 17:46 + * BuilServerCommand / me.devkevin.landcore.commands.impl / LandCore + */ +public class BuildServerCommand extends PlayerCommand { + private final LandCore plugin; + + public BuildServerCommand(LandCore plugin) { + super("buildserver", Rank.BUILDER); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + LandCoreAPI.sendToServer(player, "build"); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/FreezeCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/FreezeCommand.java new file mode 100644 index 0000000..be84df7 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/FreezeCommand.java @@ -0,0 +1,68 @@ +package me.devkevin.landcore.commands.impl.staff; + +import com.google.common.collect.Maps; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.event.player.PlayerFreezeEvent; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Map; + +public class FreezeCommand extends BaseCommand { + private final LandCore plugin; + + public FreezeCommand(LandCore plugin) { + super("freeze", Rank.SENIOR_MOD); + this.plugin = plugin; + setAliases("screenshare", "ss"); + setUsage("/freeze "); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + if (args.length < 1) { + sender.sendMessage(CC.RED + getUsage()); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + + if (target != null) { + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasStaff()) { + sender.sendMessage(CC.RED + "If you believe a staff member is cheating, please alert higher staff."); + return; + } + + String server = plugin.getServerName(); + String targetName = target.getName(); + String senderName = sender.getName(); + + Map map = Maps.newHashMap(); + map.put("server", server); + map.put("frozen", targetName); + map.put("sender", senderName); + + if (targetProfile.freeze(sender)) { + map.put("isFrozen", true); + plugin.getRedisMessenger().send("freeze-listener", map); + return; + } + map.put("isFrozen", false); + plugin.getRedisMessenger().send("freeze-listener", map); + return; + } + + PlayerFreezeEvent event = new PlayerFreezeEvent(target); + this.plugin.getServer().getPluginManager().callEvent(event); + + sender.sendMessage(CC.RED + "That player is offline or does not exist."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/GameModeCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/GameModeCommand.java new file mode 100644 index 0000000..5256243 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/GameModeCommand.java @@ -0,0 +1,47 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.GameMode; +import org.bukkit.entity.Player; + +public class GameModeCommand extends PlayerCommand { + public GameModeCommand() { + super("gamemode", Rank.SENIOR_MOD); + setAliases("gm"); + setUsage(CC.RED + "Usage: /gamemode "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(usageMessage); + return; + } + + switch (args[0].toLowerCase()) { + case "1": + case "creative": + case "c": + player.setGameMode(GameMode.CREATIVE); + player.sendMessage(CC.GREEN + "Your game mode was set to creative."); + break; + case "0": + case "survival": + case "s": + player.setGameMode(GameMode.SURVIVAL); + player.sendMessage(CC.GREEN + "Your game mode was set to survival."); + break; + case "2": + case "adventure": + case "a": + player.setGameMode(GameMode.ADVENTURE); + player.sendMessage(CC.GREEN + "Your game mode was set to adventure."); + break; + default: + player.sendMessage(usageMessage); + break; + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/MisplaceCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/MisplaceCommand.java new file mode 100644 index 0000000..d717d1d --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/MisplaceCommand.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 17:57 + * MisplaceCommand / me.devkevin.landcore.commands.impl.staff / LandCore + */ +public class MisplaceCommand extends BaseCommand { + private final LandCore plugin; + + public MisplaceCommand(LandCore plugin) { + super("xp", Rank.MANAGER); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player target = this.plugin.getServer().getPlayer(args[0]); + + CoreProfile coreProfile = this.plugin.getProfileManager().getProfile(target.getUniqueId()); + try { + double d = Double.parseDouble(args[1]); + if (d > 0.25) { + sender.sendMessage(CC.RED + "Warning! " + d + " is over the recommended amount. The recommended amount is 0.25."); + } + coreProfile.setMisplace(d); + sender.sendMessage(CC.GREEN + "Misplace set to " + d + "."); + } catch (Exception ex) { + sender.sendMessage(CC.RED + "Invalid amount."); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/MuteChatCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/MuteChatCommand.java new file mode 100644 index 0000000..764b88c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/MuteChatCommand.java @@ -0,0 +1,25 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +public class MuteChatCommand extends PlayerCommand { + private final LandCore plugin; + + public MuteChatCommand(LandCore plugin) { + super("mutechat", Rank.TRIAL_MOD); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + boolean globalChatMuted = !plugin.getServerSettings().isGlobalChatMuted(); + + plugin.getServerSettings().setGlobalChatMuted(globalChatMuted); + plugin.getServer().broadcastMessage(globalChatMuted ? CC.RED + "Global chat has been muted by " + player.getName() + "." + : CC.GREEN + "Global chat has been enabled by " + plugin.getProfileManager().getProfile(player.getUniqueId()).getRank().getColor() + player.getName() + "."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/ShutdownCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/ShutdownCommand.java new file mode 100644 index 0000000..00b86d3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/ShutdownCommand.java @@ -0,0 +1,63 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.event.server.ServerShutdownCancelEvent; +import me.devkevin.landcore.event.server.ServerShutdownScheduleEvent; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.task.ShutdownTask; +import me.devkevin.landcore.utils.NumberUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; + +public class ShutdownCommand extends BaseCommand { + private final LandCore plugin; + + public ShutdownCommand(LandCore plugin) { + super("shutdown", Rank.ADMIN); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /shutdown "); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + if (args.length < 1) { + sender.sendMessage(usageMessage); + return; + } + + String arg = args[0]; + + if (arg.equals("cancel")) { + ShutdownTask task = plugin.getServerSettings().getShutdownTask(); + + if (task == null) { + sender.sendMessage(CC.RED + "There is no shutdown in progress."); + } else { + plugin.getServer().getPluginManager().callEvent(new ServerShutdownCancelEvent()); + + task.cancel(); + plugin.getServerSettings().setShutdownTask(null); + plugin.getServer().broadcastMessage(CC.GREEN + "The shutdown in progress has been cancelled by " + sender.getName() + "."); + } + return; + } + + Integer seconds = NumberUtil.getInteger(arg); + + if (seconds == null) { + sender.sendMessage(usageMessage); + } else { + if (seconds >= 5 && seconds <= 300) { + plugin.getServer().getPluginManager().callEvent(new ServerShutdownScheduleEvent()); + + ShutdownTask task = new ShutdownTask(seconds); + + plugin.getServerSettings().setShutdownTask(task); + task.runTaskTimer(plugin, 0L, 20L); + } else { + sender.sendMessage(CC.RED + "Please enter a time between 5 and 300 seconds."); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/SlowChatCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/SlowChatCommand.java new file mode 100644 index 0000000..ea857d4 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/SlowChatCommand.java @@ -0,0 +1,67 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; + +public class SlowChatCommand extends BaseCommand { + private final LandCore plugin; + + public SlowChatCommand(LandCore plugin) { + super("slowchat", Rank.TRIAL_MOD); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /slowchat "); + } + + private static Integer getInt(String arg) { + try { + int i = Integer.parseInt(arg); + + if (i < 4 || i > 60) { + return null; + } + + return i; + } catch (NumberFormatException e) { + return null; + } + } + + @Override + protected void execute(CommandSender sender, String[] args) { + if (args.length < 1) { + sender.sendMessage(usageMessage); + return; + } + + String arg = args[0]; + + switch (arg.toLowerCase()) { + case "off": + case "toggle": + case "disable": + int slowChatTime = plugin.getServerSettings().getSlowChatTime(); + + if (slowChatTime == -1) { + sender.sendMessage(CC.RED + "Slow chat is already disabled!"); + } else { + plugin.getServerSettings().setSlowChatTime(-1); + plugin.getServer().broadcastMessage(CC.RED + "Slow chat has been disabled by " + sender.getName() + "."); + } + break; + default: + Integer time = getInt(arg); + + if (time == null) { + sender.sendMessage(CC.RED + "You must enter a valid time between 4 and 60 seconds."); + } else { + plugin.getServerSettings().setSlowChatTime(time); + plugin.getServer().broadcastMessage(CC.YELLOW + "Slow chat has been enabled and set to " + time + + " seconds by " + sender.getName() + "."); + } + break; + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/StaffChatCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/StaffChatCommand.java new file mode 100644 index 0000000..9839f5a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/StaffChatCommand.java @@ -0,0 +1,36 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +public class StaffChatCommand extends PlayerCommand { + private final LandCore plugin; + + public StaffChatCommand(LandCore plugin) { + super("staffchat", Rank.TRIAL_MOD); + this.plugin = plugin; + setAliases("sc"); + } + + @Override + public void execute(Player player, String[] args) { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (args.length == 0) { + boolean inStaffChat = !profile.isInStaffChat(); + + profile.setInStaffChat(inStaffChat); + + player.sendMessage(inStaffChat ? CC.GREEN + "You are now in staff chat." : CC.RED + "You are no longer in staff chat."); + } else { + String message = StringUtil.buildString(args, 0); + + plugin.getStaffManager().messageStaff(profile.getChatFormat(), message); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/TeleportCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/TeleportCommand.java new file mode 100644 index 0000000..de08624 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/TeleportCommand.java @@ -0,0 +1,68 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.entity.Player; + +public class TeleportCommand extends PlayerCommand { + private final LandCore plugin; + + public TeleportCommand(LandCore plugin) { + super("tp", Rank.TRIAL_MOD); + this.plugin = plugin; + setAliases("teleport"); + setUsage(CC.RED + "Usage: /teleport [player]"); + } + + private static boolean isOffline(Player checker, Player target) { + if (target == null) { + checker.sendMessage(Messages.PLAYER_NOT_FOUND); + return true; + } + + return false; + } + + private void teleport(Player to, Player from) { + to.teleport(from); + to.sendMessage(CC.GREEN + "You have been teleported to " + from.getName() + "."); + + CoreProfile fromProfile = plugin.getProfileManager().getProfile(from.getUniqueId()); + + if (fromProfile.hasStaff()) { + from.sendMessage(CC.GREEN + to.getName() + " has been teleported to you."); + } + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(usageMessage); + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + if (isOffline(player, target)) { + return; + } + + if (args.length < 2) { + teleport(player, target); + } else { + Player target2 = plugin.getServer().getPlayer(args[1]); + + if (isOffline(player, target2)) { + return; + } + + teleport(target, target2); + + player.sendMessage(CC.GREEN + "Teleported " + target.getName() + " to " + target2.getName() + "."); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/VanishCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/VanishCommand.java new file mode 100644 index 0000000..3008226 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/VanishCommand.java @@ -0,0 +1,33 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class VanishCommand extends BaseCommand { + private final LandCore plugin; + + public VanishCommand(LandCore plugin) { + super("vanish", Rank.TRIAL_MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + boolean vanished = !profile.isVanished(); + + profile.setVanished(vanished); + + for (Player online : plugin.getServer().getOnlinePlayers()) { + plugin.getStaffManager().hideVanishedStaffFromPlayer(online); + } + + player.sendMessage(vanished ? CC.GREEN + "Poof, you vanished." : CC.RED + "You're visible again."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/WhitelistCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/WhitelistCommand.java new file mode 100644 index 0000000..676d7c0 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/WhitelistCommand.java @@ -0,0 +1,59 @@ +package me.devkevin.landcore.commands.impl.staff; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.server.ServerSettings; +import me.devkevin.landcore.server.WhitelistMode; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Server; +import org.bukkit.command.CommandSender; + +public class WhitelistCommand extends BaseCommand { + private final LandCore plugin; + + public WhitelistCommand(LandCore plugin) { + super("whitelist", Rank.ADMIN); + this.plugin = plugin; + setAliases("wl"); + setUsage(CC.RED + "Usage: /whitelist "); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + if (args.length < 1) { + sender.sendMessage(usageMessage); + return; + } + + ServerSettings settings = plugin.getServerSettings(); + + switch (args[0].toLowerCase()) { + case "none": + case "off": + settings.setServerWhitelistMode(WhitelistMode.NONE); + break; + case "ranks": + case "donors": + settings.setServerWhitelistMode(WhitelistMode.RANKS); + break; + case "staff": + case "on": + settings.setServerWhitelistMode(WhitelistMode.STAFF); + break; + default: + sender.sendMessage(CC.RED + "That's not a valid whitelist mode!"); + return; + } + + WhitelistMode whitelistMode = settings.getServerWhitelistMode(); + Server server = plugin.getServer(); + + if (whitelistMode == WhitelistMode.NONE) { + server.broadcastMessage(CC.GREEN + "The server is no longer whitelisted!"); + } else { + whitelistMode.activate(); + server.broadcastMessage(CC.RED + "The server is now whitelisted (Mode: " + whitelistMode + ")."); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/BanCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/BanCommand.java new file mode 100644 index 0000000..16eb68b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/BanCommand.java @@ -0,0 +1,79 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.utils.Duration; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import java.util.Objects; +import java.util.UUID; + +public class BanCommand extends BaseCommand { + private final LandCore plugin; + + public BanCommand(LandCore plugin) { + super("ban", Rank.MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player target = Bukkit.getPlayer(args[0]); + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (args.length < 3) { + sender.sendMessage(CC.RED + "Usage: /ban " + CC.GRAY + "[-s]" + CC.RED + "."); + } + + if (profile == null) { + sender.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + if (Objects.requireNonNull(profile).getActiveBan() != null) { + sender.sendMessage(CC.RED + "That player is already banned."); + return; + } + + long duration = Duration.fromString(args[1]).getValue(); + boolean silent = args[args.length - 1].equalsIgnoreCase("-s"); + + if (duration == -1) { + sender.sendMessage(CC.RED + "That duration is not valid."); + sender.sendMessage(CC.RED + "Example: [perm/1y1m1w1d]"); + return; + } + + String staffName = sender instanceof Player ? plugin.getProfileManager().getProfile(((Player) sender).getUniqueId()).getGrant().getRank().getColor() + sender.getName() : CC.D_RED + "Console"; + + Punishment punishment = new Punishment(UUID.randomUUID(), PunishmentType.BAN, System.currentTimeMillis(), + args[1], duration); + + if (sender instanceof Player) { + punishment.setAddedBy(((Player) sender).getUniqueId()); + } + + profile.getPunishments().add(punishment); + profile.save(true); + + punishment.broadcast(staffName, target, silent); + + Player player = profile.getPlayer(); + + if (player != null) { + new BukkitRunnable() { + @Override + public void run() { + player.kickPlayer(punishment.getKickMessage()); + } + }.runTask(LandCore.getInstance()); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/CheckCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/CheckCommand.java new file mode 100644 index 0000000..7bf0022 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/CheckCommand.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.menu.PunishmentsMenu; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 15:26 + * CheckCommand / me.devkevin.landcore.commands.impl.staff.punish / LandCore + */ +public class CheckCommand extends PlayerCommand { + private final LandCore plugin; + + public CheckCommand(LandCore plugin) { + super("check", Rank.MOD); + this.plugin = plugin; + setAliases("c"); + } + + + @Override + public void execute(Player player, String[] args) { + OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]); + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (profile == null) { + player.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + new PunishmentsMenu(profile).openMenu(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/KickCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/KickCommand.java new file mode 100644 index 0000000..bd8d106 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/KickCommand.java @@ -0,0 +1,69 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.utils.Duration; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Objects; +import java.util.UUID; + +public class KickCommand extends BaseCommand { + private final LandCore plugin; + + public KickCommand(LandCore plugin) { + super("kick", Rank.TRIAL_MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player target = Bukkit.getPlayer(args[0]); + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (args.length < 2) { + sender.sendMessage(CC.RED + "Usage: /kick " + CC.GRAY + "[-s]" + CC.RED + "."); + } + + if (profile == null) { + sender.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + String staffName = sender instanceof Player ? plugin.getProfileManager().getProfile(((Player) sender).getUniqueId()).getGrant().getRank().getColor() + sender.getName() : CC.D_RED + "Console"; + + + Punishment punishment = new Punishment(target.getUniqueId(), PunishmentType.KICK, System.currentTimeMillis(), + args[1], -1); + + if (sender instanceof Player) { + punishment.setAddedBy(((Player) sender).getUniqueId()); + } + + Objects.requireNonNull(profile).getPunishments().add(punishment); + profile.save(true); + + punishment.broadcast(staffName, target, true); + + Player player = profile.getPlayer(); + + if (player != null) { + new BukkitRunnable() { + @Override + public void run() { + player.kickPlayer(punishment.getKickMessage()); + } + }.runTask(LandCore.getInstance()); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/MuteCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/MuteCommand.java new file mode 100644 index 0000000..06622fa --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/MuteCommand.java @@ -0,0 +1,81 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.utils.Duration; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import java.util.Objects; +import java.util.UUID; + +public class MuteCommand extends BaseCommand { + private final LandCore plugin; + + public MuteCommand(LandCore plugin) { + super("mute", Rank.TRIAL_MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player target = Bukkit.getPlayer(args[0]); + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + + if (args.length < 3) { + sender.sendMessage(CC.RED + "Usage: /mute " + CC.GRAY + "[-s]" + CC.RED + "."); + } + + if (profile == null) { + sender.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + if (Objects.requireNonNull(profile).getActiveMute() != null) { + sender.sendMessage(CC.RED + "That player is already muted."); + return; + } + + long duration = Duration.fromString(args[1]).getValue(); + boolean silent = args[args.length - 1].equalsIgnoreCase("-s"); + + if (duration == -1) { + sender.sendMessage(CC.RED + "That duration is not valid."); + sender.sendMessage(CC.RED + "Example: [perm/1y1m1w1d]"); + return; + } + + String staffName = sender instanceof Player ? plugin.getProfileManager().getProfile(((Player) sender).getUniqueId()).getGrant().getRank().getColor() + sender.getName() : CC.D_RED + "Console"; + + Punishment punishment = new Punishment(target.getUniqueId(), PunishmentType.MUTE, System.currentTimeMillis(), + args[1], duration); + + if (sender instanceof Player) { + punishment.setAddedBy(((Player) sender).getUniqueId()); + } + + profile.getPunishments().add(punishment); + profile.save(true); + + Player player = profile.getPlayer(); + + + if (player != null) { + String senderName = sender instanceof Player ? plugin.getProfileManager().getProfiles().get(((Player) sender).getUniqueId()).getGrant().getRank().getColor() : CC.D_RED + "Console"; + player.sendMessage(CC.RED + "You have been muted by " + senderName + CC.RED + " for: " + CC.YELLOW + args[1]); + + if (!punishment.isPermanent()) { + player.sendMessage(CC.RED + "This mute will expire in " + CC.YELLOW + punishment.getTimeRemaining()); + } + } + + punishment.broadcast(staffName, target, silent); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/UnbanCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/UnbanCommand.java new file mode 100644 index 0000000..4969c1b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/UnbanCommand.java @@ -0,0 +1,58 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class UnbanCommand extends BaseCommand { + private final LandCore plugin; + + public UnbanCommand(LandCore plugin) { + super("unban", Rank.MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]); + + if (args.length < 2) { + sender.sendMessage(CC.RED + "Usage: /unban " + CC.GRAY + "[-s]" + CC.RED + "."); + } + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (profile == null) { + sender.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + if ((profile != null ? profile.getActiveBan() : null) == null) { + sender.sendMessage(CC.RED + "That player is not banned."); + return; + } + + boolean silent = args[args.length - 1].equalsIgnoreCase("-s"); + + String staffName = sender instanceof Player ? plugin.getProfileManager().getProfile(((Player) sender).getUniqueId()).getGrant().getRank().getColor() + sender.getName() : CC.D_RED + "Console"; + + Punishment punishment = profile.getActiveBan(); + punishment.setPardonedAt(System.currentTimeMillis()); + punishment.setPardonedReason(args[1]); + punishment.setPardoned(true); + + if (sender instanceof Player) { + punishment.setPardonedBy(((Player) sender).getUniqueId()); + } + + profile.save(true); + + punishment.broadcast(staffName, target.getPlayer(), silent); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/UnmuteCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/UnmuteCommand.java new file mode 100644 index 0000000..e669bab --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/UnmuteCommand.java @@ -0,0 +1,57 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class UnmuteCommand extends BaseCommand { + private final LandCore plugin; + + public UnmuteCommand(LandCore plugin) { + super("unmute", Rank.MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player target = Bukkit.getPlayer(args[0]); + + if (args.length < 2) { + sender.sendMessage(CC.RED + "Usage: /unmute " + CC.GRAY + "[-s]" + CC.RED + "."); + } + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (profile == null) { + sender.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + if ((profile != null ? profile.getActiveMute() : null) == null) { + sender.sendMessage(CC.RED + "That player is not muted."); + return; + } + + boolean silent = args[args.length - 1].equalsIgnoreCase("-s"); + + String staffName = sender instanceof Player ? plugin.getProfileManager().getProfile(((Player) sender).getUniqueId()).getGrant().getRank().getColor() + sender.getName() : CC.D_RED + "Console"; + + Punishment punishment = profile.getActiveMute(); + punishment.setPardonedAt(System.currentTimeMillis()); + punishment.setPardonedReason(args[1]); + punishment.setPardoned(true); + + if (sender instanceof Player) { + punishment.setPardonedBy(((Player) sender).getUniqueId()); + } + + profile.save(true); + + punishment.broadcast(staffName, target, silent); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/WarnCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/WarnCommand.java new file mode 100644 index 0000000..b03ef93 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/staff/punish/WarnCommand.java @@ -0,0 +1,67 @@ +package me.devkevin.landcore.commands.impl.staff.punish; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.Objects; +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 15:52 + * WarnCommand / me.devkevin.landcore.commands.impl.staff.punish / LandCore + */ +public class WarnCommand extends BaseCommand { + private final LandCore plugin; + + public WarnCommand(LandCore plugin) { + super("warn", Rank.TRIAL_MOD); + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player target = Bukkit.getPlayer(args[0]); + + if (args.length < 2) { + sender.sendMessage(CC.RED + "Usage: /warn " + CC.GRAY + "[-s]" + CC.RED + "."); + } + + CoreProfile profile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (profile == null) { + sender.sendMessage(CC.RED + "Could no load " + target.getName() + " database. Contact with the developer."); + } + + boolean silent = args[args.length - 1].equalsIgnoreCase("-s"); + + String staffName = sender instanceof Player ? plugin.getProfileManager().getProfile(((Player) sender).getUniqueId()).getGrant().getRank().getColor() + sender.getName() : CC.D_RED + "Console"; + + Punishment punishment = new Punishment(target.getUniqueId(), PunishmentType.WARN, System.currentTimeMillis(), + args[1], -1); + + if (sender instanceof Player) { + punishment.setAddedBy(((Player) sender).getUniqueId()); + } + + Objects.requireNonNull(profile).getPunishments().add(punishment); + profile.save(true); + + Player player = profile.getPlayer(); + + if (player != null) { + String senderName = sender instanceof Player ? plugin.getProfileManager().getProfiles().get(((Player) sender).getUniqueId()).getGrant().getRank().getColor() : CC.D_RED + "Console"; + player.sendMessage(CC.RED + "You have been warned by " + senderName + CC.RED + " for: " + CC.YELLOW + args[1]); + } + + punishment.broadcast(staffName, target, silent); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleGlobalChat.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleGlobalChat.java new file mode 100644 index 0000000..e3228df --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleGlobalChat.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.commands.impl.toggle; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +public class ToggleGlobalChat extends PlayerCommand { + private final LandCore plugin; + + public ToggleGlobalChat(LandCore plugin) { + super("toggleglobalchat"); + this.plugin = plugin; + setAliases("togglechat", "tgc"); + } + + @Override + public void execute(Player player, String[] args) { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + boolean enabled = !profile.isGlobalChatEnabled(); + + profile.setGlobalChatEnabled(enabled); + player.sendMessage(enabled ? CC.GREEN + "Global chat enabled." : CC.RED + "Global chat disabled."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleMessagesCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleMessagesCommand.java new file mode 100644 index 0000000..58a870b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleMessagesCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.commands.impl.toggle; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +public class ToggleMessagesCommand extends PlayerCommand { + private final LandCore plugin; + + public ToggleMessagesCommand(LandCore plugin) { + super("togglemessages"); + this.plugin = plugin; + setAliases("tpm"); + } + + @Override + public void execute(Player player, String[] args) { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + boolean messaging = !profile.isMessaging(); + + profile.setMessaging(messaging); + player.sendMessage(messaging ? CC.GREEN + "Messages enabled." : CC.RED + "Messages disabled."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleSoundsCommand.java b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleSoundsCommand.java new file mode 100644 index 0000000..fce2f16 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/commands/impl/toggle/ToggleSoundsCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.commands.impl.toggle; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +public class ToggleSoundsCommand extends PlayerCommand { + private final LandCore plugin; + + public ToggleSoundsCommand(LandCore plugin) { + super("togglesounds"); + this.plugin = plugin; + setAliases("sounds", "ts"); + } + + @Override + public void execute(Player player, String[] args) { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + boolean playingSounds = !profile.isPlayingSounds(); + + profile.setPlayingSounds(playingSounds); + player.sendMessage(playingSounds ? CC.GREEN + "Sounds enabled." : CC.RED + "Sounds disabled."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/disguise/commands/DisguiseCommand.java b/LandCore/src/main/java/me/devkevin/landcore/disguise/commands/DisguiseCommand.java new file mode 100644 index 0000000..9838e85 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/disguise/commands/DisguiseCommand.java @@ -0,0 +1,67 @@ +package me.devkevin.landcore.disguise.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.disguise.manager.DisguiseManager; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.haoshoku.nick.api.NickAPI; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 18:58 + * DisguiseCommand / me.devkevin.landcore.disguise / LandCore + */ +public class DisguiseCommand extends BaseCommand { + private final LandCore plugin; + + public DisguiseCommand(LandCore plugin) { + super("disguise", Rank.TRIAL_MOD); // temp rank for test + this.plugin = plugin; + } + + @Override + protected void execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + + if ("random".equals(args[0])) { + String disguiseName; + String disguiseSkin = DisguiseManager.generateSkin().split(":")[0]; + + if (DisguiseManager.nickData.get(player) != null) { + disguiseName = DisguiseManager.nickData.get(player); + } else { + disguiseName = DisguiseManager.generate(); + } + + plugin.getDisguiseManager().setPlayerDisguise(player, disguiseName, disguiseSkin); + + // first disguise a player and then after 2 sec open the rank menu + plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + // check is player in nicked yet so we won't get errors + if (NickAPI.isNicked(player)) { + player.openInventory(this.plugin.getDisguiseMenu().getRankMenu().getCurrentPage()); + } + }, 20L); + + + } else { + if (NickAPI.nickExists(args[0])) { + player.sendMessage(CC.RED + "That name is already used."); + return; + } + + plugin.getDisguiseManager().setPlayerDisguise(player, args[0], args[1]); + + // first disguise a player and then after 2 sec open the rank menu + plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + // check is player in nicked yet so we won't get errors + if (NickAPI.isNicked(player)) { + player.openInventory(this.plugin.getDisguiseMenu().getRankMenu().getCurrentPage()); + } + }, 20L); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/disguise/commands/UndisguiseCommand.java b/LandCore/src/main/java/me/devkevin/landcore/disguise/commands/UndisguiseCommand.java new file mode 100644 index 0000000..031f5e0 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/disguise/commands/UndisguiseCommand.java @@ -0,0 +1,52 @@ +package me.devkevin.landcore.disguise.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.managers.PlayerManager; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import xyz.haoshoku.nick.NickPlugin; +import xyz.haoshoku.nick.api.NickAPI; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/02/2023 @ 0:23 + * UndisguiseCommand / me.devkevin.landcore.disguise / LandCore + */ +public class UndisguiseCommand extends BaseCommand { + private final LandCore plugin; + + public UndisguiseCommand(LandCore plugin) { + super("undisguise", Rank.TRIAL_MOD); // temp rank for test + this.plugin = plugin; + } + + + @Override + public void execute(CommandSender sender, String[] args) { + Player player = (Player) sender; + + CoreProfile coreProfile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (NickAPI.isNicked(player)) { + NickAPI.resetNick(player); + NickAPI.resetSkin(player); + NickAPI.resetGameProfileName(player); + NickAPI.resetUniqueId(player); + NickAPI.refreshPlayer(player); + NickAPI.refreshPlayerSync(player); + + coreProfile.setDisguiseRank(null); // when player un disguise we reset the rank + + player.setDisplayName(player.getName()); + player.setPlayerListName(player.getName()); + + player.sendMessage(CC.SECONDARY + "You've been " + CC.RED + "undisguised" + CC.SECONDARY + " and reset to your default skin."); + } else { + player.sendMessage(CC.RED + "You aren't currently disguised!"); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/disguise/manager/DisguiseManager.java b/LandCore/src/main/java/me/devkevin/landcore/disguise/manager/DisguiseManager.java new file mode 100644 index 0000000..2bdda0a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/disguise/manager/DisguiseManager.java @@ -0,0 +1,265 @@ +package me.devkevin.landcore.disguise.manager; + +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.nametag.impl.InternalNametag; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; +import net.minecraft.server.v1_8_R3.PacketPlayOutRespawn; +import net.minecraft.server.v1_8_R3.WorldSettings; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import xyz.haoshoku.nick.NickPlugin; +import xyz.haoshoku.nick.api.NickAPI; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 18:53 + * DisguiseManager / me.devkevin.landcore.disguise / LandCore + */ +@Getter +public class DisguiseManager { + public static HashMap nickData = new HashMap<>(); + + private static final List skinNames = Arrays.asList("_rsu:Killer", "E_Girl:E-girl", "MHF_Sheep:Sheep Man", "BackupDancer:L", "Arro:Arabian", "bennyknight:Badman", "MHF_Herobrine:Herobrine", + "MHF_Villager:Villager", "CocoDeMedellin:Black Goku", "SheAGoldDigger:Blue Goku", "MHF_Enderman:Enderman", "Marcel:Marcel", "Zwergoor:Emoji", + "HikakinGames:Youtuber", "loudoggydog3010:Juice Wrld", "Reinstallation:Rambo Chicken", "SolluxCaptor:Nezuko", "DevKevin:DevKevin", "Brandy:Brandy", + "Grief:Grief", "Nimble:Nimble", "fangirl:fangirl", "Pokemon:Pokemon", "icy:icy", "Magista80:Magista80"); + + + private static final List shortWords = Arrays.asList("About", "Active", "Admit", "Advise", "Again", "After", "Agent", "Alive", "Alone", "Beach", "Basket", "Basic", "Bath", "Battle", + "Bean", "Beat", "Bed", "Become", "Begin", "Before", "Beer", "Behind", "Blade", "Black", "Blue", "Bomb", "Brush", "Build", "Bunch", "Button", "Biz", "Busy", + "Box", "Boy", "Break", "Best", "Better", "Cake", "Camera", "Campus", "Cap", "Card", "Care", "Case", "Catch", "Center", "Chain", "Chair", "Chara", "Charge", + "Chase", "Cheap", "Cheese", "Check", "Close", "Choose", "Christ", "Circle", "Dad", "Dance", "Dark", "Data", "Dead", "Defend", "Desert", "Desk", "Device", + "Detect", "Dinner", "Direct", "Dirt", "Dirty", "Doctor", "Down", "Drama", "Draw", "Dream", "Drop", "Earth", "Eat", "Easy", "Editor", "Effect", "Eight", + "Elect", "Effort", "Emote", "Enter", "Engine", "Enemy", "Empty", "Entry", "Error", "Enough", "Every", "Exact", "Eye", "Expert", "Face", "Fact", "Fade", + "Fail", "Family", "Famous", "Farmer", "Father", "Fight", "Find", "Finger", "Fire", "First", "Fit", "Fix", "Fish", "Field", "Floor", "Focus", "Fly", + "Forest", "Force", "Frame", "Uber"); + + private static final List longWords = Arrays.asList("Actually", "Aircraft", "Backbone", "Blooming", "Brightly", "Building", "Camellia", "Cardinal", "Careless", "Chemical", "Cheerful", + "Civilian", "Daughter", "Demolish", "Detector", "Disaster", "Disposal", "Electron", "Elective", "Engaging", "Enormous", "Erection", "Evidence", "Exertion", + "External", "Faithful", "Familiar", "Favorite", "Fearless", "Fixation", "Fragment", "Generous", "Grateful", "Grievous", "Hydrogen", "Horrible", "Ignorant", + "Industry", "Majority", "Military", "Mountain", "Mythical", "Normally", "Numerous", "Organism", "Overview", "Pacifist", "Pentagon", "Perilous", "Physical", + "Precious", "Prestige", "Puzzling", "Railroad", "Reckless"); + + private static final List conjuctions = Arrays.asList("The", "Da", "And", "Of", "By", "Is", "El", "Its", "MC", "GANGMEMBER", "xXx", "_", "__"); + + private static final List onlyNames = Arrays.asList("Ibirawyr", "Niniel", "Celahan", "Gwysien", "Figovudd", "Zathiel", "Adwiawyth", "Nydinia", "Laraeb", "Eowendasa", "Grendakin", + "Werradia", "Cauth", "Umigolian", "Tardond", "Dwearia", "Yeiwyn", "Adraclya", "Zaev", "Thabeth", "Chuven", "Zaredon", "Bob", "Robert", "Johnny", "Joy", + "Matthew", "Michael", "Jacob", "Joshua", "Daniel", "Christopher", "Andrew", "Ethan", "Joseph", "William", "Anthony", "David", "Alexander", "Nicholas", + "Ryan", "Tyler", "James", "John", "Jonathan", "Noah", "Brandon", "Christian", "Dylan", "Samuel", "Benjamin", "Nathan", "Zachary", "Logan", "Justin", + "Gabriel", "Emily", "Madison", "Emma", "Olivia", "Hannah", "Abigail", "Isabella", "Samantha", "Elizabeth", "Ashley", "Alexis", "Sarah", "Sophia", + "Alyssa", "Grace", "Ava", "Taylor", "Brianna", "Lauren", "Chloe", "Natalie", "Kayla", "Jessica", "Anna", "Victoria", "Mia", "Hailey", "Sydney", "Jasmine"); + + private static final List japaneseNames = Arrays.asList("Ai", "Aya", "Ayako", "Itsuki", "Eita", "Eiko", "Kanta", "Kaito", "Kenta", "Kento", "Kouki", "Kouta", "Kouya", "Kou", + "Keito", "Keita", "Saya", "Sayako", "Sara", "Sizuki", "Sizuko", "Sizuno", "Sizuya", "Suzuka", "Suzuki", "Suzuko", "Sumi", "Seiya", "Souta", "Souya", + "Sou", "Taichi", "Takuya", "Tatsuki", "Chitose", "Tutomu", "Tumuya", "Tetsuya", "Tetsuto", "Tekuto", "Touya", "Tomi", "Nami", "Nao", "Neo", "Notomi", + "Haruya", "Harumi", "Haruto", "Hitomi", "Hitoshi", "Fuuta", "Fuyuki", "Fuuto", "Mami", "Maya", "Mai", "Masaya", "Masahiro", "Masato", "Misaki", "Mitsuki", + "Mutsuki", "Mei", "Yae", "Yuuto", "Yuuta", "Yuuya", "Youta", "Youki"); + + + public static String generate() { + Random random = new Random(); + return generate(NicknamePattern.values()[random.nextInt(NicknamePattern.values().length)]); + } + + public static String generateSkin() { + Random random = new Random(); + + return skinNames.get(random.nextInt(skinNames.size())); + } + + public static String generate(NicknamePattern pattern) { + + String disguiseNickname = null; + + if (pattern.equals(NicknamePattern.NameWithNumbers)) { + Random random = new Random(); + String name = onlyNames.get(random.nextInt(onlyNames.size())); + if (name.length() <= 10 && chance(50.0)) { + disguiseNickname = name + "_" + random.nextInt(9999); + } else { + disguiseNickname = name + random.nextInt(9999); + } + } + + if (pattern.equals(NicknamePattern.TwoShortsWithConjunction)) { + pattern = NicknamePattern.JapaneseNameWithBirth; + } + + if (pattern.equals(NicknamePattern.JapaneseNameWithBirth)) { + Random random = new Random(); + String name = japaneseNames.get(random.nextInt(japaneseNames.size())); + String birth = random.nextInt(12) + 1 + String.valueOf(random.nextInt(30) + 1); + if (chance(50.0)) { + disguiseNickname = name + "_" + birth; + } else { + disguiseNickname = name + birth; + } + } + + if (pattern.equals(NicknamePattern.LongWithNumbers)) { + Random random = new Random(); + String name = longWords.get(random.nextInt(longWords.size())); + if (chance(50.0)) { + disguiseNickname = name + "_" + random.nextInt(9999); + } else { + disguiseNickname = name + random.nextInt(9999); + } + } + + if (pattern.equals(NicknamePattern.ShortWithConjunction)) { + Random random = new Random(); + String name = conjuctions.get(random.nextInt(conjuctions.size())); + String secondName = shortWords.get(random.nextInt(shortWords.size())); + if (chance(50.0)) { + disguiseNickname = name + "_" + secondName; + } else { + disguiseNickname = name + secondName; + } + } + + if (pattern.equals(NicknamePattern.ShortAndLong)) { + Random random = new Random(); + String name = shortWords.get(random.nextInt(shortWords.size())); + String secondName = longWords.get(random.nextInt(longWords.size())); + disguiseNickname = name + secondName; + } + + if (chance(50.0)) { + assert disguiseNickname != null; + disguiseNickname = disguiseNickname.toLowerCase(); + } + + return disguiseNickname; + } + + private static boolean chance(double percent) { + return Math.random() < percent / 100.0; + } + + public void setPlayerDisguise(Player player, String disguiseName, String disguiseSkin) { + LandCore.getInstance().getStaffManager().messageStaff(Rank.TRIAL_MOD, CC.GRAY + "[Staff] " + + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + + player.getName() + CC.GRAY + " has disguise as " + CC.PRIMARY + disguiseName + ); + + NickAPI.nick(player, disguiseName); + NickAPI.setGameProfileName(player, disguiseName); + NickAPI.setUniqueId(player, disguiseName); + + NickAPI.setSkin(player, disguiseSkin); + NickAPI.refreshPlayer(player); + + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + final EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + + entityPlayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, entityPlayer)); + entityPlayer.playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, entityPlayer)); + entityPlayer.playerConnection.sendPacket(new PacketPlayOutRespawn( + entityPlayer.getWorld().worldProvider.getDimension(), + entityPlayer.getWorld().worldData.getDifficulty(), + entityPlayer.getWorld().worldData.getType(), + WorldSettings.EnumGamemode.valueOf(entityPlayer.getBukkitEntity().getGameMode().name()) + )); + + updateTablist(); + updateCache(player); + + player.setDisplayName(player.getName()); + player.setPlayerListName(player.getName()); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + + NickAPI.refreshPlayer(player); + NickAPI.refreshPlayerSync(player); + } + }); + + player.sendMessage(CC.SECONDARY + "You've disguised as " + CC.PRIMARY + disguiseName + CC.GRAY + " (with a random skin)" + CC.SECONDARY + "."); + } + + public boolean isNameUsed(String[] args, Player player) { + for (Player p : LandCore.getInstance().getServer().getOnlinePlayers()) { + if (p.getName().equalsIgnoreCase(args[0])) { + player.sendMessage(CC.RED + "That name is already used."); + return true; + } + } + + return false; + } + + // Make it check if the name contains a filtered word in between, before or after the text + boolean isFiltered(String[] args, Player player) { + List filteredWord = LandCore.getInstance().getConfig().getStringList("FILTERED-WORDS"); + if (filteredWord.contains(args[0].toLowerCase())) { + player.sendMessage(CC.RED + "You can't use that name because it contains a filtered word in it!"); + return true; + } + + return false; + } + + public void updateTablist() { + final List playerList = new ArrayList<>(net.minecraft.server.v1_8_R3.MinecraftServer.getServer().getPlayerList().players); + final List finalList = playerList.stream() + .sorted(Comparator.comparingInt(potPlayer -> -(LandCore.getInstance().getProfileManager().getProfile(potPlayer.getUniqueID()).getDisguiseRank() != null ? LandCore.getInstance().getProfileManager().getProfile(potPlayer.getUniqueID()).getDisguiseRank().getWeight() : LandCore.getInstance().getProfileManager().getProfile(potPlayer.getUniqueID()).getGrant().getRank().getWeight()))) + .collect(Collectors.toList()); + + try { + final Object list = net.minecraft.server.v1_8_R3.MinecraftServer.getServer().getPlayerList().getClass() + .getMethod("playerList", ((Class[]) null)) + .invoke(net.minecraft.server.v1_8_R3.MinecraftServer.getServer().getPlayerList()); + final Class playerListClass = list.getClass().getSuperclass(); + final Field declaredField = playerListClass.getDeclaredField("players"); + + declaredField.set(list, finalList); + } catch (Exception ignored) { + } + } + + public void updateCache(Player player) { + final List playerList = new ArrayList<>(net.minecraft.server.v1_8_R3.MinecraftServer.getServer().getPlayerList().players); + final EntityPlayer entityPlayer = playerList.stream() + .filter(entityPlayer1 -> entityPlayer1.getUniqueID().equals(player.getUniqueId())) + .findFirst().orElse(null); + + playerList.remove(entityPlayer); + playerList.add(((CraftPlayer) player).getHandle()); + + try { + final Object list = net.minecraft.server.v1_8_R3.MinecraftServer.getServer().getPlayerList().getClass() + .getMethod("playerList", ((Class[]) null)) + .invoke(net.minecraft.server.v1_8_R3.MinecraftServer.getServer().getPlayerList()); + final Class playerListClass = list.getClass().getSuperclass(); + final Field declaredField = playerListClass.getDeclaredField("players"); + + declaredField.set(list, playerList); + } catch (Exception ignored) { + } + } + + public enum NicknamePattern { + ShortAndLong, + NameWithNumbers, + LongWithNumbers, + ShortWithConjunction, + JapaneseNameWithBirth, + TwoShortsWithConjunction + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/disguise/menu/DisguiseMenu.java b/LandCore/src/main/java/me/devkevin/landcore/disguise/menu/DisguiseMenu.java new file mode 100644 index 0000000..49172d5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/disguise/menu/DisguiseMenu.java @@ -0,0 +1,252 @@ +package me.devkevin.landcore.disguise.menu; + +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.nametag.impl.InternalNametag; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.inventory.InventoryUI; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import xyz.haoshoku.nick.api.NickAPI; + +import java.util.Arrays; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 19:00 + * DisguiseMenu / me.devkevin.landcore.disguise / LandCore + */ +@Getter +public class DisguiseMenu { + private final InventoryUI rankMenu = new InventoryUI(CC.GRAY + "Pick a Rank -> (Disguise)", 1); + + public DisguiseMenu() { + setup(); + } + + private void setup() { + this.rankMenu.setItem(0, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEATHER_CHESTPLATE).color(Color.BLUE) + .name(CC.BLUE + "✦" + CC.GREEN + "Basic") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "In disguise mode", + CC.GRAY + CC.B + "you can only choose", + CC.GRAY + CC.B + "donor ranks or member.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + coreProfile.setDisguiseRank(Rank.BASIC); + player.sendMessage(CC.GREEN + "You has choose " + CC.BLUE + "✦" + CC.GREEN + "Basic" + CC.GREEN + " rank."); + + player.closeInventory(); + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + LandCore.getInstance().getDisguiseManager().updateTablist(); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + }); + } + }); + + this.rankMenu.setItem(1, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEATHER_CHESTPLATE).color(Color.YELLOW) + .name(CC.YELLOW + "✯" + CC.GOLD + "Gold") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "In disguise mode", + CC.GRAY + CC.B + "you can only choose", + CC.GRAY + CC.B + "donor ranks or member.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + coreProfile.setDisguiseRank(Rank.GOLD); + player.sendMessage(CC.GREEN + "You has choose " + CC.YELLOW + "✯" + CC.GOLD + "Gold" + CC.GREEN + " rank."); + + player.closeInventory(); + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + LandCore.getInstance().getDisguiseManager().updateTablist(); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + }); + } + }); + + this.rankMenu.setItem(2, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEATHER_CHESTPLATE).color(Color.LIME) + .name(CC.GREEN + "✵" + CC.DARK_GREEN + "Emerald") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "In disguise mode", + CC.GRAY + CC.B + "you can only choose", + CC.GRAY + CC.B + "donor ranks or member.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + coreProfile.setDisguiseRank(Rank.EMERALD); + player.sendMessage(CC.GREEN + "You has choose " + CC.GREEN + "✵" + CC.DARK_GREEN + "Emerald" + CC.GREEN + " rank."); + + player.closeInventory(); + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + LandCore.getInstance().getDisguiseManager().updateTablist(); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + }); + } + }); + + this.rankMenu.setItem(3, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEATHER_CHESTPLATE).color(Color.AQUA) + .name(CC.AQUA + "❇" + CC.D_AQUA + "Diamond") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "In disguise mode", + CC.GRAY + CC.B + "you can only choose", + CC.GRAY + CC.B + "donor ranks or member.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + coreProfile.setDisguiseRank(Rank.DIAMOND); + player.sendMessage(CC.GREEN + "You has choose " + CC.AQUA + "❇" + CC.D_AQUA + "Diamond" + CC.GREEN + " rank."); + + player.closeInventory(); + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + LandCore.getInstance().getDisguiseManager().updateTablist(); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + }); + } + }); + + this.rankMenu.setItem(4, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEATHER_CHESTPLATE).color(Color.ORANGE) + .name(CC.GOLD + "❊" + CC.YELLOW + "LOL") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "In disguise mode", + CC.GRAY + CC.B + "you can only choose", + CC.GRAY + CC.B + "donor ranks or member.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + coreProfile.setDisguiseRank(Rank.LOL); + player.sendMessage(CC.GREEN + "You has choose " + CC.GOLD + "❊" + CC.YELLOW + "LOL" + CC.GREEN + " rank."); + + player.closeInventory(); + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + LandCore.getInstance().getDisguiseManager().updateTablist(); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + }); + } + }); + + this.rankMenu.setItem(8, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEATHER_CHESTPLATE).color(Color.GREEN) + .name(CC.GREEN + "Member") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "In disguise mode", + CC.GRAY + CC.B + "you can only choose", + CC.GRAY + CC.B + "donor ranks or member.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + coreProfile.setDisguiseRank(Rank.MEMBER); + player.sendMessage(CC.GREEN + "You has choose " + CC.GREEN + "Member" + CC.GREEN + " rank."); + + player.closeInventory(); + + Bukkit.getScheduler().runTask(LandCore.getInstance(), () -> { + for (Player player1 : Bukkit.getOnlinePlayers()) { + player1.hidePlayer(player); + player1.showPlayer(player); + + LandCore.getInstance().getDisguiseManager().updateTablist(); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + + NickAPI.refreshPlayerSync(player); + } + }); + } + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/BanEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/BanEvent.java new file mode 100644 index 0000000..aed9dd9 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/BanEvent.java @@ -0,0 +1,39 @@ +package me.devkevin.landcore.event; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.command.CommandSender; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +@RequiredArgsConstructor +@Getter +public class BanEvent extends Event implements Cancellable { + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final CommandSender punisher; + private final UUID punishedId; + private boolean cancelled; + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/BaseEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/BaseEvent.java new file mode 100644 index 0000000..a9cbbad --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/BaseEvent.java @@ -0,0 +1,31 @@ +package me.devkevin.landcore.event; + +import me.devkevin.landcore.LandCore; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 16/01/2023 @ 12:36 + * BaseEvent / land.pvp.core.event / LandCore + */ +public class BaseEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public boolean call() { + LandCore.getInstance().getServer().getPluginManager().callEvent(this); + return this instanceof Cancellable && ((Cancellable) this).isCancelled(); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/CoreEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/CoreEvent.java new file mode 100644 index 0000000..feae9ff --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/CoreEvent.java @@ -0,0 +1,24 @@ +package me.devkevin.landcore.event; + +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/01/2023 @ 18:31 + * CoreEvent / me.devkevin.landcore.event / LandCore + */ +public class CoreEvent extends Event { + + private static HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/CoreProfileEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/CoreProfileEvent.java new file mode 100644 index 0000000..e342927 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/CoreProfileEvent.java @@ -0,0 +1,22 @@ +package me.devkevin.landcore.event; + +import me.devkevin.landcore.player.CoreProfile; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 16/01/2023 @ 12:34 + * CoreProfileEvent / land.pvp.core.event / LandCore + */ +@Getter +@RequiredArgsConstructor +public class CoreProfileEvent extends BaseEvent { + private final CoreProfile profile; + + public UUID getUniqueId() { + return this.profile.getId(); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/PlayerFakeEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/PlayerFakeEvent.java new file mode 100644 index 0000000..b36e1db --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/PlayerFakeEvent.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.event; + +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:14 + * PlayerFakeEvent / land.pvp.core.event / LandCore + */ +@Getter +public class PlayerFakeEvent extends BaseEvent { + private Player player; + + public PlayerFakeEvent(Player player) { + this.player = player; + } + + public Player getPlayer() { + return player; + } + + public UUID getUniqueId() { + return player.getUniqueId(); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/disguise/PreDisguiseEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/disguise/PreDisguiseEvent.java new file mode 100644 index 0000000..4ad5ed9 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/disguise/PreDisguiseEvent.java @@ -0,0 +1,44 @@ +package me.devkevin.landcore.event.disguise; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 19/01/2023 @ 17:19 + * PreDisguiseEvent / land.pvp.core.event.disguise / LandCore + */ +@Getter +@RequiredArgsConstructor +public class PreDisguiseEvent extends Event implements Cancellable { + + private static final HandlerList HANDLERS = new HandlerList(); + + private final Player player; + + private boolean cancelled; + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean b) { + this.cancelled = b; + } +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/disguise/UnDisguiseEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/disguise/UnDisguiseEvent.java new file mode 100644 index 0000000..0b26573 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/disguise/UnDisguiseEvent.java @@ -0,0 +1,30 @@ +package me.devkevin.landcore.event.disguise; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 19/01/2023 @ 17:20 + * UnDisguiseEvent / land.pvp.core.event.disguise / LandCore + */ +@Getter +@RequiredArgsConstructor +public class UnDisguiseEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + + private final Player player; + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerFreezeEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerFreezeEvent.java new file mode 100644 index 0000000..471020f --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerFreezeEvent.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.event.player; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.event.CoreEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/01/2023 @ 18:27 + * PlayerFreezeEvent / me.devkevin.landcore.event.player / LandCore + */ +@Getter +@Setter +public class PlayerFreezeEvent extends PlayerEvent { + + public PlayerFreezeEvent(Player who) { + super(who); + } + + @Override + public HandlerList getHandlers() { + return null; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerMessageEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerMessageEvent.java new file mode 100644 index 0000000..945f399 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerMessageEvent.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.event.player; + +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +@Getter +public class PlayerMessageEvent extends PlayerEvent { + private static final HandlerList HANDLERS = new HandlerList(); + private final Player receiver; + private final String message; + + public PlayerMessageEvent(Player sender, Player receiver, String message) { + super(sender); + this.receiver = receiver; + this.message = message; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerRankChangeEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerRankChangeEvent.java new file mode 100644 index 0000000..32b6be6 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/player/PlayerRankChangeEvent.java @@ -0,0 +1,32 @@ +package me.devkevin.landcore.event.player; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.Grant; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +@Getter +public class PlayerRankChangeEvent extends PlayerEvent { + private static final HandlerList HANDLERS = new HandlerList(); + private final CoreProfile profile; + private final Grant newRank; + private final long duration; + + public PlayerRankChangeEvent(Player who, CoreProfile profile, Grant newRank, long duration) { + super(who); + this.profile = profile; + this.newRank = newRank; + this.duration = duration; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/server/ServerShutdownCancelEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/server/ServerShutdownCancelEvent.java new file mode 100644 index 0000000..218cf82 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/server/ServerShutdownCancelEvent.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.event.server; + +import org.bukkit.event.HandlerList; +import org.bukkit.event.server.ServerEvent; + +public class ServerShutdownCancelEvent extends ServerEvent { + private static final HandlerList HANDLER_LIST = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/event/server/ServerShutdownScheduleEvent.java b/LandCore/src/main/java/me/devkevin/landcore/event/server/ServerShutdownScheduleEvent.java new file mode 100644 index 0000000..f79a8fe --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/event/server/ServerShutdownScheduleEvent.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.event.server; + +import org.bukkit.event.HandlerList; +import org.bukkit.event.server.ServerEvent; + +public class ServerShutdownScheduleEvent extends ServerEvent { + private static final HandlerList HANDLER_LIST = new HandlerList(); + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/Faction.java b/LandCore/src/main/java/me/devkevin/landcore/faction/Faction.java new file mode 100644 index 0000000..0a6060b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/Faction.java @@ -0,0 +1,49 @@ +package me.devkevin.landcore.faction; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 0:38 + * Faction / me.devkevin.landcore.faction / LandCore + */ +@Getter +@Setter +@RequiredArgsConstructor +public class Faction { + private final String name; + private final UUID leader; + + private int limit = 12; + + private List members = new ArrayList<>(); + private List captains = new ArrayList<>(); + + private String description; + private String password; + private String dateCreated; + private int elo = 1000; + private int wins; + private int losses; + private int winStreak; + + private boolean factionChat; + + public void broadcast(String message) { + members.forEach(users -> { + Player player = (Player) Bukkit.getOfflinePlayer(users); + + if (player != null) { + player.sendMessage(message); + } + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/FactionHelpCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/FactionHelpCommand.java new file mode 100644 index 0000000..66a4ef7 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/FactionHelpCommand.java @@ -0,0 +1,51 @@ +package me.devkevin.landcore.faction.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +import java.util.Arrays; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 2:11 + * FactionHelpCommand / me.devkevin.landcore.faction.commands / LandCore + */ +public class FactionHelpCommand extends PlayerCommand { + + public FactionHelpCommand(LandCore plugin) { + super("faction"); + setAliases(Arrays.asList("f", "f help", "faction help")); + } + + @Override + public void execute(Player player, String[] args) { + player.sendMessage(new String[] { + CC.GRAY + CC.BOARD_SEPARATOR, + CC.GOLD + CC.B + "Factions Help " + CC.GRAY + "-" + CC.GRAY + " Information on how to use faction commands", + CC.GRAY + CC.BOARD_SEPARATOR, + CC.GOLD + "General Commands:", + CC.YELLOW + "/faction create " + CC.GRAY + "- Create a new faction", + CC.YELLOW + "/faction leave " + CC.GRAY + "- Leave your current faction", + CC.YELLOW + "/faction accept [faction|player] " + CC.GRAY + "- Accept clan invitation", + CC.YELLOW + "/faction info [faction|player] " + CC.GRAY + "- View a clan's information", + "", + CC.GOLD + "Leader Commands:", + CC.YELLOW + "/faction disband " + CC.GRAY + "- Disband your faction", + CC.YELLOW + "/faction description " + CC.GRAY + "- Set your faction's description", + CC.YELLOW + "/faction password " + CC.GRAY + "- Sets faction password", + CC.YELLOW + "/faction promote " + CC.GRAY + "- Promote a player", + CC.YELLOW + "/faction demote " + CC.GRAY + "- Demote a player", + "", + CC.GOLD + "Captain Commands:", + CC.YELLOW + "/faction invite " + CC.GRAY + "- Invite a player to join your faction", + CC.YELLOW + "/faction kick " + CC.GRAY + "- Kick a player from your faction", + "", + CC.GOLD + "Other Help:", + CC.YELLOW + "To use " + CC.PINK + "faction chat" + CC.YELLOW + " /factionchat or /fc", + CC.YELLOW + "Factions are limited to " + CC.PINK + "12 members" + CC.YELLOW + ".", + CC.GRAY + CC.BOARD_SEPARATOR + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionDemoteCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionDemoteCommand.java new file mode 100644 index 0000000..c5e2404 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionDemoteCommand.java @@ -0,0 +1,66 @@ +package me.devkevin.landcore.faction.commands.captain; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 13:50 + * FactionDemoteCommand / me.devkevin.landcore.faction.commands.captain / LandCore + */ +public class FactionDemoteCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionDemoteCommand(LandCore plugin) { + super("faction.demote"); + this.plugin = plugin; + setAliases("f.demote"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length != 1) { + player.sendMessage(CC.RED + "Usage: /faction demote "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + + if (!faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the faction leader!"); + return; + } + + OfflinePlayer offlinePlayer = this.plugin.getServer().getOfflinePlayer(args[0]); + + if (offlinePlayer.getPlayer() != null && offlinePlayer.getPlayer() == player) { + player.sendMessage(CC.RED + "You may not demote yourself!"); + return; + } + + if (!faction.getMembers().contains(offlinePlayer.getUniqueId())) { + player.sendMessage(player.getName() + CC.RED + " is not in your faction!"); + return; + } + + if (!faction.getCaptains().contains(offlinePlayer.getUniqueId())) { + player.sendMessage(player.getName() + CC.RED + " is not a faction captain!"); + return; + } + + faction.getCaptains().remove(offlinePlayer.getUniqueId()); + faction.broadcast(player.getName() + CC.YELLOW + " has been demoted to faction member!"); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionInviteCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionInviteCommand.java new file mode 100644 index 0000000..0128ebb --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionInviteCommand.java @@ -0,0 +1,94 @@ +package me.devkevin.landcore.faction.commands.captain; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.invite.FactionInvite; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 13:53 + * FactionInviteCommand / me.devkevin.landcore.faction.commands.captain / LandCore + */ +public class FactionInviteCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionInviteCommand(LandCore plugin) { + super("faction.invite"); + this.plugin = plugin; + setAliases("f.invite"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length != 1) { + player.sendMessage(CC.RED + "Usage: /faction invite "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + + if (faction.getMembers().size() >= faction.getLimit()) { + player.sendMessage(CC.RED + "Your faction has exceeded the max member limit, you are unable to invite no one currently!"); + return; + } + + if (!faction.getCaptains().contains(player.getUniqueId()) && !faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not a faction captain!"); + return; + } + + Player target = this.plugin.getServer().getPlayer(args[0]); + if (target == null) { + player.sendMessage(CC.RED + "Could not find player."); + return; + } + + if (target == player) { + player.sendMessage(CC.RED + "Yoy may not invite yourself to a faction!"); + return; + } + + if (faction.getMembers().contains(target.getUniqueId())) { + player.sendMessage(target.getDisplayName() + CC.RED + " is already in your faction!"); + return; + } + + FactionProfile targetProfile = this.plugin.getFactionManager().getProfile(target); + if (targetProfile.getFaction() != null) { + player.sendMessage(target.getDisplayName() + CC.RED + " already belongs to a faction. They must first leave their faction to be able to receive invites."); + return; + } + + FactionInvite factionInvite = targetProfile.getInviteList().stream().filter(ci -> ci.getFaction() == faction && System.currentTimeMillis() - ci.getTimestamp() <= 60000).findFirst().orElse(null); + if (factionInvite != null) { + player.sendMessage(target.getDisplayName() + CC.RED + " has already been invited to the faction within the last 60 seconds."); + return; + } + targetProfile.getInviteList().add(new FactionInvite(faction)); + faction.broadcast(target.getDisplayName() + CC.YELLOW + " has been invited to the faction."); + + TextComponent textComponent = new TextComponent(CC.YELLOW + "Click "); + TextComponent clickable = new TextComponent(CC.GOLD + "here"); + textComponent.addExtra(clickable); + textComponent.addExtra(CC.YELLOW + " to accept the invite"); + clickable.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(CC.GREEN + "Click to join " + target.getDisplayName() + CC.GREEN + "'s faction").create())); + clickable.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/faction join " + player.getName())); + + target.sendMessage(player.getDisplayName() + CC.YELLOW + " has invited you to join their faction " + CC.GRAY + "'" + CC.DARK_GREEN + faction.getName() + CC.GRAY + "'"); + target.spigot().sendMessage(textComponent); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionKickCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionKickCommand.java new file mode 100644 index 0000000..3a74155 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionKickCommand.java @@ -0,0 +1,74 @@ +package me.devkevin.landcore.faction.commands.captain; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 13:59 + * FactionKickCommand / me.devkevin.landcore.faction.commands.captain / LandCore + */ +public class FactionKickCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionKickCommand(LandCore plugin) { + super("faction.kick"); + this.plugin = plugin; + setAliases("f.kick"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length != 1) { + player.sendMessage(CC.RED + "Usage: /faction kick "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + if (!faction.getCaptains().contains(player.getUniqueId()) && !faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not a faction captain!"); + return; + } + + OfflinePlayer offlinePlayer = this.plugin.getServer().getOfflinePlayer(args[0]); + if (offlinePlayer.getPlayer() != null && offlinePlayer.getPlayer() == player) { + player.sendMessage(CC.RED + "You may not kick yourself from the faction!"); + return; + } + + if (!faction.getMembers().contains(offlinePlayer.getUniqueId())) { + player.sendMessage(player.getName() + CC.RED + " is not in your faction!"); + return; + } + + if ((faction.getCaptains().contains(offlinePlayer.getUniqueId()) && !faction.getLeader().equals(player.getUniqueId())) || faction.getLeader() == offlinePlayer.getUniqueId()) { + player.sendMessage(CC.RED + "You may only kick faction members."); + return; + } + + faction.getMembers().remove(offlinePlayer.getUniqueId()); + faction.getCaptains().remove(offlinePlayer.getUniqueId()); + + if (offlinePlayer.getPlayer() != null && offlinePlayer.getPlayer().isOnline()) { + Player target = offlinePlayer.getPlayer(); + + FactionProfile targetProfile = this.plugin.getFactionManager().getProfile(target); + targetProfile.setFaction(null); + + target.sendMessage(CC.RED + CC.B + "You have been kicked from the faction!"); + } + + faction.broadcast(player.getName() + CC.YELLOW + " has been kicked from the faction!"); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionPasswordCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionPasswordCommand.java new file mode 100644 index 0000000..5f8079e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionPasswordCommand.java @@ -0,0 +1,48 @@ +package me.devkevin.landcore.faction.commands.captain; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 14:02 + * FactionPasswordCommand / me.devkevin.landcore.faction.commands.captain / LandCore + */ +public class FactionPasswordCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionPasswordCommand(LandCore plugin) { + super("faction.password"); + this.plugin = plugin; + setAliases("f.password"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length != 1) { + player.sendMessage(CC.RED + "Usage: /faction password "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + if (!faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the faction leader!"); + return; + } + + String password = args[0]; + faction.setPassword(password); + + player.sendMessage(CC.YELLOW + "Your faction password is now " + CC.GRAY + "'" + CC.DARK_GREEN + password + CC.GRAY + "'" + CC.YELLOW + "."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionPromoteCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionPromoteCommand.java new file mode 100644 index 0000000..7065525 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/captain/FactionPromoteCommand.java @@ -0,0 +1,65 @@ +package me.devkevin.landcore.faction.commands.captain; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 14:04 + * FactionPromoteCommand / me.devkevin.landcore.faction.commands.captain / LandCore + */ +public class FactionPromoteCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionPromoteCommand(LandCore plugin) { + super("faction.promote"); + this.plugin = plugin; + setAliases("f.promote"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length != 1) { + player.sendMessage(CC.RED + "Usage: /faction promote "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + + if (!faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the faction leader!"); + return; + } + + OfflinePlayer offlinePlayer = this.plugin.getServer().getOfflinePlayer(args[0]); + + if (offlinePlayer.getPlayer() != null && offlinePlayer.getPlayer() == player) { + player.sendMessage(CC.RED + "You may not promote yourself!"); + return; + } + + if (!faction.getMembers().contains(offlinePlayer.getUniqueId())) { + player.sendMessage(player.getName() + CC.RED + " is not in your faction!"); + return; + } + + if (faction.getCaptains().contains(offlinePlayer.getUniqueId())) { + player.sendMessage(player.getName() + CC.RED + " is already a faction captain!"); + return; + } + + faction.getCaptains().add(offlinePlayer.getUniqueId()); + faction.broadcast(player.getName() + CC.YELLOW + " has been promoted to faction captain!"); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/leader/FactionDescriptionCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/leader/FactionDescriptionCommand.java new file mode 100644 index 0000000..0818b45 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/leader/FactionDescriptionCommand.java @@ -0,0 +1,50 @@ +package me.devkevin.landcore.faction.commands.leader; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 13:38 + * FactionDescriptionCommand / me.devkevin.landcore.faction.commands.leader / LandCore + */ +public class FactionDescriptionCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionDescriptionCommand(LandCore plugin) { + super("faction.description"); + this.plugin = plugin; + setAliases("f.description"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(CC.RED + "Usage: /faction description "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + + if (faction.getLeader() != player.getUniqueId()) { + player.sendMessage(CC.RED + "You are not the faction leader!"); + return; + } + + String description = StringUtil.buildString(args, 0); + faction.setDescription(description); + faction.broadcast(player.getDisplayName() + CC.YELLOW + " has set the faction's description to " + CC.GRAY + "'" + CC.DARK_GREEN + description + CC.GRAY + "'" + CC.YELLOW + "."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/leader/FactionDisbandCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/leader/FactionDisbandCommand.java new file mode 100644 index 0000000..327612e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/leader/FactionDisbandCommand.java @@ -0,0 +1,57 @@ +package me.devkevin.landcore.faction.commands.leader; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 13:46 + * FactionDisbandCommand / me.devkevin.landcore.faction.commands.leader / LandCore + */ +public class FactionDisbandCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionDisbandCommand(LandCore plugin) { + super("faction.disband"); + this.plugin = plugin; + setAliases("f.disband"); + } + + @Override + public void execute(Player player, String[] args) { + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + + Faction faction = factionProfile.getFaction(); + + if (!faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the faction leader!"); + return; + } + + player.sendMessage(CC.RED + CC.B + "You have successfully disbanded your faction!"); + + faction.getMembers().remove(player.getUniqueId()); + factionProfile.setFaction(null); + faction.broadcast(CC.RED + CC.B + "Your faction has been disbanded."); + + faction.getMembers().forEach(u -> { + Player member = this.plugin.getServer().getPlayer(u); + + if (member != null) { + FactionProfile memberProfile = this.plugin.getFactionManager().getProfile(member); + memberProfile.setFaction(null); + } + }); + + this.plugin.getFactionManager().getFactions().remove(faction); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionAcceptCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionAcceptCommand.java new file mode 100644 index 0000000..693ad80 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionAcceptCommand.java @@ -0,0 +1,83 @@ +package me.devkevin.landcore.faction.commands.player; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.invite.FactionInvite; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +import java.util.Arrays; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 2:17 + * FactionAcceptCommand / me.devkevin.landcore.faction.commands.player / LandCore + */ +public class FactionAcceptCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionAcceptCommand(LandCore plugin) { + super("faction.accept"); + this.plugin = plugin; + setAliases(Arrays.asList("f.accept", "faction.join", "f.join")); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length < 1) { + player.sendMessage(CC.RED + "Usage: /faction "); + return; + } + + String name = args[0]; + FactionInvite factionInvite = getInvite(player, name); + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() != null) { + player.sendMessage(CC.RED + "You are already in a faction!"); + return; + } + + if (factionInvite == null && (getFaction(name) == null || getFaction(name).getPassword() == null)) { + player.sendMessage(CC.RED + "You weren't invited to a faction with this name or a faction with a member with this name."); + return; + } + + if (factionInvite == null && getFaction(name).getPassword() != null && args.length < 2) { + player.sendMessage(CC.RED + "You need the password or an invitation to join this faction."); + player.sendMessage(CC.YELLOW + "To join with a password, use " + CC.PINK + "/faction join " + name + " "); + return; + } + + Faction faction = getFaction(name); + + if (faction.getPassword() != null && args.length >= 2 && factionInvite == null) { + String password = args[1]; + + if (!faction.getPassword().equalsIgnoreCase(password)) { + player.sendMessage(CC.RED + "The password you have entered is incorrect."); + return; + } + } + + factionProfile.setFaction(faction); + faction.getMembers().add(player.getUniqueId()); + + if (factionInvite != null) factionProfile.getInviteList().remove(factionInvite); + + faction.broadcast(player.getDisplayName() + CC.YELLOW + " has joined the faction!"); + } + + private FactionInvite getInvite(Player player, String name) { + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + return factionProfile.getInviteList().stream().filter(ci -> ci.getFaction() == getFaction(name) && System.currentTimeMillis() - ci.getTimestamp() <= 60000 && !ci.isCancelled()).findFirst().orElse(null); + } + + private Faction getFaction(String name) { + return this.plugin.getFactionManager().getFactions().stream().filter(c -> c.getName().equalsIgnoreCase(name) || c.getMembers().contains(this.plugin.getServer().getOfflinePlayer(name).getUniqueId())).findFirst().orElse(null); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionChatCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionChatCommand.java new file mode 100644 index 0000000..6528faa --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionChatCommand.java @@ -0,0 +1,33 @@ +package me.devkevin.landcore.faction.commands.player; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 22/03/2023 @ 12:42 + * FactionChatCommand / me.devkevin.landcore.faction.commands.player / LandCore + */ +public class FactionChatCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionChatCommand(LandCore plugin) { + super("factionchat"); + this.plugin = plugin; + setAliases("fc"); + } + + @Override + public void execute(Player player, String[] args) { + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + boolean inFactionChat = !factionProfile.getFaction().isFactionChat(); + + factionProfile.getFaction().setFactionChat(inFactionChat); + + player.sendMessage(inFactionChat ? CC.GREEN + "You are now in faction chat." : CC.RED + "You are no longer in faction chat."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionCreateCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionCreateCommand.java new file mode 100644 index 0000000..9bbe4aa --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionCreateCommand.java @@ -0,0 +1,77 @@ +package me.devkevin.landcore.faction.commands.player; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.LandCoreAPI; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.TaskUtil; +import me.devkevin.landcore.utils.message.CC; +import org.apache.commons.lang.StringUtils; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 2:28 + * FactionCreateCommand / me.devkevin.landcore.faction.commands.player / LandCore + */ +public class FactionCreateCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionCreateCommand(LandCore plugin) { + super("faction.create"); + this.plugin = plugin; + setAliases("f create"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length != 1) { + player.sendMessage(CC.RED + "Usage: /faction create "); + return; + } + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() != null) { + player.sendMessage(CC.RED + "You are already in a faction."); + return; + } + + String name = args[0]; + + if (name.length() < 2) { + player.sendMessage(CC.RED + "Faction names must be greater than or equal to 2 characters long."); + return; + } + + if (!StringUtils.isAlpha(name)) { + player.sendMessage(CC.RED + "Faction names must only contain alpha characters (letters only)."); + return; + } + + if (name.length() > 8) { + player.sendMessage(CC.RED + "Faction names must be less than or equal to 8 characters long."); + return; + } + + Faction faction = this.plugin.getFactionManager().getFaction(name); + + if (faction != null) { + player.sendMessage(CC.RED + "A faction with that name already exists!"); + return; + } + + Faction createdFaction = new Faction(name, player.getUniqueId()); + createdFaction.getMembers().add(player.getUniqueId()); + factionProfile.setFaction(createdFaction); + createdFaction.setDescription("This is the default description..."); + createdFaction.setDateCreated(LandCoreAPI.getTodayDate() + " " + LandCoreAPI.getCurrentTime()); + this.plugin.getFactionManager().getFactions().add(createdFaction); + + player.sendMessage(CC.GREEN + "You have successfully created a new faction!"); + + TaskUtil.runAsync(plugin.getFactionManager()::save); + this.plugin.getFactionManager().savePlayerFaction(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionInfoCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionInfoCommand.java new file mode 100644 index 0000000..b1bea68 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionInfoCommand.java @@ -0,0 +1,89 @@ +package me.devkevin.landcore.faction.commands.player; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.member.FactionMember; +import me.devkevin.landcore.faction.member.FactionMemberType; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.OfflinePlayer; +import org.bukkit.craftbukkit.libs.joptsimple.internal.Strings; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 13:32 + * FactionInfoCommand / me.devkevin.landcore.faction.commands.player / LandCore + */ +public class FactionInfoCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionInfoCommand(LandCore plugin) { + super("faction.info"); + this.plugin = plugin; + setAliases("f info"); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length == 0) { + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() == null) { + player.sendMessage(CC.RED + "You are not in a faction!"); + return; + } + describeFaction(player, factionProfile.getFaction()); + return; + } + + String name = args[0]; + Faction faction = this.plugin.getFactionManager().getFaction(name); + Faction playerFaction = playerFaction(name); + + if (faction == null && playerFaction == null) { + player.sendMessage(CC.RED + "No faction found with the name or member with the name '" + name + "'"); + return; + } + if (playerFaction != null && faction == playerFaction) { + describeFaction(player, faction); + return; + } + if (faction != null) describeFaction(player, faction); + if (playerFaction != null) describeFaction(player, playerFaction); + } + + private void describeFaction(Player player, Faction faction) { + List factionMembers = new ArrayList<>(); + faction.getMembers().forEach(u -> factionMembers.add(new FactionMember(u, faction.getLeader().equals(u) ? FactionMemberType.LEADER : faction.getCaptains().contains(u) ? FactionMemberType.CAPTAIN : FactionMemberType.MEMBER))); + factionMembers.sort(Comparator.comparing(cm -> cm.getType().getWeight())); + + List playerNames = new ArrayList<>(); + factionMembers.forEach(cm -> playerNames.add((faction.getLeader().equals(cm.getUuid()) ? CC.DARK_GREEN + "***" : faction.getCaptains().contains(cm.getUuid()) ? CC.DARK_GREEN + "*" : "") + colorName(cm.getUuid()))); + + player.sendMessage(CC.GRAY + CC.BOARD_SEPARATOR); + player.sendMessage(CC.DARK_GREEN + CC.B + faction.getName() + CC.GRAY + " [" + faction.getMembers().size() + "/12]"); + player.sendMessage(CC.YELLOW + "Description: " + CC.GRAY + faction.getDescription()); + player.sendMessage(CC.YELLOW + "Members: " + Strings.join(playerNames, CC.GRAY + ", ")); + player.sendMessage(CC.YELLOW + "Elo: " + CC.DARK_GREEN + (faction.getElo() == 0 ? "[N/A]" : faction.getElo())); + player.sendMessage(CC.YELLOW + "Date Created: " + CC.GREEN + faction.getDateCreated()); + player.sendMessage(CC.GOLD + "View this faction on our site: " + CC.GRAY + "www.prac.lol/faction/" + faction.getName()); + player.sendMessage(CC.GRAY + CC.BOARD_SEPARATOR); + } + + private Faction playerFaction(String name) { + OfflinePlayer offlinePlayer = this.plugin.getServer().getOfflinePlayer(name); + return this.plugin.getFactionManager().getFactions().stream().filter(faction -> faction.getMembers().contains(offlinePlayer.getUniqueId())).findFirst().orElse(null); + } + + private String colorName(UUID uuid) { + OfflinePlayer offlinePlayer = this.plugin.getServer().getOfflinePlayer(uuid); + return offlinePlayer.isOnline() ? CC.GREEN + offlinePlayer.getName() : CC.RED + offlinePlayer.getName(); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionLeaveCommand.java b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionLeaveCommand.java new file mode 100644 index 0000000..b8e7ed2 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/commands/player/FactionLeaveCommand.java @@ -0,0 +1,51 @@ +package me.devkevin.landcore.faction.commands.player; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.TaskUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 2:36 + * FactionLeaveCommand / me.devkevin.landcore.faction.commands.player / LandCore + */ +public class FactionLeaveCommand extends PlayerCommand { + private final LandCore plugin; + + public FactionLeaveCommand(LandCore plugin) { + super("faction.leave"); + this.plugin = plugin; + setAliases("f.leave"); + } + + @Override + public void execute(Player player, String[] args) { + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile.getFaction() != null) { + player.sendMessage(CC.RED + "You are already in a faction."); + return; + } + + Faction faction = factionProfile.getFaction(); + + if (faction.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are the faction leader. You must disband the faction or promote someone else."); + return; + } + + faction.getMembers().remove(player.getUniqueId()); + faction.getCaptains().remove(player.getUniqueId()); + factionProfile.setFaction(null); + faction.broadcast(player.getDisplayName() + CC.YELLOW + " has left the faction!"); + + player.sendMessage(CC.RED + CC.B + "You have left the faction!"); + + TaskUtil.runAsync(plugin.getFactionManager()::save); + this.plugin.getFactionManager().savePlayerFaction(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/invite/FactionInvite.java b/LandCore/src/main/java/me/devkevin/landcore/faction/invite/FactionInvite.java new file mode 100644 index 0000000..858e5f5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/invite/FactionInvite.java @@ -0,0 +1,20 @@ +package me.devkevin.landcore.faction.invite; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.landcore.faction.Faction; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 0:38 + * FactionInvite / me.devkevin.landcore.faction.invite / LandCore + */ +@Getter +@Setter +@RequiredArgsConstructor +public class FactionInvite { + private final Faction faction; + private long timestamp = System.currentTimeMillis(); + private boolean cancelled; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/listener/FactionListener.java b/LandCore/src/main/java/me/devkevin/landcore/faction/listener/FactionListener.java new file mode 100644 index 0000000..62c081c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/listener/FactionListener.java @@ -0,0 +1,84 @@ +package me.devkevin.landcore.faction.listener; + +import com.google.common.collect.Maps; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.Messages; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 1:29 + * FactionListener / me.devkevin.landcore.faction.listener / LandCore + */ +public class FactionListener implements Listener { + private final LandCore plugin = LandCore.getInstance(); + + @EventHandler + public void onPlayerLoginEvent(PlayerLoginEvent event) { + Player player = event.getPlayer(); + + this.plugin.getFactionManager().addPlayer(player); + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile == null) { + event.disallow(PlayerLoginEvent.Result.KICK_BANNED, Messages.DATA_LOAD_FAIL); + return; + } + + this.plugin.getFactionManager().loadPlayerFaction(player); + } + + @EventHandler + public void onPlayerJoinEvent(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + CoreProfile profile = this.plugin.getProfileManager().getProfile(player.getUniqueId()); + + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile != null) { + Map message = Maps.newHashMap(); + message.put("server", this.plugin.getServerName()); + message.put("sender", profile.getRank().getColor() + player.getName()); + + plugin.getRedisMessenger().send("faction-join", message); + } + } + + @EventHandler + public void onPlayerQuitEvent(PlayerQuitEvent event) { + Player player = event.getPlayer(); + + this.plugin.getFactionManager().removePlayer(player); + this.plugin.getFactionManager().savePlayerFaction(player); + } + + @EventHandler + public void onChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + String chatMessage = event.getMessage(); + + CoreProfile coreProfile = this.plugin.getProfileManager().getProfile(player.getUniqueId()); + FactionProfile factionProfile = this.plugin.getFactionManager().getProfile(player); + + if (factionProfile != null && factionProfile.getFaction() != null && factionProfile.getFaction().isFactionChat()) { + Map message = Maps.newHashMap(); + message.put("server", plugin.getServerName()); + message.put("format", coreProfile.getRank().getColor() + player.getName()); + message.put("message", chatMessage); + message.put("sender", event.getPlayer().getName()); + + plugin.getRedisMessenger().send("faction-chat", message); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/manager/FactionManager.java b/LandCore/src/main/java/me/devkevin/landcore/faction/manager/FactionManager.java new file mode 100644 index 0000000..392ec6a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/manager/FactionManager.java @@ -0,0 +1,145 @@ +package me.devkevin.landcore.faction.manager; + +import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.ReplaceOptions; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bson.Document; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 0:48 + * FactionManager / me.devkevin.landcore.faction.manager / LandCore + */ +@Getter +public class FactionManager { + private final LandCore plugin = LandCore.getInstance(); + + private final List factions = new ArrayList<>(); + private final Map factionProfileMap = new HashMap<>(); + + public FactionManager() { + load(); + } + + private void load() { + MongoCollection collection = this.plugin.getMongoStorage().getFactionsCollection(); + + for (Document document : collection.find()) { + Faction faction = new Faction(document.getString("name"), (UUID) document.get("leader")); + faction.setMembers((List) document.get("members")); + faction.getMembers().add((UUID) document.get("leader")); + faction.setCaptains((List) document.get("captains")); + faction.setDescription(document.getString("description")); + faction.setDateCreated(document.getString("date-created")); + faction.setElo(document.getInteger("elo")); + faction.setWins(document.getInteger("wins")); + faction.setLosses(document.getInteger("losses")); + faction.setWinStreak(document.getInteger("winStreak")); + if (document.containsKey("description")) { + faction.setDescription(document.getString("description")); + } + if (document.containsKey("password")) { + faction.setPassword(document.getString("password")); + } + + faction.setFactionChat(document.getBoolean("faction_chat_enabled")); + + factions.add(faction); + } + } + + public void save() { + MongoCollection collection = this.plugin.getMongoStorage().getFactionsCollection(); + collection.deleteMany(new Document()); + + for (Faction faction : factions) { + Document document = new Document() + .append("name", faction.getName()) + .append("leader", faction.getLeader()) + .append("members", faction.getMembers()) + .append("captains", faction.getCaptains()) + .append("date-created", faction.getDateCreated()) + .append("elo", faction.getElo()) + .append("wins", faction.getWins()) + .append("losses", faction.getLosses()) + .append("winStreak", faction.getWinStreak()) + .append("faction_chat_enabled", faction.isFactionChat()); + + if (faction.getDescription() != null) { + document.append("description", faction.getDescription()); + } + if (faction.getPassword() != null) { + document.append("password", faction.getPassword()); + } + + collection.insertOne(document); + } + } + + public void loadPlayerFaction(Player player) { + MongoCollection collection = this.plugin.getMongoStorage().getFactionsPlayersCollection(); + Document document = collection.find(Filters.eq("uuid", player.getUniqueId().toString())).first(); + + if (document != null) { + FactionProfile factionProfile = this.getProfile(player); + Faction faction = this.getFaction(document.getString("faction")); + + factionProfile.setFaction(faction); + } + } + + public void savePlayerFaction(Player player) { + MongoCollection collection = this.plugin.getMongoStorage().getFactionsPlayersCollection(); + String uuid = player.getUniqueId().toString(); + + FactionProfile factionProfile = this.getProfile(player); + + if (factionProfile == null) { + collection.deleteOne(Filters.eq("uuid", uuid)); + } else { + Document document = new Document("uuid", uuid) + .append("faction", factionProfile.getFaction().getName()); + collection.replaceOne(Filters.eq("uuid", uuid), document, new ReplaceOptions().upsert(true)); + } + } + + public Faction getFaction(String name) { + return factions.stream().filter(faction -> faction.getName().equalsIgnoreCase(name)).findFirst().orElse(null); + } + + public void addPlayer(Player player) { + factionProfileMap.put(player.getUniqueId(), new FactionProfile()); + } + + public void removePlayer(Player player) { + factionProfileMap.remove(player.getUniqueId()); + } + + public FactionProfile getProfile(Player player) { + return factionProfileMap.get(player.getUniqueId()); + } + public boolean hasProfile(Player player) { + return factionProfileMap.containsKey(player.getUniqueId()); + } + + public void broadcastToFactions(String message, String server) { + for (Faction faction : factions) { + faction.broadcast(CC.DARK_GREEN + "(Faction) " + message + " " + server); + } + } + + public void broadcastToFactionsChat(String displayName, String message, String server) { + for (Faction faction : factions) { + faction.broadcast(CC.DARK_GREEN + "(Faction) " + CC.GOLD + " [" + server + "] " + displayName + CC.GRAY + " : " + CC.R + message); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/member/FactionMember.java b/LandCore/src/main/java/me/devkevin/landcore/faction/member/FactionMember.java new file mode 100644 index 0000000..c60114e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/member/FactionMember.java @@ -0,0 +1,20 @@ +package me.devkevin.landcore.faction.member; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 0:39 + * FactionMember / me.devkevin.landcore.faction.member / LandCore + */ +@Getter +@Setter +@AllArgsConstructor +public class FactionMember { + private final UUID uuid; + private final FactionMemberType type; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/member/FactionMemberType.java b/LandCore/src/main/java/me/devkevin/landcore/faction/member/FactionMemberType.java new file mode 100644 index 0000000..84a9fd9 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/member/FactionMemberType.java @@ -0,0 +1,20 @@ +package me.devkevin.landcore.faction.member; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 0:40 + * FactionMemberType / me.devkevin.landcore.faction.member / LandCore + */ +@Getter +@AllArgsConstructor +public enum FactionMemberType { + LEADER("Leader", 0), + CAPTAIN("Captain", 1), + MEMBER("Member", 2); + + private final String name; + private final int weight; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/faction/profile/FactionProfile.java b/LandCore/src/main/java/me/devkevin/landcore/faction/profile/FactionProfile.java new file mode 100644 index 0000000..a9dcd5b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/faction/profile/FactionProfile.java @@ -0,0 +1,21 @@ +package me.devkevin.landcore.faction.profile; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.faction.Faction; +import me.devkevin.landcore.faction.invite.FactionInvite; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 0:43 + * FactionProfile / me.devkevin.landcore.faction.profile / LandCore + */ +@Getter +@Setter +public class FactionProfile { + private Faction faction; + private List inviteList = new ArrayList<>(); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory.java b/LandCore/src/main/java/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory.java new file mode 100644 index 0000000..abad574 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory.java @@ -0,0 +1,77 @@ +package me.devkevin.landcore.gson; + +import com.google.common.base.Preconditions; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.utils.location.CustomLocation; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.io.IOException; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:15 + * CustomLocationTypeAdapterFactory / land.pvp.core.gson / LandCore + */ +public class CustomLocationTypeAdapterFactory implements TypeAdapterFactory { + + public static LocationData serialize(CustomLocation customLocation) { + Preconditions.checkNotNull(customLocation); + + return new LocationData(customLocation.getWorld(), customLocation.getX(), customLocation.getY(), + customLocation.getZ(), customLocation.getYaw(), customLocation.getPitch()); + } + + public static CustomLocation deserialize(LocationData locationData) { + Preconditions.checkNotNull(locationData); + + return new CustomLocation(locationData.getWorld(), locationData.getX(), locationData.getY(), locationData + .getZ(), locationData.getYaw(), locationData.getPitch()); + } + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + if (!CustomLocation.class.isAssignableFrom(typeToken.getRawType())) { + return null; + } + + return new TypeAdapter() { + @Override + public void write(JsonWriter jsonWriter, T location) throws IOException { + if (location == null) { + jsonWriter.nullValue(); + } else { + LandCore.GSON.toJson(serialize((CustomLocation) location), LocationData.class, jsonWriter); + } + } + + @Override + public T read(JsonReader jsonReader) throws IOException { + if (jsonReader.peek() == null) { + jsonReader.nextNull(); + return null; + } else { + return (T) deserialize(LandCore.GSON.fromJson(jsonReader, LocationData.class)); + } + } + }; + } + + @Getter + @RequiredArgsConstructor + private static class LocationData { + + private final String world; + private final double x; + private final double y; + private final double z; + private final float yaw; + private final float pitch; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory.java b/LandCore/src/main/java/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory.java new file mode 100644 index 0000000..1143b68 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory.java @@ -0,0 +1,175 @@ +package me.devkevin.landcore.gson; + +import com.google.common.base.Preconditions; +import com.google.gson.Gson; +import com.google.gson.TypeAdapter; +import com.google.gson.TypeAdapterFactory; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.gson.item.EnchantType; +import me.devkevin.landcore.gson.item.ItemMetaType; +import me.devkevin.landcore.gson.item.ItemType; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.*; +import org.bukkit.potion.PotionEffect; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:15 + * ItemStackTypeAdapterFactory / land.pvp.core.gson / LandCore + */ +public class ItemStackTypeAdapterFactory implements TypeAdapterFactory { + + public static ItemType serializeItem(ItemStack itemStack) { + Preconditions.checkNotNull(itemStack); + + ItemType item; + ItemMeta itemStackMeta; + ItemMetaType itemMeta = null; + List itemEnchants = null; + + if (itemStack.hasItemMeta()) { + itemStackMeta = itemStack.getItemMeta(); + itemMeta = new ItemMetaType(); + + if (itemStackMeta.hasDisplayName()) { + itemMeta.setDisplayName(itemStackMeta.getDisplayName()); + } + + if (itemStackMeta.hasLore()) { + itemMeta.setLore(itemStackMeta.getLore()); + } + + if (itemStackMeta instanceof EnchantmentStorageMeta) { + EnchantmentStorageMeta esm = (EnchantmentStorageMeta) itemStackMeta; + if (esm.hasStoredEnchants()) { + List storedEnchants = new ArrayList<>(); + for (Map.Entry entry : esm.getStoredEnchants().entrySet()) { + storedEnchants.add(new EnchantType(entry.getKey().getName(), entry.getValue())); + } + itemMeta.setStoredEnchants(storedEnchants); + } + } + + if (itemStackMeta instanceof Repairable) { + itemMeta.setRepairCost(((Repairable) itemStackMeta).getRepairCost()); + } + + if (itemStackMeta instanceof LeatherArmorMeta) { + itemMeta.setLeatherArmorColor(((LeatherArmorMeta) itemStackMeta).getColor().asRGB()); + } + + if (itemStackMeta instanceof PotionMeta) { + PotionMeta potionMeta = (PotionMeta) itemStackMeta; + if (potionMeta.hasCustomEffects()) { + List potionEffects = new ArrayList<>(); + potionEffects.addAll(potionMeta.getCustomEffects()); + itemMeta.setPotionEffects(potionEffects); + } + } + } + + for (Map.Entry e : itemStack.getEnchantments().entrySet()) { + if (itemEnchants == null) { + itemEnchants = new ArrayList<>(); + } + itemEnchants.add(new EnchantType(e.getKey().getName(), e.getValue())); + } + + item = new ItemType(itemStack.getType().toString(), itemStack.getDurability(), itemStack.getAmount(), + itemEnchants, itemMeta); + + return item; + } + + public static ItemStack deserializeItem(ItemType item) { + Preconditions.checkNotNull(item); + + ItemStack itemStack = new ItemStack(Material.matchMaterial(item.getType()), item.getAmount()); + ItemMeta itemMeta = itemStack.getItemMeta(); + + itemStack.setDurability(item.getDurability()); + + if (item.getEnchants() != null) { + for (EnchantType enchant : item.getEnchants()) { + itemMeta.addEnchant(Enchantment.getByName(enchant.getType()), enchant.getTier(), true); + } + } + + if (item.getMeta() != null) { + if (item.getMeta().getDisplayName() != null) { + itemMeta.setDisplayName(item.getMeta().getDisplayName()); + } + + if (item.getMeta().getLore() != null) { + itemMeta.setLore(item.getMeta().getLore()); + } + + if (itemMeta instanceof EnchantmentStorageMeta && item.getMeta().getStoredEnchants() != null) { + EnchantmentStorageMeta esm = (EnchantmentStorageMeta) itemMeta; + for (EnchantType enchant : item.getMeta().getStoredEnchants()) { + esm.addStoredEnchant(Enchantment.getByName(enchant.getType()), enchant.getTier(), true); + } + } + + if (itemMeta instanceof Repairable && item.getMeta().getRepairCost() != null) { + ((Repairable) itemMeta).setRepairCost(item.getMeta().getRepairCost()); + } + + if (itemMeta instanceof LeatherArmorMeta && item.getMeta().getLeatherArmorColor() != null) { + ((LeatherArmorMeta) itemMeta).setColor(Color.fromRGB(item.getMeta().getLeatherArmorColor())); + } + + if (itemMeta instanceof PotionMeta && item.getMeta().getPotionEffects() != null) { + PotionMeta potionMeta = (PotionMeta) itemMeta; + for (PotionEffect effect : item.getMeta().getPotionEffects()) { + potionMeta.addCustomEffect(effect, true); + } + } + } + + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + + @Override + public TypeAdapter create(Gson gson, TypeToken type) { + if (!ItemStack.class.isAssignableFrom(type.getRawType())) { + return null; + } + + return new TypeAdapter() { + + @Override + public void write(JsonWriter writer, T item) throws IOException { + if (item == null) { + writer.nullValue(); + } else { + LandCore.GSON.toJson(serializeItem((ItemStack) item), ItemType.class, writer); + } + } + + @Override + public T read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } else { + return (T) deserializeItem(LandCore.GSON.fromJson(reader, ItemType.class)); + } + } + }; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/gson/item/EnchantType.java b/LandCore/src/main/java/me/devkevin/landcore/gson/item/EnchantType.java new file mode 100644 index 0000000..23d7ffc --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/gson/item/EnchantType.java @@ -0,0 +1,16 @@ +package me.devkevin.landcore.gson.item; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:17 + * EnchantType / land.pvp.core.gson.item / LandCore + */ +@Getter +@RequiredArgsConstructor +public class EnchantType { + private final String type; + private final int tier; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/gson/item/ItemMetaType.java b/LandCore/src/main/java/me/devkevin/landcore/gson/item/ItemMetaType.java new file mode 100644 index 0000000..2b117ec --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/gson/item/ItemMetaType.java @@ -0,0 +1,23 @@ +package me.devkevin.landcore.gson.item; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.potion.PotionEffect; + +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:17 + * ItemMetaType / land.pvp.core.gson.item / LandCore + */ +@Getter +@Setter +public class ItemMetaType { + private String displayName; + private List lore; + private List storedEnchants; + private Integer repairCost; + private Integer leatherArmorColor; + private List potionEffects; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/gson/item/ItemType.java b/LandCore/src/main/java/me/devkevin/landcore/gson/item/ItemType.java new file mode 100644 index 0000000..446b849 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/gson/item/ItemType.java @@ -0,0 +1,22 @@ +package me.devkevin.landcore.gson.item; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:17 + * ItemType / land.pvp.core.gson.item / LandCore + */ +@Getter +@RequiredArgsConstructor +public class ItemType { + + private final String type; + private final short durability; + private final int amount; + private final List enchants; + private final ItemMetaType meta; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/gson/item/PotionEffectType.java b/LandCore/src/main/java/me/devkevin/landcore/gson/item/PotionEffectType.java new file mode 100644 index 0000000..0ef036f --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/gson/item/PotionEffectType.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.gson.item; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 15:18 + * PotionEffectType / land.pvp.core.gson.item / LandCore + */ +@Getter +@RequiredArgsConstructor +public class PotionEffectType { + private final String type; + private final int duration; + private final int amplifier; +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/handler/PacketListener.java b/LandCore/src/main/java/me/devkevin/landcore/handler/PacketListener.java new file mode 100644 index 0000000..06408c0 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/handler/PacketListener.java @@ -0,0 +1,118 @@ +package me.devkevin.landcore.handler; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.location.CustomLocation; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import xyz.refinedev.spigot.api.handlers.impl.PacketHandler; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 17:51 + * PacketListener / me.devkevin.landcore.handler / LandCore + */ +public abstract class PacketListener implements PacketHandler { + /*@Override + public void handleReceivedPacket(PlayerConnection playerConnection, Packet packet) { + Player player = playerConnection.getPlayer(); + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if ("PacketPlayInFlying".equals(packet.getClass().getSimpleName())) { + handleFlyPacket((PacketPlayInFlying) packet, coreProfile); + } + } + + @Override + public void handleSentPacket(PlayerConnection playerConnection, Packet packet) { + Player player = playerConnection.getPlayer(); + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + switch (packet.getClass().getSimpleName()) { + case "PacketPlayOutEntityTeleport": { + this.handleTeleportPacket((PacketPlayOutEntityTeleport) packet, coreProfile, player); + break; + } + case "PacketPlayOutEntityLook": + case "PacketPlayOutRelEntityMove": + case "PacketPlayOutRelEntityMoveLook": + case "PacketPlayOutEntity": { + this.handleEntityPacket((PacketPlayOutEntity) packet, coreProfile, player); + break; + } + } + } + + private void handleTeleportPacket(PacketPlayOutEntityTeleport packet, CoreProfile coreProfile, final Player player) { + final Entity targetEntity = ((CraftPlayer) player).getHandle().getWorld().a(packet.getA()); + if (targetEntity instanceof EntityPlayer) { + Player target = (Player) targetEntity.getBukkitEntity(); + double x = packet.getB() / 32.0; + double y = packet.getC() / 32.0; + double z = packet.getD() / 32.0; + float yaw = packet.getE() * 360.0f / 256.0f; + float pitch = packet.getF() * 360.0f / 256.0f; + if (coreProfile.getMisplace() != 0.0) { + CustomLocation lastLocation = coreProfile.getLastMovePacket(); + float entityYaw = this.getAngle(x, z, lastLocation); + double addX = Math.cos(Math.toRadians(entityYaw + 90.0f)) * coreProfile.getMisplace(); + double addZ = Math.sin(Math.toRadians(entityYaw + 90.0f)) * coreProfile.getMisplace(); + x -= addX; + z -= addZ; + packet.setB(MathHelper.floor(x * 32.0)); + packet.setD(MathHelper.floor(z * 32.0)); + } + coreProfile.addPlayerPacket(target.getUniqueId(), new CustomLocation(x, y, z, yaw, pitch)); + } + } + + private void handleEntityPacket(final PacketPlayOutEntity packet, final CoreProfile coreProfile, final Player player) { + final Entity targetEntity = ((CraftPlayer) player).getHandle().getWorld().a(packet.getA()); + if (targetEntity instanceof EntityPlayer) { + final Player target = (Player) targetEntity.getBukkitEntity(); + final CustomLocation customLocation = coreProfile.getLastPlayerPacket(target.getUniqueId(), 1); + if (customLocation != null) { + final double x = packet.getB() / 32.0; + final double y = packet.getC() / 32.0; + final double z = packet.getD() / 32.0; + float yaw = packet.getE() * 360.0f / 256.0f; + float pitch = packet.getF() * 360.0f / 256.0f; + if (!packet.isH()) { + yaw = customLocation.getYaw(); + pitch = customLocation.getPitch(); + } + coreProfile.addPlayerPacket(target.getUniqueId(), new CustomLocation(customLocation.getX() + x, customLocation.getY() + y, customLocation.getZ() + z, yaw, pitch)); + } + } + } + + private void handleFlyPacket(final PacketPlayInFlying packet, final CoreProfile coreProfile) { + final CustomLocation customLocation = new CustomLocation(packet.a(), packet.b(), packet.c(), packet.d(), packet.e()); + final CustomLocation lastLocation = coreProfile.getLastMovePacket(); + if (lastLocation != null) { + if (!packet.g()) { + customLocation.setX(lastLocation.getX()); + customLocation.setY(lastLocation.getY()); + customLocation.setZ(lastLocation.getZ()); + } + if (!packet.h()) { + customLocation.setYaw(lastLocation.getYaw()); + customLocation.setPitch(lastLocation.getPitch()); + } + } + coreProfile.setLastMovePacket(customLocation); + } + + private float getAngle(final double posX, final double posZ, final CustomLocation location) { + final double x = posX - location.getX(); + final double z = posZ - location.getZ(); + float newYaw = (float) Math.toDegrees(-Math.atan(x / z)); + if (z < 0.0 && x < 0.0) { + newYaw = (float) (90.0 + Math.toDegrees(Math.atan(z / x))); + } else if (z < 0.0 && x > 0.0) { + newYaw = (float) (-90.0 + Math.toDegrees(Math.atan(z / x))); + } + return newYaw; + }*/ +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/Menu.java b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/Menu.java new file mode 100644 index 0000000..ceacfe5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/Menu.java @@ -0,0 +1,63 @@ +package me.devkevin.landcore.inventory.menu; + +import me.devkevin.landcore.inventory.menu.action.Action; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class Menu { + @Getter + private final Inventory inventory; + private final Map actions = new HashMap<>(); + private final List pages = new ArrayList<>(); + + protected Menu(int rows, String name) { + inventory = Bukkit.createInventory(null, 9 * rows, name); + } + + protected void setItem(int slot, ItemStack item) { + inventory.setItem(slot, item); + } + + protected void setActionableItem(int slot, ItemStack item, Action action) { + inventory.setItem(slot, item); + actions.put(slot, action); + } + + protected ItemStack getItem(int slot) { + return inventory.getItem(slot); + } + + public Action getAction(int slot) { + return actions.get(slot); + } + + public void open(Player player) { + player.openInventory(inventory); + } + + public void addPage(Menu page) { + pages.add(page); + } + + public Menu getPage(int index) { + return pages.get(index); + } + + protected void clear() { + actions.clear(); + pages.clear(); + inventory.clear(); + } + + public abstract void setup(); + + public abstract void update(); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/action/Action.java b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/action/Action.java new file mode 100644 index 0000000..dfc2ac8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/action/Action.java @@ -0,0 +1,7 @@ +package me.devkevin.landcore.inventory.menu.action; + +import org.bukkit.entity.Player; + +public interface Action { + void onClick(Player player); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/impl/PerPlayerMenu.java b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/impl/PerPlayerMenu.java new file mode 100644 index 0000000..2f6d7d3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/impl/PerPlayerMenu.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.inventory.menu.impl; + +import me.devkevin.landcore.inventory.menu.Menu; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; + +public abstract class PerPlayerMenu extends Menu { + protected PerPlayerMenu(int rows, String name) { + super(rows, name); + } + + @Override + public final void update() { + for (HumanEntity entity : getInventory().getViewers()) { + Player player = (Player) entity; + updatePlayer(player); + player.updateInventory(); + } + } + + @Override + public final void open(Player player) { + super.open(player); + updatePlayer(player); + } + + public abstract void updatePlayer(Player player); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/impl/ReportMenu.java b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/impl/ReportMenu.java new file mode 100644 index 0000000..4ab59a0 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/inventory/menu/impl/ReportMenu.java @@ -0,0 +1,64 @@ +package me.devkevin.landcore.inventory.menu.impl; + +import com.google.common.collect.Maps; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.inventory.menu.Menu; +import me.devkevin.landcore.inventory.menu.action.Action; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.timer.Timer; +import org.bukkit.Material; + +import java.util.Map; + +public class ReportMenu extends Menu { + private final LandCore plugin; + + public ReportMenu(LandCore plugin) { + super(1, "Select a Report Reason"); + this.plugin = plugin; + } + + private Action getAction(String reason) { + return player -> { + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + Timer cooldownTimer = profile.getReportCooldownTimer(); + + if (cooldownTimer.isActive()) { + player.sendMessage(CC.RED + "You can't report a player for another " + cooldownTimer.formattedExpiration() + "."); + player.closeInventory(); + return; + } + + String targetName = profile.getReportingPlayerName(); + + Map reportInformation = Maps.newHashMap(); + + reportInformation.put("server", plugin.getServerName()); + reportInformation.put("reporter", player.getName()); + reportInformation.put("reported", targetName); + reportInformation.put("reason", reason); + + plugin.getStaffManager().messageStaff(""); + plugin.getRedisMessenger().send("report", reportInformation); + plugin.getStaffManager().messageStaff(""); + + player.sendMessage(CC.GREEN + "Report sent for " + targetName + CC.GREEN + ": " + CC.R + reason); + + player.closeInventory(); + }; + } + + @Override + public void setup() { + } + + @Override + public void update() { + setActionableItem(1, new ItemBuilder(Material.DIAMOND_SWORD).name(CC.PRIMARY + "Combat Cheats").build(), getAction("Combat Cheats")); + setActionableItem(3, new ItemBuilder(Material.DIAMOND_BOOTS).name(CC.PRIMARY + "Movement Cheats").build(), getAction("Movement Cheats")); + setActionableItem(5, new ItemBuilder(Material.PAPER).name(CC.PRIMARY + "Chat Violation").build(), getAction("Chat Violation")); + setActionableItem(7, new ItemBuilder(Material.NETHER_STAR).name(CC.PRIMARY + "Assistance").build(), getAction("I need assistance related to this player")); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/HelpCommandListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/HelpCommandListener.java new file mode 100644 index 0000000..81daa1a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/HelpCommandListener.java @@ -0,0 +1,41 @@ +package me.devkevin.landcore.listeners; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 12:49 + * HelpCommandListener / land.pvp.core.listeners / LandCore + */ +@RequiredArgsConstructor +public class HelpCommandListener implements Listener { + private final LandCore plugin; + + // Commands we don't want players to be able to run(and or, display the help message for). + private static final String[] DISALLOWED_COMMANDS = { + "?", + "help", + "version", + "ver", + "bukkit" + }; + + @EventHandler + public void onHelpCommand(PlayerCommandPreprocessEvent event) { + CoreProfile coreProfile = plugin.getProfileManager().getProfile(event.getPlayer().getUniqueId()); + + boolean staff = coreProfile.hasStaff(); + + for (String command : DISALLOWED_COMMANDS) { + if (event.getMessage().startsWith("/" + command) && !staff) { + event.getPlayer().sendMessage(CC.RED + "If you need help, require assistance by using /helpop."); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/InventoryListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/InventoryListener.java new file mode 100644 index 0000000..1249e93 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/InventoryListener.java @@ -0,0 +1,52 @@ +package me.devkevin.landcore.listeners; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.inventory.menu.Menu; +import me.devkevin.landcore.inventory.menu.action.Action; +import me.devkevin.landcore.player.CoreProfile; +import lombok.RequiredArgsConstructor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; + +@RequiredArgsConstructor +public class InventoryListener implements Listener { + private final LandCore plugin; + + @EventHandler + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + + if (player.getGameMode() != GameMode.SURVIVAL || event.getClickedInventory() == null + || event.getClickedInventory() == player.getInventory() || event.getCurrentItem() == null + || event.getCurrentItem().getType() == Material.AIR) { + return; + } + + Menu menu = plugin.getMenuManager().getMatchingMenu(event.getClickedInventory()); + + if (menu != null) { + Action action = menu.getAction(event.getSlot()); + + if (action != null) { + event.setCancelled(true); + action.onClick(player); + } + } + } + + @EventHandler + public void onClose(InventoryCloseEvent event) { + Player player = (Player) event.getPlayer(); + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (profile != null && profile.getReportingPlayerName() != null) { + profile.setReportingPlayerName(null); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/MenuListeners.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/MenuListeners.java new file mode 100644 index 0000000..556097a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/MenuListeners.java @@ -0,0 +1,71 @@ +package me.devkevin.landcore.listeners; + +import me.devkevin.landcore.utils.Menu; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.inventory.Inventory; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/01/2023 @ 14:15 + * MenuListeners / me.devkevin.landcore.listeners / LandCore + */ +public class MenuListeners implements Listener { + + @EventHandler + public void onInventoryGrantClickFix(InventoryClickEvent event) { + Inventory inv = event.getClickedInventory(); + + if (inv.getTitle().equalsIgnoreCase(CC.translate("&aAre you sure?")) + || inv.getTitle().equalsIgnoreCase(CC.PRIMARY + "Please select a duration") + || inv.getTitle().equalsIgnoreCase(CC.PRIMARY + "Please select a reason") + || inv.getTitle().equalsIgnoreCase(CC.PRIMARY + "Please select a rank") + + || inv.getTitle().equalsIgnoreCase(CC.PRIMARY + "Viewing grants..") + || inv.getTitle().equalsIgnoreCase(CC.PRIMARY + "Please select a player") + || inv.getTitle().equalsIgnoreCase(CC.PRIMARY + "Rank List")) { + event.setCancelled(false); + } + } + + @EventHandler(ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Menu menu = Menu.getByUuid(player.getUniqueId()); + + if(!event.isCancelled() && menu != null) { + event.setCancelled(true); + + if(event.getClickedInventory() != null && event.getClickedInventory().getTitle().equals(menu.getInventory().getTitle())) { + if(event.getCurrentItem() == null || event.getCurrentItem().getType() == Material.AIR) { + return; + } + + menu.onClickItem(player, event.getCurrentItem(), event.isRightClick()); + + if (menu.isUpdateOnClick() && menu.getPlayer() != null && menu.getInventory() != null) { + menu.updateInventory(player); + } + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onInventoryClose(InventoryCloseEvent event) { + Player player = (Player) event.getPlayer(); + Menu menu = Menu.getByUuid(player.getUniqueId()); + + if (menu != null) { + if(event.getInventory().getTitle().equals(menu.getInventory().getTitle())) { + menu.onClose(); + } + + menu.destroy(); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/MessageListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/MessageListener.java new file mode 100644 index 0000000..9602968 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/MessageListener.java @@ -0,0 +1,66 @@ +package me.devkevin.landcore.listeners; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.event.player.PlayerMessageEvent; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +@RequiredArgsConstructor +public class MessageListener implements Listener { + private final LandCore plugin; + + private static void sendMessage(CoreProfile sender, CoreProfile receiver, Player player, String msg) { + receiver.setConverser(sender.getId()); + player.sendMessage(msg); + } + + @EventHandler + public void onMessage(PlayerMessageEvent event) { + Player sender = event.getPlayer(); + CoreProfile senderProfile = plugin.getProfileManager().getProfile(sender.getUniqueId()); + + if (!senderProfile.isMessaging() && !senderProfile.hasStaff()) { + sender.sendMessage(CC.RED + "You have messaging disabled."); + return; + } + + Player receiver = event.getReceiver(); + CoreProfile receiverProfile = plugin.getProfileManager().getProfile(receiver.getUniqueId()); + + if (senderProfile.hasStaff()) { + // NO-OP + } else if (!receiverProfile.isMessaging()) { + sender.sendMessage(CC.RED + receiver.getName() + " has messaging disabled."); + return; + } + + String toMsg = CC.GRAY + "(To " + receiverProfile.getChatFormat() + CC.GRAY + ") " + event.getMessage(); + String fromMsg = CC.GRAY + "(From " + senderProfile.getChatFormat() + CC.GRAY + ") " + event.getMessage(); +// +// if (plugin.getFilter().isFiltered(event.getMessage())) { +// if (senderProfile.hasStaff()) { +// sender.sendMessage(CC.RED + "That would have been filtered."); +// } else { +// String filteredMessage = CC.GRAY + "(" + sender.getDisplayName() +// + CC.GRAY + " -> " + receiver.getDisplayName() + CC.GRAY + ") " + event.getMessage(); +// +// plugin.getStaffManager().messageStaff(CC.RED + "(Filtered) " + filteredMessage); +// sender.sendMessage(toMsg); +// return; +// } +// } + // TODO: message-specific filter + + sendMessage(senderProfile, receiverProfile, receiver, fromMsg); + sendMessage(receiverProfile, senderProfile, sender, toMsg); + + if (receiverProfile.isPlayingSounds()) { + receiver.playSound(receiver.getLocation(), Sound.NOTE_PLING, 1.0F, 2.0F); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerInteractListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerInteractListener.java new file mode 100644 index 0000000..2cf55d2 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerInteractListener.java @@ -0,0 +1,44 @@ +package me.devkevin.landcore.listeners; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.SkullType; +import org.bukkit.block.Block; +import org.bukkit.block.Skull; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 18/01/2023 @ 13:59 + * PlayerInteractListener / land.pvp.core.listeners / LandCore + */ +@RequiredArgsConstructor +public class PlayerInteractListener implements Listener { + private final LandCore plugin; + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Block block = event.getClickedBlock(); + if (block.getState() instanceof Skull) { + Skull skull = (Skull) block.getState(); + if (skull.getSkullType() != SkullType.PLAYER) + return; + + if (skull.getOwner() == null) { + player.sendMessage(CC.GOLD + "This is the head of: " + CC.WHITE + "Steve"); + return; + } + + player.sendMessage(CC.GOLD + "This is the head of: " + CC.WHITE + skull.getOwner()); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerListener.java new file mode 100644 index 0000000..daf06f2 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerListener.java @@ -0,0 +1,406 @@ +package me.devkevin.landcore.listeners; + +import com.google.common.collect.Maps; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.event.player.PlayerRankChangeEvent; +import me.devkevin.landcore.faction.profile.FactionProfile; +import me.devkevin.landcore.nametag.impl.InternalNametag; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.Grant; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.server.ServerSettings; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import me.devkevin.landcore.utils.time.TimeUtil; +import me.devkevin.landcore.utils.timer.Timer; +import lombok.RequiredArgsConstructor; +import net.minecraft.server.v1_8_R3.PlayerList; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +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.EntityDamageByEntityEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.player.*; +import org.bukkit.permissions.PermissionAttachment; +import xyz.haoshoku.nick.api.NickAPI; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +@RequiredArgsConstructor +public class PlayerListener implements Listener { + private static final String[] DISALLOWED_PERMISSIONS = { + "bukkit.command.version", "bukkit.command.plugins", "bukkit.command.help", "bukkit.command.tps", + "minecraft.command.tell", "minecraft.command.me", "minecraft.command.help" + }; + private final LandCore plugin; + + private void handleBan(AsyncPlayerPreLoginEvent event, Punishment punishment) { + event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER); + event.setKickMessage(punishment.getKickMessage()); + } + + @EventHandler(priority = EventPriority.LOW) + public void onPreLogin(AsyncPlayerPreLoginEvent event) { + if (plugin.getPlayerManager().isNameOnline(event.getName()) || plugin.getPlayerManager().getOnlineByIp(event.getAddress()) > 3) { + event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, CC.RED + "You're already online!"); + } else if (event.getLoginResult() == AsyncPlayerPreLoginEvent.Result.ALLOWED) { + CoreProfile profile = plugin.getProfileManager().createProfile(event.getName(), event.getUniqueId(), event.getAddress().getHostAddress()); + ServerSettings serverSettings = plugin.getServerSettings(); + + if (serverSettings.getServerWhitelistMode().isProfileIneligible(profile)) { + event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_WHITELIST, serverSettings.getWhitelistMessage()); + return; + } + + if (profile.getActiveBan() != null) { + handleBan(event, profile.getActiveBan()); + } + + if (profile.getCurrentAddress() == null) { + profile.setCurrentAddress(event.getAddress().getHostAddress()); + } + + if (!profile.getIpAddresses().contains(event.getAddress().getHostAddress())) { + profile.getIpAddresses().add(event.getAddress().getHostAddress()); + } + + if (!profile.getCurrentAddress().equals(event.getAddress().getHostAddress())) { + List alts = CoreProfile.getByIpAddress(event.getAddress().getHostAddress()); + + for (CoreProfile alt : alts) { + if (alt.getActiveBan() != null) { + handleBan(event, alt.getActiveBan()); + return; + } + } + } + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onLogin(PlayerLoginEvent event) { + Player player = event.getPlayer(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (profile == null) { + event.disallow(PlayerLoginEvent.Result.KICK_OTHER, Messages.DATA_LOAD_FAIL); + return; + } else if (event.getResult() != PlayerLoginEvent.Result.ALLOWED) { + plugin.getProfileManager().removeProfile(player.getUniqueId()); + return; + } + + PermissionAttachment attachment = player.addAttachment(plugin); + + if (!profile.hasRank(Rank.ADMIN)) { + for (String permission : DISALLOWED_PERMISSIONS) { + attachment.setPermission(permission, false); + } + } + + profile.getRank().apply(player); + + if (profile.hasStaff()) { + plugin.getStaffManager().addCachedStaff(profile); + } + } + + @EventHandler + public void onJoin(PlayerJoinEvent event) { + event.setJoinMessage(null); + + Player player = event.getPlayer(); + + plugin.getPlayerManager().addPlayer(player); + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + plugin.getStaffManager().hideVanishedStaffFromPlayer(player); + + if (profile.hasStaff()) { + Map message = Maps.newHashMap(); + message.put("server", plugin.getServerName()); + message.put("sender", profile.getRank().getColor() + player.getName()); + + plugin.getRedisMessenger().send("staff-join", message); + } + } + + private void onDisconnect(Player player) { + plugin.getPlayerManager().removePlayer(player); + + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + // in case disconnect is somehow called twice + if (profile == null) { + return; + } + + if (profile.isFrozen()) { + Map message = Maps.newHashMap(); + + message.put("server", plugin.getServerName()); + message.put("sender", profile.getRank().getColor() + player.getName()); + + plugin.getRedisMessenger().send("frozen-disconnect", message); + } + + if (profile.hasStaff()) { + plugin.getStaffManager().removeCachedStaff(profile); + + Map message = Maps.newHashMap(); + message.put("server", plugin.getServerName()); + message.put("sender", profile.getRank().getColor() + player.getName()); + + plugin.getRedisMessenger().send("staff-left", message); + } + + profile.save(true); + plugin.getProfileManager().removeProfile(player.getUniqueId()); + + Bukkit.getScheduler().runTask(this.plugin, () -> { + PlayerList playerList = ((CraftServer) Bukkit.getServer()).getHandle(); + playerList.disconnect(((CraftPlayer) player).getHandle()); + }); + } + + @EventHandler + public void onKick(PlayerKickEvent event) { + event.setLeaveMessage(null); + + onDisconnect(event.getPlayer()); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + event.setQuitMessage(null); + + onDisconnect(event.getPlayer()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + String msg = event.getMessage(); + + Punishment punishment = profile.getActiveMute(); + + if (!profile.hasStaff()) { + if (plugin.getServerSettings().isGlobalChatMuted()) { + event.setCancelled(true); + player.sendMessage(CC.RED + "Global chat is currently muted."); + return; + } else if (punishment != null) { + event.setCancelled(true); + + player.sendMessage(CC.RED + "You are currently muted."); + player.sendMessage(CC.RED + "Reason: " + CC.YELLOW + punishment.getAddedReason()); + player.sendMessage(CC.RED + "Expires: " + CC.YELLOW + punishment.getTimeRemaining()); + return; + } else if (plugin.getServerSettings().getSlowChatTime() != -1) { + long lastChatTime = profile.getLastChatTime(); + int slowChatTime = plugin.getServerSettings().getSlowChatTime(); + long sum = lastChatTime + (slowChatTime * 1000L); + + if (lastChatTime != 0 && sum > System.currentTimeMillis()) { + event.setCancelled(true); + String diff = TimeUtil.formatTimeMillis(sum - System.currentTimeMillis()); + player.sendMessage(CC.RED + "Slow chat is currently enabled. You can talk again in " + diff + "."); + return; + } + } + + Timer timer = profile.getChatCooldownTimer(); + + if (timer.isActive()) { + event.setCancelled(true); + player.sendMessage(CC.RED + "You can't chat for another " + timer.formattedExpiration() + "."); + return; + } + + } else if (profile.isInStaffChat()) { + event.setCancelled(true); + + Map message = Maps.newHashMap(); + + message.put("server", plugin.getServerName()); + message.put("format", profile.getRank().getColor() + player.getName()); + message.put("message", event.getMessage()); + message.put("sender", event.getPlayer().getName()); + + plugin.getRedisMessenger().send("staff-chat", message); + return; + } + + if (plugin.getFilter().isFiltered(msg)) { + if (profile.hasStaff()) { + player.sendMessage(CC.RED + "That would have been filtered."); + } else { + event.setCancelled(true); + + String formattedMessage = profile.getChatFormat() + CC.R + ": " + msg; + + plugin.getStaffManager().messageStaff(CC.RED + "(Filtered) " + formattedMessage); + player.sendMessage(formattedMessage); + return; + } + } + + Iterator recipients = event.getRecipients().iterator(); + + while (recipients.hasNext()) { + Player recipient = recipients.next(); + CoreProfile recipientProfile = plugin.getProfileManager().getProfile(recipient.getUniqueId()); + + if (recipientProfile == null) { + continue; + } + + if (recipientProfile.hasPlayerIgnored(player.getUniqueId()) + || (!recipientProfile.isGlobalChatEnabled() && (!profile.hasStaff() || recipientProfile.hasStaff()))) { + recipients.remove(); + } else if (recipient != player) { + String[] words = msg.split(" "); + boolean found = false; + + StringBuilder newMessage = new StringBuilder(); + + for (String word : words) { + if (recipient.getName().equalsIgnoreCase(word) && !found) { + newMessage.append(CC.PINK).append(CC.I).append(word).append(CC.R).append(" "); + found = true; + } else { + newMessage.append(word).append(" "); + } + } + + if (!found) { + continue; + } + + if (recipientProfile.isPlayingSounds()) { + recipient.playSound(recipient.getLocation(), Sound.LEVEL_UP, 1.0F, 2.0F); + } + + String mentionMessage = profile.getChatFormat() + CC.R + ": " + newMessage; + + recipient.sendMessage(mentionMessage); + recipient.sendMessage(player.getDisplayName() + CC.PRIMARY + " mentioned you!"); + + recipients.remove(); + } + } + + if (NickAPI.isNicked(player)) { + event.setFormat(String.format(profile.getDisguiseRank().getRawFormat()) + profile.getDisguiseRank().getColor() + player.getName() + CC.R + ": %2$s"); + } else { + event.setFormat(profile.getChatFormat() + CC.R + ": %2$s"); + } + + profile.updateLastChatTime(); + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + Player player = event.getPlayer(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + + if (profile.hasStaff()) { + return; + } + + Timer timer = profile.getCommandCooldownTimer(); + + if (timer.isActive()) { + event.setCancelled(true); + player.sendMessage(CC.RED + "You can't use commands for another " + timer.formattedExpiration() + "."); + } + } + + @EventHandler + public void onRankChange(PlayerRankChangeEvent event) { + Player player = event.getPlayer(); + CoreProfile profile = event.getProfile(); + Grant newRank = event.getNewRank(); + + profile.getGrant().setRank(newRank.getRank()); + + if (profile.hasStaff()) { + if (!plugin.getStaffManager().isInStaffCache(profile)) { + plugin.getStaffManager().addCachedStaff(profile); + } + } else if (plugin.getStaffManager().isInStaffCache(profile)) { + plugin.getStaffManager().removeCachedStaff(profile); + } + + newRank.getRank().apply(player); + + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + + @EventHandler + public void onFreezeDamage(EntityDamageByEntityEvent e) { + if (e.getDamager() instanceof Player) { + Player player = (Player) e.getDamager(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + if (e.getEntity() instanceof Player && plugin.getProfileManager().getProfile(e.getEntity().getUniqueId()).isFrozen() || profile.isFrozen()) + e.setCancelled(true); + } + } + + @EventHandler + public void onFreezeCommand(PlayerCommandPreprocessEvent e) { + Player player = e.getPlayer(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + if (profile.isFrozen()) { + player.sendMessage(CC.RED + "You cannot run commands while you are frozen."); + e.setCancelled(true); + } + } + + @EventHandler + public void onFreezeInteract(PlayerInteractEvent e) { + Player player = e.getPlayer(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + if (profile.isFrozen()) { + e.setCancelled(true); + } + } + + @EventHandler + public void onFreezeSprint(PlayerToggleSprintEvent e) { + Player player = e.getPlayer(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + if (profile.isFrozen()) { + e.setCancelled(true); + } + } + + @EventHandler + public void onFoodLevelChange(FoodLevelChangeEvent e) { + if (!(e.getEntity() instanceof Player)) return; + Player player = (Player) e.getEntity(); + CoreProfile profile = plugin.getProfileManager().getProfile(player.getUniqueId()); + if (profile.isFrozen()) { + e.setCancelled(true); + } + } + + /*@EventHandler + public void onVelocity(PlayerVelocityEvent event) { + Player player = event.getPlayer(); + if (player.getUniqueId().toString().equalsIgnoreCase(LandCore.verzideUUID)) { + event.setVelocity(event.getVelocity().multiply(0.92).setY(event.getVelocity().getY())); + } + }*/ +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerPacketListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerPacketListener.java new file mode 100644 index 0000000..6241211 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/PlayerPacketListener.java @@ -0,0 +1,84 @@ +package me.devkevin.landcore.listeners; + +import me.devkevin.landcore.LandCoreAPI; +import me.devkevin.landcore.utils.packet.PacketInterceptor; +import me.devkevin.landcore.utils.packet.PacketListener; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.HashMap; +import java.util.UUID; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/03/2023 @ 12:26 + * PlayerPacketListener / me.devkevin.landcore.listeners / LandCore + */ +public class PlayerPacketListener extends LandCoreAPI.LandCoreListener { + + private final Executor INJECT_EXECUTOR = Executors.newSingleThreadExecutor(); + private final Executor EJECT_EXECUTOR = Executors.newSingleThreadExecutor(); + private final HashMap packetInterceptorHashMap; + + private final PacketListener packetListener; + + public PlayerPacketListener(JavaPlugin javaPlugin, PacketListener packetListener) { + super(javaPlugin); + this.packetListener = packetListener; + + packetInterceptorHashMap = new HashMap<>(); + } + + @EventHandler + public void onPlayerJoin(PlayerJoinEvent playerJoinEvent) { + + Player player = playerJoinEvent.getPlayer(); + + INJECT_EXECUTOR.execute(() -> { + PacketInterceptor interceptor = new PacketInterceptor(player, packetListener); + interceptor.attach(); + packetInterceptorHashMap.put(player.getUniqueId(), interceptor); + }); + + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent playerQuitEvent) { + + Player player = playerQuitEvent.getPlayer(); + + EJECT_EXECUTOR.execute(() -> { + if (packetInterceptorHashMap.containsKey(player.getUniqueId())) { + PacketInterceptor interceptor = packetInterceptorHashMap.get(player.getUniqueId()); + if (interceptor.isAttached()) { + interceptor.detach(); + } + packetInterceptorHashMap.remove(player.getUniqueId()); + } + }); + + } + + @EventHandler + public void onPlayerKick(PlayerKickEvent playerKickEvent) { + + Player player = playerKickEvent.getPlayer(); + + EJECT_EXECUTOR.execute(() -> { + if (packetInterceptorHashMap.containsKey(player.getUniqueId())) { + PacketInterceptor interceptor = packetInterceptorHashMap.get(player.getUniqueId()); + if (interceptor.isAttached()) { + interceptor.detach(); + } + packetInterceptorHashMap.remove(player.getUniqueId()); + } + }); + + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/FreezeListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/FreezeListener.java new file mode 100644 index 0000000..273a207 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/FreezeListener.java @@ -0,0 +1,29 @@ +package me.devkevin.landcore.listeners.redis; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 12:20 + * FreezeListener / land.pvp.core.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class FreezeListener { + private final LandCore plugin; + + @RedisHandler("freeze-listener") + public void onFreeze(Map map) { + String sender = (String) map.get("sender"); + String target = (String) map.get("frozen"); + String server = (String) map.get("server"); + + boolean frozen = Boolean.parseBoolean((String) map.get("isFrozen")); + + plugin.getStaffManager().messageStaffWithPrefix(CC.PRIMARY + sender + CC.SECONDARY + " has " + (frozen ? "frozen " : "unfrozen ") + target + ".", server); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/FrozenDisconnectListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/FrozenDisconnectListener.java new file mode 100644 index 0000000..d91ff53 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/FrozenDisconnectListener.java @@ -0,0 +1,23 @@ +package me.devkevin.landcore.listeners.redis; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 12:46 + * FrozenDisconnectListener / land.pvp.core.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class FrozenDisconnectListener { + private final LandCore plugin; + + @RedisHandler("frozen-disconnect") + public void onFrozenDisconnect(Map message) { + plugin.getStaffManager().messageStaffWithPrefix(message.get("sender") + CC.PRIMARY + " left the server while frozen.", (String) message.get("server")); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/HelpopListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/HelpopListener.java new file mode 100644 index 0000000..9e88b5c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/HelpopListener.java @@ -0,0 +1,27 @@ +package me.devkevin.landcore.listeners.redis; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 12:19 + * HelpopListener / land.pvp.core.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class HelpopListener { + private final LandCore plugin; + + @RedisHandler("help-op") + public void onHelpOp(Map map) { + String server = (String) map.get("server"); + String player = (String) map.get("player"); + String request = (String) map.get("request"); + plugin.getStaffManager().messageStaff(CC.RED + "\n(HelpOp) " + CC.D_AQUA + "[" + server + "] " + CC.SECONDARY + player + + CC.PRIMARY + " requested assistance: " + CC.SECONDARY + request + CC.PRIMARY + ".\n "); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/RedisFactionListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/RedisFactionListener.java new file mode 100644 index 0000000..2c179cf --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/RedisFactionListener.java @@ -0,0 +1,39 @@ +package me.devkevin.landcore.listeners.redis; + +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/03/2023 @ 14:27 + * FactionListener / me.devkevin.landcore.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class RedisFactionListener { + private final LandCore plugin; + + @RedisHandler("faction-join") + public void onFactionJoin(Map message) { + plugin.getFactionManager().broadcastToFactions(message.get("sender") + CC.GREEN + " has connected the ", (String) message.get("server")); + } + + @RedisHandler("faction-left") + public void onFactionLeft(Map message) { + plugin.getFactionManager().broadcastToFactions(message.get("sender") + CC.RED + " has left the server.", (String) message.get("server")); + } + + @RedisHandler("faction-chat") + public void onFactionChat(Map message) { + String sender = (String) message.get("sender"); + + if (sender.equalsIgnoreCase("CONSOLE")) { + plugin.getFactionManager().broadcastToFactionsChat(CC.RED + sender, (String) message.get("message"), "GLOBAL"); + } + + plugin.getFactionManager().broadcastToFactionsChat((String) message.get("format"), (String) message.get("message"), (String) message.get("server")); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/RedisServerMonitorListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/RedisServerMonitorListener.java new file mode 100644 index 0000000..3dd68a8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/RedisServerMonitorListener.java @@ -0,0 +1,32 @@ +package me.devkevin.landcore.listeners.redis; + +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 14/02/2023 @ 17:21 + * ServerMonitor / me.devkevin.landcore.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class RedisServerMonitorListener { + private final LandCore plugin; + + @RedisHandler("server-monitor-add") + public void onServerMonitorAdding(Map message) { + String server = (String) message.get("server"); + + plugin.getStaffManager().messageStaff(CC.D_GRAY + "[" + CC.YELLOW + "Server Monitor" + CC.D_GRAY + "] " + CC.WHITE + "Adding server " + server + "..."); + } + + @RedisHandler("server-monitor-remove") + public void onServerMonitorRemoving(Map message) { + String server = (String) message.get("server"); + + plugin.getStaffManager().messageStaff(CC.D_GRAY + "[" + CC.YELLOW + "Server Monitor" + CC.D_GRAY + "] " + CC.WHITE + "Removing server " + server + "..."); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/ReportListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/ReportListener.java new file mode 100644 index 0000000..9e3ced5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/ReportListener.java @@ -0,0 +1,31 @@ +package me.devkevin.landcore.listeners.redis; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 10:38 + * ReportListener / land.pvp.core.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class ReportListener { + private final LandCore plugin; + + @RedisHandler("report") + public void onReport(Map map) { + String player = (String) map.get("reporter"); + String target = (String) map.get("reported"); + String report = (String) map.get("reason"); + String server = (String) map.get("server"); + + plugin.getStaffManager().messageStaff(""); + plugin.getStaffManager().messageStaff(CC.RED + "(Report) " + CC.D_AQUA + "[" + server + "] " + CC.SECONDARY + player + CC.PRIMARY + + " reported " + CC.SECONDARY + target + CC.PRIMARY + " for " + CC.SECONDARY + report + CC.PRIMARY + "."); + plugin.getStaffManager().messageStaff(""); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/StaffChatListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/StaffChatListener.java new file mode 100644 index 0000000..b76d3cd --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/StaffChatListener.java @@ -0,0 +1,29 @@ +package me.devkevin.landcore.listeners.redis; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 10:38 + * StaffChatListener / land.pvp.core.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class StaffChatListener { + private final LandCore plugin; + + @RedisHandler("staff-chat") + public void onStaffChat(Map message) { + String sender = (String) message.get("sender"); + + if (sender.equalsIgnoreCase("CONSOLE")) { + plugin.getStaffManager().messageStaff(CC.RED + sender, (String) message.get("message"), "GLOBAL"); + } + + plugin.getStaffManager().messageStaff((String) message.get("format"), (String) message.get("message"), (String) message.get("server")); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/StaffStreamListener.java b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/StaffStreamListener.java new file mode 100644 index 0000000..feaf4fa --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/listeners/redis/StaffStreamListener.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.listeners.redis; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 10:30 + * StaffStreamListener / land.pvp.core.listeners.redis / LandCore + */ +@RequiredArgsConstructor +public class StaffStreamListener { + private final LandCore plugin; + + @RedisHandler("staff-join") + public void onStaffJoin(Map message) { + plugin.getStaffManager().messageStaffWithPrefix(message.get("sender") + CC.PRIMARY + " joined the server.", (String) message.get("server")); + } + + @RedisHandler("staff-left") + public void onStaffLeft(Map message) { + plugin.getStaffManager().messageStaffWithPrefix(message.get("sender") + CC.PRIMARY + " left the server.", (String) message.get("server")); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/managers/MenuManager.java b/LandCore/src/main/java/me/devkevin/landcore/managers/MenuManager.java new file mode 100644 index 0000000..a828af9 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/managers/MenuManager.java @@ -0,0 +1,41 @@ +package me.devkevin.landcore.managers; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.inventory.menu.Menu; +import me.devkevin.landcore.inventory.menu.impl.ReportMenu; +import org.bukkit.inventory.Inventory; + +import java.util.HashMap; +import java.util.Map; + +public class MenuManager { + private final Map, Menu> menus = new HashMap<>(); + + public MenuManager(LandCore plugin) { + registerMenus( + new ReportMenu(plugin) + ); + } + + public Menu getMenu(Class clazz) { + return menus.get(clazz); + } + + public Menu getMatchingMenu(Inventory other) { + for (Menu menu : menus.values()) { + if (menu.getInventory().equals(other)) { + return menu; + } + } + + return null; + } + + public void registerMenus(Menu... menus) { + for (Menu menu : menus) { + menu.setup(); + menu.update(); + this.menus.put(menu.getClass(), menu); + } + } +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/managers/PlayerManager.java b/LandCore/src/main/java/me/devkevin/landcore/managers/PlayerManager.java new file mode 100644 index 0000000..4bb2920 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/managers/PlayerManager.java @@ -0,0 +1,44 @@ +package me.devkevin.landcore.managers; + +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.net.InetAddress; +import java.util.*; + +@Getter +public class PlayerManager { + private final Map onlinePerIp = new HashMap<>(); + private final List onlineNames = new ArrayList<>(); + private final List dummyPlayers = new ArrayList<>(); + + public void addPlayer(Player player) { + onlineNames.add(player.getName()); + + InetAddress address = player.getAddress().getAddress(); + int count = onlinePerIp.getOrDefault(address, 0) + 1; + + onlinePerIp.put(address, count); + } + + public void removePlayer(Player player) { + onlineNames.remove(player.getName()); + + InetAddress address = player.getAddress().getAddress(); + int count = onlinePerIp.getOrDefault(address, 0) - 1; + + if (count == 0) { + onlinePerIp.remove(address); + } else { + onlinePerIp.put(address, count); + } + } + + public int getOnlineByIp(InetAddress address) { + return onlinePerIp.getOrDefault(address, 0); + } + + public boolean isNameOnline(String name) { + return onlineNames.contains(name); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/managers/ProfileManager.java b/LandCore/src/main/java/me/devkevin/landcore/managers/ProfileManager.java new file mode 100644 index 0000000..f0d5323 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/managers/ProfileManager.java @@ -0,0 +1,33 @@ +package me.devkevin.landcore.managers; + +import me.devkevin.landcore.player.CoreProfile; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +@Getter +public class ProfileManager { + private final Map profiles = new HashMap<>(); + + public CoreProfile createProfile(String name, UUID id, String address) { + CoreProfile profile = new CoreProfile(name, id, address); + profiles.put(id, profile); + return profile; + } + + public CoreProfile getProfile(UUID id) { + return profiles.get(id); + } + + public void removeProfile(UUID id) { + profiles.remove(id); + } + + public void saveProfiles() { + for (CoreProfile profile : profiles.values()) { + profile.save(false); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/managers/StaffManager.java b/LandCore/src/main/java/me/devkevin/landcore/managers/StaffManager.java new file mode 100644 index 0000000..f38b5e6 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/managers/StaffManager.java @@ -0,0 +1,103 @@ +package me.devkevin.landcore.managers; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Set; + +@RequiredArgsConstructor +public class StaffManager { + @Getter + private final Set cachedStaff = new HashSet<>(); + private final LandCore plugin; + + public void addCachedStaff(CoreProfile profile) { + cachedStaff.add(profile); + } + + public boolean isInStaffCache(CoreProfile profile) { + return cachedStaff.contains(profile); + } + + public void removeCachedStaff(CoreProfile profile) { + cachedStaff.remove(profile); + } + + public void messageStaff(String displayName, String msg) { + String formattedMsg = CC.GREEN + "[Staff] " + displayName + CC.R + ": " + msg; + messageStaff(formattedMsg); + } + + public void messageStaff(Rank requiredRank, String msg) { + for (CoreProfile profile : cachedStaff) { + if (profile.hasRank(requiredRank)) { + Player loopPlayer = plugin.getServer().getPlayer(profile.getId()); + + if (loopPlayer != null && loopPlayer.isOnline()) { + loopPlayer.sendMessage(msg); + } + } + } + } + + public void messageStaff(String displayName, String msg, String server) { + String formattedMsg = CC.SECONDARY + "[Staff] " + ChatColor.DARK_AQUA + "[" + server + "] " + CC.SECONDARY + displayName + CC.R + ": " + msg; + messageStaff(formattedMsg); + } + + public void messageStaffWithPrefix(String msg) { + msg = CC.GREEN + "[Staff] " + msg; + + for (CoreProfile profile : cachedStaff) { + Player loopPlayer = plugin.getServer().getPlayer(profile.getId()); + + if (loopPlayer != null && loopPlayer.isOnline()) { + loopPlayer.sendMessage(msg); + } + } + } + + public void messageStaffWithPrefix(String msg, String server) { + msg = CC.SECONDARY + "[Staff] " + CC.D_AQUA + "[" + server + "] " + CC.R + msg; + + for (CoreProfile profile : cachedStaff) { + Player loopPlayer = plugin.getServer().getPlayer(profile.getId()); + + if (loopPlayer != null && loopPlayer.isOnline()) { + loopPlayer.sendMessage(msg); + } + } + plugin.getServer().getConsoleSender().sendMessage(msg); + } + + public void messageStaff(String msg) { + for (CoreProfile profile : cachedStaff) { + Player loopPlayer = plugin.getServer().getPlayer(profile.getId()); + + if (loopPlayer != null && loopPlayer.isOnline()) { + loopPlayer.sendMessage(msg); + } + } + } + + public void hideVanishedStaffFromPlayer(Player player) { + if (!plugin.getProfileManager().getProfile(player.getUniqueId()).hasStaff()) { + for (CoreProfile profile : cachedStaff) { + if (profile.isVanished()) { + Player loopPlayer = plugin.getServer().getPlayer(profile.getId()); + + if (loopPlayer != null && loopPlayer.isOnline()) { + player.hidePlayer(loopPlayer); + } + } + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/nametag/NameTagAdapter.java b/LandCore/src/main/java/me/devkevin/landcore/nametag/NameTagAdapter.java new file mode 100644 index 0000000..9565754 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/nametag/NameTagAdapter.java @@ -0,0 +1,32 @@ +package me.devkevin.landcore.nametag; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.nametag.impl.InternalNametag; +import me.devkevin.landcore.nametag.impl.NametagProvider; +import me.devkevin.landcore.player.CoreProfile; +import org.bukkit.entity.Player; +import xyz.haoshoku.nick.api.NickAPI; + +import static net.minecraft.server.v1_8_R3.ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 11:37 + * NameTagAdapter / land.pvp.core.nametag / LandCore + */ +public class NameTagAdapter extends NametagProvider { + public NameTagAdapter() { + super("NameTagAdapter", 5); + } + + @Override + public InternalNametag.NametagInfo fetchNametag(Player toRefresh, Player refreshFor) { + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(toRefresh.getUniqueId()); + + if (NickAPI.isNicked(toRefresh)) { + return createNametag(coreProfile.getDisguiseRank().getColor(), "", ALWAYS); + } + + return createNametag(coreProfile.getGrant().getRank().getColor(), "", ALWAYS); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/InternalNametag.java b/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/InternalNametag.java new file mode 100644 index 0000000..85f58d3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/InternalNametag.java @@ -0,0 +1,359 @@ +package me.devkevin.landcore.nametag.impl; + +import com.google.common.primitives.Ints; +import lombok.Getter; +import net.minecraft.server.v1_8_R3.PacketPlayOutScoreboardTeam; +import net.minecraft.server.v1_8_R3.ScoreboardTeamBase; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 11:37 + * InternalNametag / land.pvp.core.nametag.impl / LandCore + */ +public class InternalNametag { + + private JavaPlugin plugin; + + @Getter + private static Map> teamMap = new ConcurrentHashMap<>(); + private static final List registeredTeams = Collections.synchronizedList(new ArrayList()); + private static int teamCreateIndex = 1; + private static final List providers = new ArrayList<>(); + + private final static boolean async = true; + @Getter + private static int updateInterval = 2; // In ticks + + public InternalNametag(JavaPlugin plugin, NametagProvider provider) { + this.plugin = plugin; + + (new NametagThread()).start(); + registerProvider(provider); // fix async provider + + this.plugin.getServer().getPluginManager().registerEvents(new NametagListener(plugin), plugin); + } + + /** + * Registers a new NametagProvider. Note that the newProvider + * will not always be used. It will only be used if it is the highest + * weighted provider available. + * + * @param newProvider The NametagProvider to register. + */ + public static void registerProvider(NametagProvider newProvider) { + providers.add(newProvider); + providers.sort((weight, target) -> (Ints.compare(target.getWeight(), weight.getWeight()))); + } + + /** + * Refreshes one player for all players online. + * NOTE: This is not an instant refresh, this is queued and async. + * + * @param toRefresh The player to refresh. + */ + public static void reloadPlayer(Player toRefresh) { + NametagUpdate update = new NametagUpdate(toRefresh); + + if (async) { + NametagThread.getPendingUpdates().put(update, true); + } else { + applyUpdate(update); + } + } + + /** + * Reloads all OTHER players for the player provided. + * + * @param refreshFor The player who should have all viewable nametags refreshed. + */ + public static void reloadOthersFor(Player refreshFor) { + for (Player toRefresh : Bukkit.getOnlinePlayers()) { + if (refreshFor == toRefresh) continue; + reloadPlayer(toRefresh, refreshFor); + } + } + + /** + * Refreshes one player for another player only. + * NOTE: This is not an instant refresh, this is queued and async. + * + * @param toRefresh The player to refresh. + * @param refreshFor The player to refresh toRefresh for. + */ + public static void reloadPlayer(Player toRefresh, Player refreshFor) { + NametagUpdate update = new NametagUpdate(toRefresh, refreshFor); + + if (async) { + NametagThread.getPendingUpdates().put(update, true); + } else { + applyUpdate(update); + } + } + + /** + * Applies a pending nametag update. Only for internal use. + * + * @param nametagUpdate The nametag update to apply. + */ + protected static void applyUpdate(NametagUpdate nametagUpdate) { + Player toRefreshPlayer = Bukkit.getPlayerExact(nametagUpdate.getToRefresh()); + + // Just ignore it if they logged off since the request to update was submitted + if (toRefreshPlayer == null) { + return; + } + + if (nametagUpdate.getRefreshFor() == null) { + for (Player refreshFor : Bukkit.getOnlinePlayers()) { + reloadPlayerInternal(toRefreshPlayer, refreshFor); + } + } else { + Player refreshForPlayer = Bukkit.getPlayerExact(nametagUpdate.getRefreshFor()); + + if (refreshForPlayer != null) { + reloadPlayerInternal(toRefreshPlayer, refreshForPlayer); + } + } + } + + /** + * Reloads a player sync. Only for internal use. + * + * @param toRefresh The player to refresh. + * @param refreshFor The player to refresh 'toRefresh' for. + */ + protected static void reloadPlayerInternal(Player toRefresh, Player refreshFor) { + if (!refreshFor.hasMetadata("NameTag-LoggedIn")) { + return; + } + + NametagInfo provided = null; + int providerIndex = 0; + + while (provided == null) { + provided = providers.get(providerIndex++).fetchNametag(toRefresh, refreshFor); + } + + Map teamInfoMap = new HashMap<>(); + + if (teamMap.containsKey(refreshFor.getName())) { + teamInfoMap = teamMap.get(refreshFor.getName()); + } + + (new NametagMethod(provided.getName(), Collections.singletonList(toRefresh.getName()), 3)).sendToPlayer(refreshFor); + teamInfoMap.put(toRefresh.getName(), provided); + teamMap.put(refreshFor.getName(), teamInfoMap); + } + + /** + * 'Sets up' a player. This sends them all existing teams + * and their members. This does NOT send new nametag + * packets for the given player. Only for internal use. + * + * @param player The player to setup. + */ + protected static void initiatePlayer(Player player) { + for (NametagInfo teamInfo : registeredTeams) { + teamInfo.getNametagMethod().sendToPlayer(player); + } + } + + /** + * Gets or created a NametagInfo objetc + * with the specified prefix and suffix. Only for internal use. + * + * @param prefix The prefix the NametagInfo object should have. + * @param suffix The suffix the NametagInfo object should have. + * @return The NametagInfo object with the prefix and suffix given. + */ + protected static NametagInfo getOrCreate(String prefix, String suffix, ScoreboardTeamBase.EnumNameTagVisibility tagVisibility) { + for (NametagInfo teamInfo : registeredTeams) { + if (teamInfo.getPrefix().equals(prefix) && teamInfo.getSuffix().equals(suffix)) { + return (teamInfo); + } + } + + NametagInfo newTeam = new NametagInfo(String.valueOf(teamCreateIndex++), prefix, suffix, tagVisibility); + registeredTeams.add(newTeam); + + NametagMethod addPacket = newTeam.getNametagMethod(); + + for (Player player : Bukkit.getOnlinePlayers()) { + addPacket.sendToPlayer(player); + } + + return (newTeam); + } + + @Getter + public static class NametagInfo { + + private String name, prefix, suffix; + private ScoreboardTeamBase.EnumNameTagVisibility tagVisibility; + private NametagMethod nametagMethod; + + protected NametagInfo(String name, String prefix, String suffix, ScoreboardTeamBase.EnumNameTagVisibility tagVisibility) { + this.name = name; + this.prefix = prefix; + this.suffix = suffix; + this.tagVisibility = tagVisibility; + + // add nametag visibility reader + nametagMethod = new NametagMethod(name, prefix, suffix, tagVisibility, new ArrayList(), 0); + } + + @Override + public boolean equals(Object other) { + if (other instanceof NametagInfo) { + NametagInfo otherNametag = (NametagInfo) other; + return (name.equals(otherNametag.name) && prefix.equals(otherNametag.prefix) && suffix.equals(otherNametag.suffix)); + } + + return (false); + } + } + + /** + * A nametag update that is queued to happen. + * Commonly the update is queued from a sync. thread. + */ + @Getter + public static class NametagUpdate { + + private String toRefresh; + private String refreshFor; + + /** + * Refreshes one player for all players online. + * + * @param toRefresh The player to refresh. + */ + public NametagUpdate(Player toRefresh) { + this.toRefresh = toRefresh.getName(); + } + + /** + * Refreshes one player for another player only. + * + * @param toRefresh The player to refresh. + * @param refreshFor The player to refresh toRefresh for. + */ + public NametagUpdate(Player toRefresh, Player refreshFor) { + this.toRefresh = toRefresh.getName(); + this.refreshFor = refreshFor.getName(); + } + } + + /** + * A simple scoreboard team reflection + * */ + public static class NametagMethod { + + private PacketPlayOutScoreboardTeam scoreboardTeam; + + public NametagMethod(String name, String prefix, String suffix, ScoreboardTeamBase.EnumNameTagVisibility tagVisibility, Collection players, int paramInt) { + scoreboardTeam = new PacketPlayOutScoreboardTeam(); + + setField("a", name); + setField("h", paramInt); + + if(paramInt == 0 || paramInt == 2) { + setField("b", name); + setField("c", prefix); + setField("d", suffix); + setField("e", tagVisibility.e); + setField("i", 1); + } + + if(paramInt == 0) { + addAll(players); + } + } + + public NametagMethod(String name, Collection players, int paramInt) { + scoreboardTeam = new PacketPlayOutScoreboardTeam(); + + if(players == null) { + players = new ArrayList(); + } + + setField("a", name); + setField("h", paramInt); + + addAll(players); + } + + public void sendToPlayer(Player bukkitPlayer) { + ((CraftPlayer) bukkitPlayer).getHandle().playerConnection.sendPacket(scoreboardTeam); + } + + private void setField(String field, Object value) { + try { + Field fieldObject = scoreboardTeam.getClass().getDeclaredField(field); + + fieldObject.setAccessible(true); + fieldObject.set(scoreboardTeam, value); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void addAll(Collection collection) { + try { + Field fieldObject = scoreboardTeam.getClass().getDeclaredField("g"); + + fieldObject.setAccessible(true); + ((Collection) fieldObject.get(scoreboardTeam)).addAll(collection); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static class NametagThread extends Thread { + + // We use a Map here for a few reasons... + // 1) Why the heck not + // 2) There's no good concurrent set implementation + // 3) (Concurrent) Sets are backed by Maps anyway so... + @Getter private static Map pendingUpdates = new ConcurrentHashMap<>(); + + public NametagThread() { + super("InternalNametag Thread"); + + this.setDaemon(false); + } + + public void run() { + while (true) { + Iterator pendingUpdatesIterator = pendingUpdates.keySet().iterator(); + + while (pendingUpdatesIterator.hasNext()) { + NametagUpdate pendingUpdate = pendingUpdatesIterator.next(); + + try { + InternalNametag.applyUpdate(pendingUpdate); + pendingUpdatesIterator.remove(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + try { + Thread.sleep(InternalNametag.getUpdateInterval() * 50L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/NametagListener.java b/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/NametagListener.java new file mode 100644 index 0000000..b5dc8ae --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/NametagListener.java @@ -0,0 +1,42 @@ +package me.devkevin.landcore.nametag.impl; + +import lombok.AllArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 11:38 + * NametagListener / land.pvp.core.nametag.impl / LandCore + */ +@AllArgsConstructor +public class NametagListener implements Listener { + + private JavaPlugin plugin; + + @EventHandler(priority = EventPriority.LOW) + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + player.setMetadata("NameTag-LoggedIn", new FixedMetadataValue(plugin, true)); + + InternalNametag.initiatePlayer(player); + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + } + + @EventHandler(priority = EventPriority.LOW) + public void onQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + // fix async updater when player disconnect + player.removeMetadata("NameTag-LoggedIn", plugin); + + InternalNametag.getTeamMap().remove(player.getName()); + } +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/NametagProvider.java b/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/NametagProvider.java new file mode 100644 index 0000000..deaeedb --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/nametag/impl/NametagProvider.java @@ -0,0 +1,53 @@ +package me.devkevin.landcore.nametag.impl; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.minecraft.server.v1_8_R3.ScoreboardTeamBase; +import org.bukkit.entity.Player; + +/** + * A class that can 'provide' nametags for players. + */ +@Getter +@AllArgsConstructor +public abstract class NametagProvider { + + private String name; + private int weight; + + /** + * Takes in the player to refresh and who to refresh that player for, + * and returns the prefix and suffix they should be given. + * + * @param toRefresh The player whose nametag is getting refreshed. + * @param refreshFor The player who this nametag change is going to be visible to. + * @return The nametag that refreshFor should see above toRefresh's head. + */ + public abstract InternalNametag.NametagInfo fetchNametag(Player toRefresh, Player refreshFor); + + /** + * Wrapper method to create a NametagInfo object. + * + * @param prefix The prefix the nametag has. + * @param suffix The suffix the nametag has. + * @param tagVisibility The visibility the nametag has. + * @return The created NametagInfo object. + */ + public static InternalNametag.NametagInfo createNametag(String prefix, String suffix, ScoreboardTeamBase.EnumNameTagVisibility tagVisibility) { + return (InternalNametag.getOrCreate(prefix, suffix, tagVisibility)); + } + + protected static final class DefaultNametagProvider extends NametagProvider { + + public DefaultNametagProvider() { + super("Default Provider", 0); + } + + @Override + public InternalNametag.NametagInfo fetchNametag(Player toRefresh, Player refreshFor) { + return (createNametag("", "", ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS)); + } + + } +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/CoreProfile.java b/LandCore/src/main/java/me/devkevin/landcore/player/CoreProfile.java new file mode 100644 index 0000000..7ac72a4 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/CoreProfile.java @@ -0,0 +1,344 @@ +package me.devkevin.landcore.player; + +import com.google.common.reflect.TypeToken; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.mongodb.Block; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.grant.Grant; +import me.devkevin.landcore.player.notes.Note; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.storage.database.MongoRequest; +import me.devkevin.landcore.storage.database.MongoStorage; +import me.devkevin.landcore.utils.location.CustomLocation; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.message.Messages; +import me.devkevin.landcore.utils.timer.Timer; +import me.devkevin.landcore.utils.timer.impl.DoubleTimer; +import me.devkevin.landcore.utils.timer.impl.IntegerTimer; +import org.bson.Document; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import java.lang.reflect.Type; +import java.util.*; +import java.util.concurrent.TimeUnit; + +@Getter +@Setter +public class CoreProfile { + public static Type GRANT_TYPE = new TypeToken() {}.getType(); + public static Type GRANTS_TYPE = new TypeToken>() {}.getType(); + public static Type LIST_STRING_TYPE = new TypeToken>() {}.getType(); + + private final List ignored = new ArrayList<>(); + + private final String name; + private final UUID id; + private final Timer commandCooldownTimer = new DoubleTimer(1); + private final Timer reportCooldownTimer = new IntegerTimer(TimeUnit.SECONDS, 60); + private Timer chatCooldownTimer; + private UUID converser; + private String reportingPlayerName; + private boolean playingSounds = true; + private boolean messaging = true; + private boolean globalChatEnabled = true; + private boolean inStaffChat; + private boolean vanished; + private long lastChatTime; + private boolean frozen = false; + + private Grant grant; + private List grants = new ArrayList<>(); + + private List notes = new ArrayList<>(); + + private double misplace; + private CustomLocation lastMovePacket; + private Map> recentPlayerPackets = new HashMap<>(); + + private Set prefixes, suffix = new HashSet<>(); + + private String customPrefix = ""; + private String customSuffix = ""; + private String customColor; + private Rank disguiseRank; + private String disguiseName; + + private List punishments = new ArrayList<>(); + + private String currentAddress; + private List ipAddresses = new ArrayList<>(); + private List knownAlts = new ArrayList<>(); + + private int p_coin; + + @SuppressWarnings("unchecked") + public CoreProfile(String name, UUID id, String address) { + this.name = name; + this.id = id; + this.ipAddresses.add(address); + + LandCore.getInstance().getMongoStorage().getOrCreateDocument("players", id, (document, exists) -> { + if (exists) { + this.inStaffChat = document.getBoolean("staff_chat_enabled", inStaffChat); + this.messaging = document.getBoolean("messaging_enabled", messaging); + this.playingSounds = document.getBoolean("playing_sounds", playingSounds); + + + this.customPrefix = document.getString("customPrefix"); + this.customSuffix = document.getString("customSuffix"); + this.customColor = document.getString("customColor"); + + this.grant = LandCore.GSON.fromJson(document.getString("grant"), GRANT_TYPE); + this.grants = LandCore.GSON.fromJson(document.getString("grants"), GRANTS_TYPE); + + this.currentAddress = document.getString("currentAddress"); + this.ipAddresses = LandCore.GSON.fromJson(document.getString("ipAddresses"), LIST_STRING_TYPE); + + this.p_coin = document.getInteger("p_coin", p_coin); + + List permissions = (List) document.get("permissions"); + + if (permissions != null) { + this.grant.getRank().getPermissions().addAll(permissions); + } + + List ignored = (List) document.get("ignored_ids"); + + if (ignored != null) { + this.ignored.addAll(ignored); + } + + JsonArray punishments = new JsonParser().parse(document.getString("punishments")).getAsJsonArray(); + for (JsonElement jsonElement : punishments) { + JsonObject jsonObject = jsonElement.getAsJsonObject(); + this.punishments.add(Punishment.DESERIALIZER.deserialize(jsonObject)); + } + + if (document.getString("notes") != null) { + JsonArray notesArray = new JsonParser().parse(document.getString("notes")).getAsJsonArray(); + + for (JsonElement noteData : notesArray) { + // Transform into a note object + Note note = Note.DESERIALIZER.deserialize(noteData.getAsJsonObject()); + + if (note != null) { + notes.add(note); + } + } + } + } else { + grant = new Grant(Rank.MEMBER, -1L, System.currentTimeMillis(), "Console", "Profile creation"); + } + + save(true); + }); + } + + public Punishment getActiveMute() { + for (Punishment punishment : punishments) { + if (punishment.getType() == PunishmentType.MUTE && punishment.isActive()) { + return punishment; + } + } + + return null; + } + + public Punishment getActiveBan() { + for (Punishment punishment : punishments) { + if (punishment.getType().isBan() && punishment.isActive()) { + return punishment; + } + } + + return null; + } + + public int getPunishmentCountByType(PunishmentType type) { + int i = 0; + + for (Punishment punishment : punishments) { + if (punishment.getType() == type) i++; + } + + return i; + } + + public void save(boolean async) { + MongoRequest request = MongoRequest.newRequest("players", id) + .put("name", name) + .put("staff_chat_enabled", inStaffChat) + .put("messaging_enabled", messaging) + .put("playing_sounds", playingSounds) + .put("ignored_ids", ignored) + .put("customPrefix", customPrefix) + .put("customSuffix", customSuffix) + .put("customColor", customColor) + .put("currentAddress", currentAddress) + .put("ipAddresses", LandCore.GSON.toJson(ipAddresses, LIST_STRING_TYPE)) + .put("permissions", this.grant.getRank().getPermissions()) + .put("p_coin", p_coin); + + request.put("grant", LandCore.GSON.toJson(this.grant, GRANT_TYPE)); + request.put("grants", LandCore.GSON.toJson(this.grants, GRANTS_TYPE)); + + JsonArray notesArray = new JsonArray(); + for (Note note : notes) { + notesArray.add(Note.SERIALIZER.serialize(note)); + } + request.put("notes", notesArray.toString()); + + JsonArray punishments = new JsonArray(); + for (Punishment punishment : this.punishments) { + punishments.add(Punishment.SERIALIZER.serialize(punishment)); + } + request.put("punishments", punishments.toString()); + + if (async) { + LandCore.getInstance().getServer().getScheduler().runTaskAsynchronously(LandCore.getInstance(), request::run); + } else { + request.run(); + } + } + + public Timer getChatCooldownTimer() { + if (chatCooldownTimer == null) { + if (isDonor()) { + chatCooldownTimer = new DoubleTimer(1); + } else { + chatCooldownTimer = new DoubleTimer(3); + } + } + + return chatCooldownTimer; + } + + public String getChatFormat() { + String rankColor = this.getRank().getColor(); + String color = customColor != null && !customColor.isEmpty() && hasRank(Rank.BASIC) ? customColor : rankColor; + String prefix = getGrant().getRank().getRawFormat().equals("") ? "" : customPrefix + " "; + String suffix = getGrant().getRank().getName().equals(" ") ? " " : "" + customSuffix; + + return String.format(prefix + this.getRank().getRawFormat()) + color + name + suffix; + } + + public void updateLastChatTime() { + lastChatTime = System.currentTimeMillis(); + } + + public boolean hasRank(Rank requiredRank) { + return grant.getRank().ordinal() >= requiredRank.ordinal(); + } + + public boolean hasStaff() { + return hasRank(Rank.HOST); + } + + public boolean hasDonor() { + return hasRank(Rank.BASIC); + } + + public boolean isDonor() { + return grant.getRank() == Rank.BASIC; + } + + public void ignore(UUID id) { + ignored.add(id); + } + + public void unignore(UUID id) { + ignored.remove(id); + } + + public boolean hasPlayerIgnored(UUID id) { + return ignored.contains(id); + } + + public Player getPlayer() { + return LandCore.getInstance().getServer().getPlayer(this.id); + } + + public boolean freeze(CommandSender sender) { + frozen = !frozen; + + if (frozen) { + getPlayer().setWalkSpeed(0.0F); + getPlayer().setFlySpeed(0.0F); + getPlayer().setFoodLevel(0); + getPlayer().setSprinting(false); + getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 200)); + Arrays.stream(Messages.FROZEN_MESSAGE).forEach(message -> Messages.sendCenteredMessage(getPlayer(), message)); + sender.sendMessage(CC.RED + "Player frozen."); + return true; + } + getPlayer().setWalkSpeed(0.2f); + getPlayer().setFlySpeed(0.0001f); + getPlayer().setFoodLevel(20); + getPlayer().setSprinting(true); + getPlayer().removePotionEffect(PotionEffectType.JUMP); + getPlayer().sendMessage(CC.SECONDARY + "You have been unfrozen."); + sender.sendMessage(CC.RED + getPlayer().getName() + " has been unfrozen."); + return false; + } + + public Rank getRank() { + return this.getGrant() != null ? this.getGrant().getRank() : Rank.MEMBER; + } + + public Grant getGrant() { + if (this.grant.hasExpired()) { + return new Grant(Rank.MEMBER, -1L, System.currentTimeMillis(), "Console", "Profile creation"); + } + return this.grant; + } + + public boolean removeNote(int id) { + Note note = notes.stream().filter(note1 -> note1.getId() == id).findFirst().orElse(null); + return notes.remove(note); + } + + public Note getNote(int id) { + return notes.stream().filter(note1 -> note1.getId() == id).findFirst().orElse(null); + } + + public void addPlayerPacket(final UUID playerUUID, final CustomLocation customLocation) { + List customLocations = this.recentPlayerPackets.get(playerUUID); + if (customLocations == null) { + customLocations = new ArrayList<>(); + } + if (customLocations.size() == 20) { + customLocations.remove(0); + } + customLocations.add(customLocation); + this.recentPlayerPackets.put(playerUUID, customLocations); + } + + public CustomLocation getLastPlayerPacket(final UUID playerUUID, final int index) { + final List customLocations = this.recentPlayerPackets.get(playerUUID); + if (customLocations != null && customLocations.size() > index) { + return customLocations.get(customLocations.size() - index); + } + return null; + } + + public static List getByIpAddress(String ipAddress) { + List profiles = new ArrayList<>(); + + MongoStorage storage = LandCore.getInstance().getMongoStorage(); + + storage.getDocumentsByFilter("players", Filters.eq("currentAddress", ipAddress)).forEach((Block) document -> + profiles.add(new CoreProfile(document.getString("username"), UUID.fromString(document.getString("uuid")), document.getString("currentAddress")))); + + return profiles; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/color/ColorCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/color/ColorCommand.java new file mode 100644 index 0000000..44e59c1 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/color/ColorCommand.java @@ -0,0 +1,61 @@ +package me.devkevin.landcore.player.color; + +import com.google.common.collect.ImmutableMap; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 4:28 + * ColorCommand / me.devkevin.landcore.player.color / LandCore + */ +public class ColorCommand extends PlayerCommand { + private final LandCore plugin; + + private static final Map COLORS = new ImmutableMap.Builder() + .put("purple", CC.PURPLE) + .put("dark_aqua", CC.D_AQUA) + .put("light_gray", CC.GRAY) + .put("gray", CC.D_GRAY) + .put("light_purple", CC.PINK) + .put("green", CC.GREEN) + .put("aqua", CC.AQUA) + .put("gold", CC.GOLD) + .put("red", CC.RED) + .put("yellow", CC.YELLOW) + .put("dark_green", CC.DARK_GREEN) + .put("white", CC.WHITE) + .put("black", CC.BLACK) + .put("dark_red", CC.D_RED) + .build(); + + public ColorCommand(LandCore plugin) { + super("setcolor"); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + CoreProfile profile = this.plugin.getProfileManager().getProfile(player.getUniqueId()); + + String customColor = COLORS.get(args[0].toLowerCase()); + if (customColor == null && !args[0].equalsIgnoreCase("default")) { + player.sendMessage(CC.RED + "Invalid color."); + player.sendMessage(CC.RED + "Valid colors are: " + + COLORS.keySet().toString().replace("[", "").replace("]", "")); + return; + } + + profile.setCustomColor(customColor); + player.sendMessage(CC.GREEN + "You changed your chat color to " + args[0] + "."); + + if (!args[0].equalsIgnoreCase("default")) { + player.sendMessage(CC.GREEN + "Do '/color' to go back to default."); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/color/SetColorCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/color/SetColorCommand.java new file mode 100644 index 0000000..f18a405 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/color/SetColorCommand.java @@ -0,0 +1,24 @@ +package me.devkevin.landcore.player.color; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 4:38 + * SetColorCommand / me.devkevin.landcore.player.color / LandCore + */ +public class SetColorCommand extends PlayerCommand { + private final LandCore plugin; + + public SetColorCommand(LandCore plugin) { + super("color"); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + player.openInventory(this.plugin.getColorMenu().getMenu(player).getCurrentPage()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/color/menu/ColorMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/color/menu/ColorMenu.java new file mode 100644 index 0000000..4e9f184 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/color/menu/ColorMenu.java @@ -0,0 +1,176 @@ +package me.devkevin.landcore.player.color.menu; + +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.WoolUtil; +import me.devkevin.landcore.utils.inventory.InventoryUI; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 4:31 + * ColorMenu / me.devkevin.landcore.player.color.menu / LandCore + */ +@Getter +public class ColorMenu { + private final InventoryUI menu = new InventoryUI(CC.GOLD + "Color Editor", 4); + + public String[] COLORS = { + "Purple", "dark_aqua", "light_gray", + "Gray", "light_purple", "Green", + "Aqua", "Gold", "Red", "Yellow", + "dark_green", "White", "Black", + "dark_red", + }; + + private String getColor(String colorName) { + switch (colorName) { + case "Purple": return CC.PURPLE; + case "dark_aqua": return CC.D_AQUA; + case "light_gray": return CC.GRAY; + case "Gray": return CC.D_GRAY; + case "light_purple": return CC.PINK; + case "Green": return CC.GREEN; + case "Aqua": return CC.AQUA; + case "Gold": return CC.GOLD; + case "Red": return CC.RED; + case "Yellow": return CC.YELLOW; + case "dark_green": return CC.DARK_GREEN; + case "White" : return CC.WHITE; + case "Black" : return CC.BLACK; + case "dark_red" : return CC.D_RED; + case "Remove Color": return null; + default: return "default"; + } + } + + public InventoryUI getMenu(Player player) { + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + String c = profile.getCustomColor() != null && !profile.getCustomColor().isEmpty() && profile.hasRank(Rank.BASIC) ? profile.getCustomColor() : profile.getGrant().getRank().getColor(); + + this.menu.setItem(4, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.REDSTONE_BLOCK) + .name(profile.getGrant().getRank().getRawFormat() + c + player.getName() + CC.R + ": Hello!") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "Your chat messages will", + CC.GRAY + CC.B + "be displayed like the example", + CC.GRAY + CC.B + "above.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + } + }); + + this.menu.setItem(35, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.GLASS) + .name(CC.RED + CC.B + "Remove color") + .lore(Arrays.asList( + "", + CC.GRAY + CC.B + "Reverts your chat color back", + CC.GRAY + CC.B + "to the original color created", + CC.GRAY + CC.B + "by your rank.", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + player.closeInventory(); + + if (profile == null) { + player.sendMessage(CC.RED + "Please wait for your data to load."); + return; + } + + String name = ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName()); + String customColor = getColor(name); + + String color = customColor != null ? customColor.replace("&", "§") : ""; + + if (color.equals(profile.getCustomColor())) { + player.sendMessage(CC.RED + "You already have " + getColor(name) + name + CC.RED + " selected."); + return; + } + + if (!profile.hasRank(Rank.BASIC)) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot change your color name with " + profile.getRank().getColor() + profile.getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://store.prac.lol/ to change your color name."); + player.sendMessage(""); + return; + } + + player.performCommand("setcolor " + "default"); + profile.save(true); + } + }); + + int[] i = {9}; + + Stream.of(COLORS).forEach(colorName -> { + String color = getColor(colorName); + + menu.setItem(i[0], new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.WOOL) + .name(color + colorName) + .durability(WoolUtil.convertCCToWoolData(color)).lore(Arrays.asList( + CC.GRAY + CC.B + "Change your color name", + CC.GRAY + CC.B + "to " + colorName + CC.GRAY + CC.I + "." + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + player.closeInventory(); + + if (profile == null) { + player.sendMessage(CC.RED + "Please wait for your data to load."); + return; + } + + String name = ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName()); + String customColor = getColor(name); + + String color = customColor != null ? customColor.replace("&", "§") : ""; + + if (color.equals(profile.getCustomColor())) { + player.sendMessage(CC.RED + "You already have " + getColor(name) + name + CC.RED + " selected."); + return; + } + + if (!profile.hasRank(Rank.BASIC)) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot change your color name with " + profile.getRank().getColor() + profile.getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://store.prac.lol/ to change your color name."); + player.sendMessage(""); + return; + } + + player.performCommand("setcolor " + name); + profile.save(true); + } + }); + i[0]++; + }); + + return menu; + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/Grant.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/Grant.java new file mode 100644 index 0000000..85abb59 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/Grant.java @@ -0,0 +1,34 @@ +package me.devkevin.landcore.player.grant; + +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.time.TimeFormatUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 0:47 + * Grant / land.pvp.core.player.grant / LandCore + */ +@Getter +@Setter +@AllArgsConstructor +public class Grant { + private Rank rank; + private long duration; + private long addedAt; + private String addedBy; + private String reason; + + public boolean hasExpired() { + if (duration == -1L) return false; + + return System.currentTimeMillis() > this.duration; + } + + public String getNiceDuration() { + if (duration == -1L) return "Never"; + return TimeFormatUtils.getDetailedTime(this.duration - System.currentTimeMillis()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu.java new file mode 100644 index 0000000..33cafbc --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu.java @@ -0,0 +1,144 @@ +package me.devkevin.landcore.player.grant.menus; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.event.player.PlayerRankChangeEvent; +import me.devkevin.landcore.player.grant.Grant; +import me.devkevin.landcore.player.grant.procedure.GrantProcedure; +import me.devkevin.landcore.player.grant.procedure.GrantProcedureStage; +import me.devkevin.landcore.utils.TaskUtil; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.ButtonSound; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.message.CC; + + +import me.devkevin.landcore.utils.time.TimeFormatUtils; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +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.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:10 + * GrantConfirmMenu / land.pvp.core.player.grant.menus / LandCore + */ +@RequiredArgsConstructor +public class GrantConfirmMenu extends Menu { + + private final GrantProcedure grantProcedure; + + @Override + public String getTitle(Player player) { + return CC.translate("&aAre you sure?"); + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + surroundButtons(true, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + int[] confirm = {10, 11, 12, 19, 21, 28, 29, 30}; + + for (int i : confirm) { + buttons.put(i, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(13).build(); + } + }); + } + + buttons.put(20, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to confirm"); + lore.add(CC.GRAY + "this current grant."); + return new ItemBuilder(Material.WOOL).durability(5).lore(CC.translate(lore)).name(CC.B + CC.GREEN + "Confirm").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + if (grantProcedure != null && grantProcedure.getStage() == GrantProcedureStage.CONFIRMATION) { + Grant grant = new Grant(grantProcedure.getRank(), grantProcedure.getDuration(), System.currentTimeMillis(), grantProcedure.getAddedBy(), grantProcedure.getReason()); + + grantProcedure.getAddedTo().setGrant(grant); + grantProcedure.getAddedTo().getGrants().add(grant); + Bukkit.getPlayer(grantProcedure.getAddedTo().getName()).sendMessage(CC.translate("&aYour rank has been set to " + grantProcedure.getRank().getColor() + grantProcedure.getRank().getName() + "&a.")); + player.sendMessage(CC.translate("&aYou have set &e" + grantProcedure.getAddedTo().getName() + " &arank to " + grantProcedure.getRank().getColor() + grantProcedure.getRank().getName() + "&a.")); + TaskUtil.runAsync(() -> Bukkit.getPlayer(grantProcedure.getAddedTo().getName()).setPlayerListName(grantProcedure.getRank().getColor() + grantProcedure.getAddedTo().getName())); + GrantProcedure.getProcedures().remove(grantProcedure); + + LandCore.getInstance().getServer().getPluginManager().callEvent(new PlayerRankChangeEvent(grantProcedure.getAddedTo().getPlayer(), grantProcedure.getAddedTo(), grant, grant.getDuration())); + + player.closeInventory(); + playSound(player, ButtonSound.SUCCESS); + } + } + }); + + buttons.put(24, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to cancel"); + lore.add(CC.GRAY + "this current grant."); + return new ItemBuilder(Material.WOOL).durability(14).lore(CC.translate(lore)).name(CC.B + CC.RED + "Cancel").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + if (grantProcedure != null && grantProcedure.getStage() == GrantProcedureStage.CONFIRMATION) { + GrantProcedure.getProcedures().remove(grantProcedure); + player.sendMessage(CC.RED + "You have cancelled grant procedure."); + player.closeInventory(); + playSound(player, ButtonSound.FAIL); + } + } + }); + + buttons.put(22, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Player&7: " + CC.PRIMARY + grantProcedure.getAddedTo().getName()); + lore.add(CC.SECONDARY + "Rank&7: " + CC.PRIMARY + grantProcedure.getRank().getColor() + grantProcedure.getRank().getName()); + lore.add(CC.SECONDARY + "Reason&7: " + CC.PRIMARY + grantProcedure.getReason()); + lore.add(CC.SECONDARY + "Duration&7: " + CC.PRIMARY + (grantProcedure.getDuration() == -1L ? "Permanent" : TimeFormatUtils.getDetailedTime(grantProcedure.getDuration()))); + lore.add(""); + lore.add(CC.GRAY + "Click one of the items"); + lore.add(CC.GRAY + "to finish the procedure."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.GREEN + "Grant Info").build(); + + } + }); + + int[] cancel = {14, 15, 16, 23, 25, 32, 33, 34}; + + for (int i : cancel) { + buttons.put(i, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(14).build(); + } + }); + } + return buttons; + } + + @Override + public int getSize() { + return 9 * 5; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantDurationMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantDurationMenu.java new file mode 100644 index 0000000..1500d11 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantDurationMenu.java @@ -0,0 +1,198 @@ +package me.devkevin.landcore.player.grant.menus; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.procedure.GrantProcedure; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.menu.buttons.BackButton; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +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.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:07 + * GrantDurationMenu / land.pvp.core.player.grant.menus / LandCore + */ +@RequiredArgsConstructor +public class GrantDurationMenu extends Menu { + + @Override + public String getTitle(Player player) { + return CC.PRIMARY + "Please select a duration"; + } + + private final GrantProcedure grantProcedure; + private final CoreProfile data; + + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(27, new BackButton(new GrantReasonMenu(grantProcedure, data))); + + surroundButtons(true, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Player&7: " + CC.PRIMARY + grantProcedure.getAddedTo().getName()); + lore.add(CC.SECONDARY + "Rank&7: " + CC.PRIMARY + grantProcedure.getRank().getColor() + grantProcedure.getRank().getName()); + lore.add(""); + lore.add(CC.GRAY + "Click one of the items"); + lore.add(CC.GRAY + "to select grant duration."); + return new ItemBuilder(Material.NETHER_STAR).lore(CC.translate(lore)).name(CC.PRIMARY + "Grant Info").build(); + } + }); + + buttons.put(10, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.SECONDARY + "grant duration to " + CC.RED + "permanent" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.RED + "Permanent").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("perm"); + new GrantReasonMenu(grantProcedure, data).openMenu(player); + } + }); + + buttons.put(11, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.SECONDARY + "grant duration to " + CC.GREEN + "1 month" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.GREEN + "1 Month").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("30d"); + new GrantReasonMenu(grantProcedure, data).openMenu(player); + + } + }); + + buttons.put(12, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.GRAY + "grant duration to " + CC.YELLOW + "1 week" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.YELLOW + "1 Week").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("1w"); + new GrantReasonMenu(grantProcedure, data).openMenu(player); + } + }); + + buttons.put(14, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.GRAY + "grant duration to " + CC.PINK + "30 minutes" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.PURPLE + "30 minutes.").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("30m"); + new GrantReasonMenu(grantProcedure, data).openMenu(player); + } + }); + + buttons.put(15, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.GRAY + "grant duration to " + CC.GOLD + "15 minutes" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.GOLD + "15 minutes.").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("15m"); + new GrantReasonMenu(grantProcedure, data).openMenu(player); + + } + }); + + buttons.put(16, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.GRAY + "grant duration to " + CC.D_AQUA + "1 minute" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.D_AQUA + "1 minute.").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("1m"); + new GrantReasonMenu(grantProcedure, data).openMenu(player); + } + }); + + buttons.put(22, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.GRAY + "grant duration to " + CC.AQUA + "custom" + CC.GRAY + "."); + return new ItemBuilder(Material.BOOK_AND_QUILL).lore(CC.translate(lore)).name(CC.B + CC.AQUA + "Custom").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.closeInventory(); + player.sendMessage(CC.GRAY + CC.SEPARATOR); + player.sendMessage(CC.SECONDARY + "Please type " + CC.PRIMARY + "duration " + CC.SECONDARY + "for this rank."); + player.sendMessage(CC.SECONDARY + "Example: " + CC.GRAY + "(1y, 1m, 1w, 1d, 1h, 1m, 1s)"); + player.sendMessage(CC.GRAY + CC.SEPARATOR); + } + }); + + buttons.put(35, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.REDSTONE).name(CC.BD_RED + "Cancel").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("cancel"); + player.closeInventory(); + } + }); + + + return buttons; + } + + @Override + public int getSize() { + return 9 * 4; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantReasonMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantReasonMenu.java new file mode 100644 index 0000000..1bab06a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantReasonMenu.java @@ -0,0 +1,180 @@ +package me.devkevin.landcore.player.grant.menus; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.procedure.GrantProcedure; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.menu.buttons.BackButton; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +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.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:04 + * GrantReasonMenu / land.pvp.core.player.grant.menus / LandCore + */ +@RequiredArgsConstructor +public class GrantReasonMenu extends Menu { + + @Override + public String getTitle(Player player) { + return CC.PRIMARY + "Please select a reason"; + } + + private final GrantProcedure grantProcedure; + private final CoreProfile data; + + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(27, new BackButton(new GrantSelectMenu(data))); + + surroundButtons(true, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Player&7: " + CC.PRIMARY + grantProcedure.getAddedTo().getName()); + lore.add(CC.SECONDARY + "Rank&7: " + CC.PRIMARY + grantProcedure.getRank().getColor() + grantProcedure.getRank().getName()); + lore.add(CC.SECONDARY + "Duration&7: " + CC.PRIMARY + grantProcedure.getDuration()); + lore.add(""); + lore.add(CC.GRAY + "Click one of the items"); + lore.add(CC.GRAY + "to select grant reason."); + return new ItemBuilder(Material.NETHER_STAR).lore(CC.translate(lore)).name(CC.PRIMARY + "Grant Info").build(); + } + }); + + buttons.put(10, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.SECONDARY + "grant to " + CC.RED + "permanent" + CC.GRAY + "."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.RED + "New Staff").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("New Staff"); + } + }); + + buttons.put(11, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.GREEN + "Promote").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("Promote"); + } + }); + + buttons.put(12, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.YELLOW + "Demote").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("Demote"); + } + }); + + buttons.put(14, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.PURPLE + "Store Issues").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("Store Issues"); + } + }); + + buttons.put(15, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.GOLD + "Giveaway").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("Giveaway"); + } + }); + + buttons.put(16, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.B + CC.AQUA + "Other").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("Other"); + } + }); + + buttons.put(22, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(CC.GRAY + "Click here to set grant"); + lore.add(CC.GRAY + "grant reason to " + CC.AQUA + "custom" + CC.GRAY + "."); + return new ItemBuilder(Material.BOOK_AND_QUILL).lore(CC.translate(lore)).name(CC.B + CC.AQUA + "Custom").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.closeInventory(); + player.sendMessage(CC.SEPARATOR); + player.sendMessage(CC.SECONDARY + "Please type " + CC.PRIMARY + "reason " + CC.SECONDARY + "for this rank."); + player.sendMessage(CC.SEPARATOR); + } + }); + + buttons.put(35, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.REDSTONE).name(CC.BD_RED + "Cancel").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.chat("cancel"); + player.closeInventory(); + } + }); + + + return buttons; + } + + @Override + public int getSize() { + return 9 * 4; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantSelectMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantSelectMenu.java new file mode 100644 index 0000000..dd63fb2 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantSelectMenu.java @@ -0,0 +1,130 @@ +package me.devkevin.landcore.player.grant.menus; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.procedure.GrantProcedure; +import me.devkevin.landcore.player.grant.procedure.GrantProcedureStage; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.buttons.CloseButton; +import me.devkevin.landcore.utils.menu.pagination.PageButton; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +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.*; +import java.util.stream.Stream; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:02 + * GrantSelectMenu / land.pvp.core.player.grant.menus / LandCore + */ +@RequiredArgsConstructor +public class GrantSelectMenu extends PaginatedMenu { + + private final CoreProfile data; + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.PRIMARY + "Please select a rank"; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + buttons.put(35, new CloseButton()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Available Ranks&7: " + CC.PRIMARY + Rank.values().length); + lore.add(CC.SECONDARY + "Staff Ranks&7: " + CC.PRIMARY + "6"); + lore.add(CC.SECONDARY + "Media Ranks&7: " + CC.PRIMARY + "3"); + lore.add(CC.SECONDARY + "Donator Ranks&7: " + CC.PRIMARY + "5"); + lore.add(CC.SECONDARY + "Special Ranks&7: " + CC.PRIMARY + "3"); + lore.add(""); + lore.add(CC.GRAY + "Click one of the ranks"); + lore.add(CC.GRAY + "to start a grant procedure."); + return new ItemBuilder(Material.NETHER_STAR).lore(CC.translate(lore)).name(CC.PRIMARY + "Information").build(); + } + }); + + buttons.put(27, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.GRAY + "Click here to change"); + lore.add(CC.GRAY + "grant player."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.PRIMARY + "Change Player").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + new QuickGrantMenu().openMenu(player); + } + }); + + surroundButtons(false, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + + Stream.of(Rank.values()).sorted(Comparator.comparingInt(Rank::ordinal).reversed()).forEach(rank -> { + buttons.put(buttons.size(), new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.WOOL).durability(StringUtil.convertChatColorToWoolData(ChatColor.getByChar(rank.getColor().replace(String.valueOf('§'), "").replace("&", "").replace("o", "")))); + + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.PRIMARY + "Permissions&7: "); + lore.add(CC.GRAY + " " + CC.CIRCLE + " " + CC.SECONDARY + "landcore." + rank.getName().toLowerCase()); + lore.add(""); + lore.add(CC.SECONDARY + "Default duration&7: " + CC.PRIMARY + "Permanent"); + lore.add(""); + lore.add(CC.SECONDARY + "Right-Click to continue."); + lore.add(CC.SECONDARY + "Middle-Click to cancel procedure."); + lore.add(""); + lore.add(CC.GRAY + "Click here to grant " + rank.getColor() + rank.getName() + CC.GRAY + " rank."); + return item.name(CC.translate(rank.getColor() + rank.getName())).lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + if(clickType == ClickType.MIDDLE) { + player.closeInventory(); + } else { + player.sendMessage(CC.translate("&aYou have selected " + rank.getColor() + rank.getName() + " rank.")); + GrantProcedure grantProcedure = new GrantProcedure(rank, data, player.getName(), GrantProcedureStage.DURATION); + grantProcedure.setRank(rank); + new GrantDurationMenu(grantProcedure, data).openMenu(player); + } + } + }); + }); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 4; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantViewMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantViewMenu.java new file mode 100644 index 0000000..ac899e3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/GrantViewMenu.java @@ -0,0 +1,106 @@ +package me.devkevin.landcore.player.grant.menus; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.Grant; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.buttons.CloseButton; +import me.devkevin.landcore.utils.menu.pagination.PageButton; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:00 + * GrantViewMenu / land.pvp.core.player.grant.menus / LandCore + */ +@RequiredArgsConstructor +public class GrantViewMenu extends PaginatedMenu { + + private final CoreProfile data; + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.PRIMARY + "Viewing grants.."; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + buttons.put(26, new CloseButton()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "No additional informations."); + lore.add(""); + return new ItemBuilder(Material.NETHER_STAR).lore(CC.translate(lore)).name(CC.PRIMARY + "Information").build(); + } + }); + + + surroundButtons(false, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + + data.getGrants().stream().filter(grant -> grant.getRank() != Rank.MEMBER).sorted(Comparator.comparingLong(Grant::getAddedAt).reversed()).forEach(grant -> { + buttons.put(buttons.size(), new Button() { + @Override + public ItemStack getButtonItem(Player player) { + + List lore = new ArrayList<>(); + ItemBuilder item = (data.getRank().getName() == grant.getRank().getName() ? new ItemBuilder(Material.WOOL).durability(5) : new ItemBuilder(Material.WOOL).durability(14)); + if (data.getRank().getName() == grant.getRank().getName()) { + Player grantplayer = Bukkit.getPlayer(grant.getAddedBy()); + lore.add(""); + lore.add(CC.SECONDARY + "Rank&7: " + grant.getRank().getColor() + grant.getRank().getName()); + lore.add(CC.SECONDARY + "Expires in&7: " + CC.PRIMARY + grant.getNiceDuration()); + lore.add(CC.SECONDARY + "Added by&7: " + CC.PRIMARY + grant.getAddedBy()); + lore.add(CC.SECONDARY + "Added at&7: " + CC.PRIMARY + new Date(grant.getAddedAt())); + lore.add(CC.SECONDARY + "Reason&7: " + CC.PRIMARY + grant.getReason()); + lore.add(""); + lore.add(CC.GREEN + "This grant is active!"); + } else { + lore.add(""); + lore.add(CC.SECONDARY + "Rank&7: " + grant.getRank().getColor() + grant.getRank().getName()); + lore.add(CC.SECONDARY + "Expires in&7: " + CC.RED + "Expired"); + lore.add(CC.SECONDARY + "Added by&7: " + CC.PRIMARY + grant.getAddedBy()); + lore.add(CC.SECONDARY + "Added at&7: " + CC.PRIMARY + new Date(grant.getAddedAt())); + lore.add(CC.SECONDARY + "Reason&7: " + CC.PRIMARY + grant.getReason()); + lore.add(""); + lore.add(CC.SECONDARY + "Removed by&7: " + CC.BD_RED + "Console"); + lore.add(CC.SECONDARY + ""); + lore.add(CC.RED + "This grant is removed!"); + + } + return item.name(CC.PRIMARY + "Grant").lore(CC.translate(lore)).build(); + } + }); + }); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 3; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/QuickGrantMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/QuickGrantMenu.java new file mode 100644 index 0000000..6a5b023 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/menus/QuickGrantMenu.java @@ -0,0 +1,106 @@ +package me.devkevin.landcore.player.grant.menus; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.buttons.BackButton; +import me.devkevin.landcore.utils.menu.buttons.CloseButton; +import me.devkevin.landcore.utils.menu.pagination.PageButton; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.Bukkit; +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.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 12:56 + * QuickGrantMenu / land.pvp.core.player.grant.menus / LandCore + */ +@RequiredArgsConstructor +public class QuickGrantMenu extends PaginatedMenu { + + private CoreProfile data; + + ChatColor color; + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.PRIMARY + "Please select a player"; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + + buttons.put(27, new BackButton(new GrantSelectMenu(data))); + + buttons.put(35, new CloseButton()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Online&7: " + CC.PRIMARY + Bukkit.getOnlinePlayers().size()); + lore.add(""); + lore.add(CC.GRAY + "Click one of the players"); + lore.add(CC.GRAY + "to start a grant procedure."); + return new ItemBuilder(Material.NETHER_STAR).lore(CC.translate(lore)).name(CC.PRIMARY + "Information").build(); + } + }); + + surroundButtons(false, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + + Bukkit.getOnlinePlayers().forEach(toGrant -> { + buttons.put(buttons.size(), new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.SKULL_ITEM); + + CoreProfile data = LandCore.getInstance().getProfileManager().getProfile(toGrant.getUniqueId()); + + List lore = new ArrayList<>(); + lore.add(""); + lore.add(LandCore.getInstance().getProfileManager().getProfile(toGrant.getUniqueId()).getGrant().getRank().getColor() + toGrant.getPlayer().getName() + CC.SECONDARY + "'s current"); + lore.add(CC.SECONDARY + "rank is " + data.getRank().getColor() + data.getRank().getName()); + lore.add(""); + lore.add(CC.GREEN + "Click here to start a procedure."); + return item.name(CC.PRIMARY + toGrant.getName()).lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.performCommand("grant " + toGrant.getName()); + } + }); + }); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 4; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedure.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedure.java new file mode 100644 index 0000000..9a2ba78 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedure.java @@ -0,0 +1,46 @@ +package me.devkevin.landcore.player.grant.procedure; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import lombok.Getter; +import lombok.Setter; + +import java.util.HashSet; +import java.util.Set; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 0:36 + * GrantProcedure / land.pvp.core.rank.procedure / LandCore + */ +@Getter +@Setter +public class GrantProcedure { + + @Getter + @Setter + private static Set procedures = new HashSet<>(); + private GrantProcedureStage stage; + private Rank rank; + private long duration; + private String reason; + private CoreProfile addedTo; + private String addedBy; + + public GrantProcedure(Rank rank, CoreProfile addedTo, String addedBy, GrantProcedureStage stage) { + this.rank = rank; + this.addedTo = addedTo; + this.addedBy = addedBy; + this.stage = stage; + procedures.add(this); + } + + public static GrantProcedure getByPlayer(String name) { + for (GrantProcedure procedure : GrantProcedure.getProcedures()) { + if (procedure.getAddedBy().equalsIgnoreCase(name)) { + return procedure; + } + } + return null; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedureListener.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedureListener.java new file mode 100644 index 0000000..1d1f906 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedureListener.java @@ -0,0 +1,61 @@ +package me.devkevin.landcore.player.grant.procedure; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.grant.menus.GrantConfirmMenu; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.time.TimeFormatUtils; +import lombok.RequiredArgsConstructor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.inventory.Inventory; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 12:09 + * GrantProcedureListener / land.pvp.core.player.grant.procedure / LandCore + */ +@RequiredArgsConstructor +public class GrantProcedureListener implements Listener { + private final LandCore plugin; + + @EventHandler + public void onChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + GrantProcedure grantProcedure = GrantProcedure.getByPlayer(player.getName()); + + if (grantProcedure != null) { + if (grantProcedure.getStage() == GrantProcedureStage.DURATION) { + event.setCancelled(true); + if (event.getMessage().equalsIgnoreCase("cancel")) { + GrantProcedure.getProcedures().remove(grantProcedure); + player.sendMessage(CC.RED + "You have cancelled grant procedure."); + return; + } + if (event.getMessage().equalsIgnoreCase("perm")) { + grantProcedure.setDuration(-1L); + grantProcedure.setStage(GrantProcedureStage.REASON); + player.sendMessage(CC.SECONDARY + "You have entered " + CC.PRIMARY + "perm" + CC.SECONDARY + " as your duration. Please enter your grant " + CC.PRIMARY + "reason" + CC.SECONDARY + "."); + return; + } + grantProcedure.setDuration(System.currentTimeMillis() + TimeFormatUtils.parseTime(event.getMessage())); + grantProcedure.setStage(GrantProcedureStage.REASON); + player.sendMessage(CC.SECONDARY + "You have entered " + CC.PRIMARY + (System.currentTimeMillis() + TimeFormatUtils.parseTime(event.getMessage()) + CC.SECONDARY + " as your duration. Please enter your grant " + CC.PRIMARY + "reason" + CC.SECONDARY + ".")); + } else if (grantProcedure.getStage() == GrantProcedureStage.REASON) { + event.setCancelled(true); + + if (event.getMessage().equalsIgnoreCase("cancel")) { + GrantProcedure.getProcedures().remove(grantProcedure); + player.sendMessage(CC.RED + "You have cancelled grant procedure."); + return; + } + grantProcedure.setStage(GrantProcedureStage.CONFIRMATION); + grantProcedure.setReason(event.getMessage()); + player.sendMessage(CC.SECONDARY + "You have entered " + CC.PRIMARY + event.getMessage() + CC.SECONDARY + " as a reason."); + new GrantConfirmMenu(grantProcedure).openMenu(player); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedureStage.java b/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedureStage.java new file mode 100644 index 0000000..e280462 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/grant/procedure/GrantProcedureStage.java @@ -0,0 +1,10 @@ +package me.devkevin.landcore.player.grant.procedure; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 0:37 + * GrantProcedureStage / land.pvp.core.rank.procedure / LandCore + */ +public enum GrantProcedureStage { + DURATION, REASON, CONFIRMATION +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/info/UserCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/info/UserCommand.java new file mode 100644 index 0000000..f99cae5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/info/UserCommand.java @@ -0,0 +1,39 @@ +package me.devkevin.landcore.player.info; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.info.menu.UserViewMenu; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 19:51 + * UserCommand / land.pvp.core.player.info / LandCore + */ +public class UserCommand extends PlayerCommand { + private final LandCore plugin; + + public UserCommand(LandCore plugin) { + super("user", Rank.TRIAL_MOD); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /user "); + } + + + @Override + public void execute(Player player, String[] args) { + if (args.length == 0) { + player.sendMessage(usageMessage); + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + CoreProfile coreProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + new UserViewMenu(coreProfile).openMenu(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/info/menu/UserViewMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/info/menu/UserViewMenu.java new file mode 100644 index 0000000..488d332 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/info/menu/UserViewMenu.java @@ -0,0 +1,161 @@ +package me.devkevin.landcore.player.info.menu; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.ButtonSound; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.menu.buttons.CloseButton; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +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.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 19:54 + * UserViewMenu / land.pvp.core.player.info.menu / LandCore + */ +@RequiredArgsConstructor +public class UserViewMenu extends Menu { + + { + setAutoUpdate(true); + } + + private final CoreProfile data; + + @Override + public String getTitle(Player player) { + return CC.PRIMARY + "User Menu -> " + data.getName(); + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(26, new CloseButton()); + + surroundButtons(true, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.NETHER_STAR); + + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Player&7: " + CC.PRIMARY + data.getName()); + lore.add(""); + + return item.name(CC.PRIMARY + "Information").lore(CC.translate(lore)).build(); + } + }); + + buttons.put(10, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.QUARTZ); + + List lore = new ArrayList<>(); + + lore.add(""); + lore.add(CC.SECONDARY + "Current rank is " + data.getRank().getColor() + data.getRank().getName()); + lore.add(""); + lore.add(CC.PRIMARY + "Information&7: "); + lore.add(CC.SECONDARY + " Added by&7: " + CC.PRIMARY + data.getGrant().getAddedBy()); + lore.add(CC.SECONDARY + " Reason&7: " + CC.PRIMARY + data.getGrant().getReason()); + lore.add(""); + lore.add(CC.GRAY + "Click here to view more info."); + + return item.name(CC.PRIMARY + "Rank Info").lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.performCommand("grants " + data.getName()); + playSound(player, ButtonSound.CLICK); + } + }); + + buttons.put(11, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.WOOL).durability(14); + + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Active&7: " + CC.GREEN + "No"); + lore.add(CC.SECONDARY + "Number of punishments&7: " + CC.PRIMARY + "5"); + lore.add(CC.SECONDARY + "Last punishment&7: " + CC.PRIMARY + "Permanent Mute"); + lore.add(""); + lore.add(CC.GRAY + "Click here to view more info."); + + return item.name(CC.PRIMARY + "Punishment Info").lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + //todo + } + }); + + buttons.put(12, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.BLAZE_POWDER); + + List lore = new ArrayList<>(); + + lore.add(""); + lore.add(CC.SECONDARY + "Prefix&7: " + CC.PRIMARY + data.getGrant().getRank().getRawFormat()); + lore.add(CC.SECONDARY + "Color&7: " + data.getGrant().getRank().getColor() + data.getGrant().getRank().getName()); + lore.add(CC.SECONDARY + "Booster&7: " + CC.PRIMARY + "None"); + lore.add(""); + lore.add(CC.GRAY + "Click here to view more info."); + + return item.name(CC.PRIMARY + "Cosmetics Info").lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + } + }); + + buttons.put(13, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.EMERALD); + + List lore = new ArrayList<>(); + + lore.add(""); + lore.add(CC.SECONDARY + "Balance&7: " + CC.PRIMARY + " 0"); + lore.add(""); + lore.add(CC.GRAY + "Click here to view more info."); + + return item.name(CC.PRIMARY + "Gems Info").lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + } + }); + + + return buttons; + } + + + @Override + public int getSize() { + return 9 * 3; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/Note.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/Note.java new file mode 100644 index 0000000..c76d38b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/Note.java @@ -0,0 +1,35 @@ +package me.devkevin.landcore.player.notes; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.devkevin.landcore.player.notes.json.NoteJsonDeSerializer; +import me.devkevin.landcore.player.notes.json.NoteJsonSerializer; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:37 + * Note / me.devkevin.landcore.player.notes / LandCore + */ +@Getter +@Setter +@NoArgsConstructor +public class Note { + public static NoteJsonSerializer SERIALIZER = new NoteJsonSerializer(); + public static NoteJsonDeSerializer DESERIALIZER = new NoteJsonDeSerializer(); + + private int id; + private long createAt; + private String createBy; + private String updateBy; + private long updateAt; + private String note; + + public Note(int id, String note, Player staff) { + this.id = id; + this.note = note; + this.createAt = System.currentTimeMillis(); + this.createBy = staff.getName(); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NoteAddCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NoteAddCommand.java new file mode 100644 index 0000000..d5a9dce --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NoteAddCommand.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.player.notes.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.notes.Note; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:57 + * NoteAddCommand / me.devkevin.landcore.player.notes.commands / LandCore + */ +public class NoteAddCommand extends PlayerCommand { + private final LandCore plugin; + + public NoteAddCommand(LandCore plugin) { + super("note.add", Rank.TRIAL_MOD); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /note.add "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length == 0) { + player.sendMessage(usageMessage); + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + int id = targetProfile.getNotes().size() + 1; + targetProfile.getNotes().add(new Note(id, args[1], player)); + player.sendMessage(CC.GREEN + "You has been added a Note to " + targetProfile.getGrant().getRank().getColor() + targetProfile.getName()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NoteRemoveCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NoteRemoveCommand.java new file mode 100644 index 0000000..bfff68c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NoteRemoveCommand.java @@ -0,0 +1,39 @@ +package me.devkevin.landcore.player.notes.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 3:02 + * NoteRemoveCommand / me.devkevin.landcore.player.notes.commands / LandCore + */ +public class NoteRemoveCommand extends PlayerCommand { + private final LandCore plugin; + + public NoteRemoveCommand(LandCore plugin) { + super("note.remove", Rank.TRIAL_MOD); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /note.remove "); + } + + @Override + public void execute(Player player, String[] args) { + Player target = plugin.getServer().getPlayer(args[0]); + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + Number noteID = Integer.parseInt(args[1]); + + if (!targetProfile.removeNote(noteID.intValue())) { + player.sendMessage(CC.translate("&7That note doesn't exist.")); + return; + } + + player.sendMessage(CC.RED + "You've deleted Note #" + noteID + " of " + targetProfile.getGrant().getRank().getColor() + targetProfile.getName()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NotesCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NotesCommand.java new file mode 100644 index 0000000..6ddb815 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/commands/NotesCommand.java @@ -0,0 +1,37 @@ +package me.devkevin.landcore.player.notes.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.notes.menu.NotesMenu; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 3:00 + * NotesCommand / me.devkevin.landcore.player.notes.commands / LandCore + */ +public class NotesCommand extends PlayerCommand { + private final LandCore plugin; + + public NotesCommand(LandCore plugin) { + super("notes", Rank.TRIAL_MOD); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + Player target = plugin.getServer().getPlayer(args[0]); + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.getNotes().isEmpty()) { + player.sendMessage(targetProfile.getGrant().getRank().getColor() + targetProfile.getName() + CC.RED + " has no notes."); + return; + } + + new NotesMenu(targetProfile).openMenu(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/json/NoteJsonDeSerializer.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/json/NoteJsonDeSerializer.java new file mode 100644 index 0000000..7e197f5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/json/NoteJsonDeSerializer.java @@ -0,0 +1,29 @@ +package me.devkevin.landcore.player.notes.json; + +import com.google.gson.JsonObject; +import me.devkevin.landcore.player.notes.Note; +import me.devkevin.landcore.utils.json.JsonDeserializer; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:40 + * NoteJsonDeSerializer / me.devkevin.landcore.player.notes.json / LandCore + */ +public class NoteJsonDeSerializer implements JsonDeserializer { + @Override + public Note deserialize(JsonObject object) { + Note note = new Note(); + + note.setId(object.get("id").getAsInt()); + note.setCreateAt(object.get("createAt").getAsInt()); + note.setCreateBy(object.get("createBy").getAsString()); + note.setNote(object.get("note").getAsString()); + + if (object.get("UpdateBy") != null) { + note.setUpdateBy(object.get("createBy").getAsString()); + note.setUpdateAt(object.get("createAt").getAsInt()); + } + + return note; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/json/NoteJsonSerializer.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/json/NoteJsonSerializer.java new file mode 100644 index 0000000..ea5f57e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/json/NoteJsonSerializer.java @@ -0,0 +1,29 @@ +package me.devkevin.landcore.player.notes.json; + +import com.google.gson.JsonObject; +import me.devkevin.landcore.player.notes.Note; +import me.devkevin.landcore.utils.json.JsonSerializer; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:38 + * NoteJsonSerializer / me.devkevin.landcore.player.notes.json / LandCore + */ +public class NoteJsonSerializer implements JsonSerializer { + @Override + public JsonObject serialize(Note note) { + JsonObject object = new JsonObject(); + + object.addProperty("id", note.getId()); + object.addProperty("createAt", note.getCreateAt()); + object.addProperty("createBy", note.getCreateBy()); + object.addProperty("note", note.getNote()); + + if (note.getCreateBy() != null) { + object.addProperty("UpdateBy", note.getUpdateBy()); + object.addProperty("UpdateAt", note.getUpdateAt()); + } + + return object; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/notes/menu/NotesMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/notes/menu/NotesMenu.java new file mode 100644 index 0000000..ac5e59d --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/notes/menu/NotesMenu.java @@ -0,0 +1,59 @@ +package me.devkevin.landcore.player.notes.menu; + +import com.google.common.collect.Maps; +import lombok.AllArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.notes.Note; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.time.TimeUtil; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Date; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:51 + * NotesMenu / me.devkevin.landcore.player.notes.menu / LandCore + */ +@AllArgsConstructor +public class NotesMenu extends PaginatedMenu { + private CoreProfile coreProfile; + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.PRIMARY + "Notes of " + coreProfile.getGrant().getRank().getColor() + coreProfile.getName(); + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = Maps.newHashMap(); + + for (Note note : coreProfile.getNotes()) { + buttons.put(buttons.size(), new NoteButton(note)); + } + + return buttons; + } + + @AllArgsConstructor + private static class NoteButton extends Button { + private Note note; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.PAPER) + .name(CC.translate("&eNote ID&7:&f " + note.getId())) + .lore(CC.translate("&eCreate by&7:&f " + note.getCreateBy())) + .lore(CC.translate("&eNote&7:&f " + note.getNote())) + .lore(CC.translate("&eCreate at&7:&f " + TimeUtil.dateToString(new Date(note.getCreateAt()), "&7"))) + .build(); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/Rank.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/Rank.java new file mode 100644 index 0000000..78f9676 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/Rank.java @@ -0,0 +1,86 @@ +package me.devkevin.landcore.player.rank; + +import me.devkevin.landcore.utils.PlayerList; +import me.devkevin.landcore.utils.message.CC; +import lombok.Getter; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public enum Rank { + + MEMBER("Member", CC.GREEN, CC.GREEN, 1), + + //DONOR RANKS + BASIC("Basic", CC.BLUE + "✦", CC.GREEN, 2), + GOLD("Gold",CC.YELLOW + "✯", CC.GOLD, 3), + EMERALD("Emerald", CC.GREEN + "✵", CC.DARK_GREEN, 4), + DIAMOND("Diamond",CC.AQUA + "❇", CC.D_AQUA,5), + LOL("LOL", CC.GOLD + "❊", CC.YELLOW, 6), + + + // MEDIA RANKS + MEDIA("Media", CC.D_GRAY + "[" + CC.PINK + "Media" + CC.D_GRAY + "] ", CC.PINK, 7), + YOUTUBER("Youtuber", CC.D_GRAY + "[" + CC.WHITE + "You" + CC.RED + "tuber" + CC.D_GRAY + "] ", CC.RED, 8), + TWITCH("Twitch", CC.D_GRAY + "[" + CC.PURPLE + "Twitch" + CC.D_GRAY + "] ", CC.PURPLE, 9), + FAMOUS("Famous", CC.PURPLE + "✳", CC.DARK_GREEN, 10), + PARTNER("Partner", CC.D_GRAY + "[" + CC.BLUE + "Partner" + CC.D_GRAY + "] ", CC.BLUE, 11), + MEDIA_OWNER("Media-Owner",CC.D_GRAY + "[" + CC.D_RED + "Owner" + CC.D_GRAY + "] ", CC.D_RED, 12), + + // STAFF RANK + BUILDER("Builder", CC.D_GRAY + "[" + CC.DARK_GREEN + "Builder" + CC.D_GRAY + "] ", CC.DARK_GREEN + CC.I, 13), + HOST("Host",CC.D_GRAY + "[" + CC.PURPLE + CC.I + "Host" + CC.D_GRAY + "] ", CC.PURPLE + CC.I, 14), + TRIAL_MOD("Trainee",CC.D_GRAY + "[" + CC.YELLOW + CC.I + "Trainee" + CC.D_GRAY + "] ", CC.YELLOW + CC.I, 15), + MOD("Mod", CC.D_GRAY + "[" + CC.D_AQUA + CC.I + "Mod" + CC.D_GRAY + "] ", CC.D_AQUA + CC.I , 16), + SENIOR_HOST("Senior-Host", CC.D_GRAY + "[" + CC.PURPLE + CC.I + "Senior Host" + CC.D_GRAY + "] ", CC.PURPLE + CC.I, 17), + SENIOR_MOD("Senior-Mod", CC.D_GRAY + "[" + CC.D_AQUA + CC.I + "Senior Mod" + CC.D_GRAY + "] ", CC.PURPLE + CC.I, 18), + ADMIN("Admin", CC.D_GRAY + "[" + CC.RED + "Admin" + CC.D_GRAY + "] ", CC.RED + CC.I, 19), + SENIOR_ADMIN("Senior-Admin", CC.D_GRAY + "[" + CC.RED + CC.I + "Senior Admin" + CC.D_GRAY + "] ", CC.RED + CC.I, 20), + MANAGER("Manager", CC.D_GRAY + "[" + CC.D_RED + CC.I + "Manager" + CC.D_GRAY + "] ", CC.D_RED + CC.I, 21), + DEVELOPER("Developer", CC.D_GRAY + "[" + CC.AQUA + CC.I + "Developer" + CC.D_GRAY + "] ", CC.AQUA + CC.I, 22), + OWNER("Owner", CC.D_GRAY + "[" + CC.D_RED + CC.I + "Owner" + CC.D_GRAY + "] ", CC.D_RED + CC.I, 23); + + private final String name; + private final String rawFormat; + private final String format; + private final String color; + private final List permissions; + private final int weight; + + Rank(String name, String rawFormat, String color, int weight) { + this.name = name; + this.rawFormat = rawFormat; + this.format = String.format(rawFormat, color, color); + this.color = color; + this.permissions = new ArrayList<>(); + this.weight = weight; + } + + public List getPermissions() { + return permissions; + } + + public static Rank getByName(String name) { + for (Rank rank : values()) { + if (rank.getName().equalsIgnoreCase(name)) { + return rank; + } + } + + return null; + } + + public void apply(Player player) { + String coloredName = color + player.getName(); + + player.setPlayerListName(coloredName); + player.setDisplayName(coloredName); + } + + public static void importRanks() { + CC.logConsole(CC.PRIMARY + "[LandCore] " + CC.SECONDARY + "Successfully imported " + CC.PRIMARY + values().length + CC.SECONDARY + " ranks."); + CC.logConsole(CC.PRIMARY + "[LandCore] " + PlayerList.ORDERED_RANKS); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/GrantCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/GrantCommand.java new file mode 100644 index 0000000..f67e52f --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/GrantCommand.java @@ -0,0 +1,43 @@ +package me.devkevin.landcore.player.rank.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.menus.GrantSelectMenu; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 19/01/2023 @ 0:27 + * GrantCommand / land.pvp.core.player.rank.commands / LandCore + */ +public class GrantCommand extends PlayerCommand { + private final LandCore plugin; + + public GrantCommand(LandCore plugin) { + super("grant", Rank.ADMIN); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /grant "); + } + + @Override + public void execute(Player player, String[] args) { + if (args.length == 0) { + player.sendMessage(usageMessage); + return; + } + + Player target = plugin.getServer().getPlayer(args[0]); + + if (target == null || !target.isOnline()) { + assert target != null; + player.sendMessage(CC.RED + "No player matching " + CC.YELLOW + target.getName() + CC.RED + " is connected to this server"); + return; + } + + CoreProfile coreProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + new GrantSelectMenu(coreProfile).openMenu(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/GrantsCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/GrantsCommand.java new file mode 100644 index 0000000..fb92755 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/GrantsCommand.java @@ -0,0 +1,46 @@ +package me.devkevin.landcore.player.rank.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.menus.GrantViewMenu; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.TaskUtil; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:19 + * GrantsCommand / land.pvp.core.player.rank.commands / LandCore + */ +public class GrantsCommand extends PlayerCommand { + private final LandCore plugin; + + public GrantsCommand(LandCore plugin) { + super("grants", Rank.MANAGER); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + TaskUtil.run(() -> { + Player target = plugin.getServer().getPlayer(args[0]); + + if (target == null || !target.isOnline()) { + assert target != null; + player.sendMessage(CC.RED + "No player matching " + CC.YELLOW + target.getName() + CC.RED + " is connected to this server"); + return; + } + + CoreProfile coreProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + + if (coreProfile.getGrants().isEmpty()) { + player.sendMessage(CC.translate("&cThat player has &l0 &cgrants.")); + return; + } + + new GrantViewMenu(coreProfile).openMenu(player); + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/QuickGrantCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/QuickGrantCommand.java new file mode 100644 index 0000000..73eb1b4 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/QuickGrantCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.player.rank.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.grant.menus.QuickGrantMenu; +import me.devkevin.landcore.player.rank.Rank; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 13:22 + * QuickGrantCommand / land.pvp.core.player.rank.commands / LandCore + */ +public class QuickGrantCommand extends PlayerCommand { + private final LandCore plugin; + + public QuickGrantCommand(LandCore plugin) { + super("qgrant", Rank.MANAGER); + this.plugin = plugin; + } + + @Override + public void execute(Player player, String[] args) { + new QuickGrantMenu().openMenu(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/RankCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/RankCommand.java new file mode 100644 index 0000000..ed5a4f4 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/RankCommand.java @@ -0,0 +1,74 @@ +package me.devkevin.landcore.player.rank.commands; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.BaseCommand; +import me.devkevin.landcore.event.player.PlayerRankChangeEvent; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.Grant; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.TaskUtil; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.time.TimeFormatUtils; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class RankCommand extends BaseCommand { + private final LandCore plugin; + + public RankCommand(LandCore plugin) { + super("rank", Rank.ADMIN); + this.plugin = plugin; + setUsage(CC.RED + "Usage: /rank "); + } + + @Override + protected void execute(CommandSender sender, String[] args) { + TaskUtil.runAsync(() -> { + Grant grant; + if (args.length < 4) { + sender.sendMessage(CC.translate("&cInvalid usage: /setrank ")); + return; + } + Player target = Bukkit.getPlayer(args[0]); + + if (target == null || !target.isOnline()) { + assert target != null; + sender.sendMessage(CC.RED + "No player matching " + CC.YELLOW + target.getName() + CC.RED + " is connected to this server"); + return; + } + + CoreProfile targetProfile = plugin.getProfileManager().getProfile(target.getUniqueId()); + Rank rank = Rank.getByName(args[1]); + + if (rank == null) { + sender.sendMessage(CC.translate("&cThat rank doesn't exist.")); + return; + } + + StringBuilder builder = new StringBuilder(); + for (int i = 3; i < args.length; i++) + builder.append(args[i]).append(" "); + + String reason = builder.toString().trim(); + + long duration = TimeFormatUtils.parseTime(args[2]); + + if (duration == -1L) { + grant = new Grant(rank, -1L, System.currentTimeMillis(), sender.getName(), reason); + } else { + grant = new Grant(rank, System.currentTimeMillis() + duration, System.currentTimeMillis(), sender.getName(), reason); + } + + targetProfile.setGrant(grant); + targetProfile.getGrants().add(grant); + + plugin.getServer().getPluginManager().callEvent(new PlayerRankChangeEvent(target, targetProfile, grant, grant.getDuration())); + + sender.sendMessage(CC.translate("&aYou have set &e" + target.getName() + " &arank to " + rank.getColor() + rank.getName())); + target.sendMessage(CC.translate("&aYour rank has been set to " + rank.getColor() + rank.getName())); + + targetProfile.save(true); + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/RankListCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/RankListCommand.java new file mode 100644 index 0000000..c2fcce7 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/commands/RankListCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.player.rank.commands; + +import me.devkevin.landcore.commands.PlayerCommand; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.player.rank.menu.RankListMenu; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 21/01/2023 @ 1:43 + * RankListCommand / me.devkevin.landcore.player.rank.commands / LandCore + */ +public class RankListCommand extends PlayerCommand { + private CoreProfile coreProfile; + + public RankListCommand() { + super("ranklist", Rank.MANAGER); + setAliases("ranks"); + } + + @Override + public void execute(Player player, String[] args) { + new RankListMenu(coreProfile).openMenu(player); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/rank/menu/RankListMenu.java b/LandCore/src/main/java/me/devkevin/landcore/player/rank/menu/RankListMenu.java new file mode 100644 index 0000000..6e84a73 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/rank/menu/RankListMenu.java @@ -0,0 +1,130 @@ +package me.devkevin.landcore.player.rank.menu; + +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.grant.menus.QuickGrantMenu; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.Clickable; +import me.devkevin.landcore.utils.StringUtil; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.buttons.CloseButton; +import me.devkevin.landcore.utils.menu.pagination.PageButton; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +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.*; +import java.util.stream.Stream; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 12:20 + * RankListMenu / land.pvp.core.player.rank.menu / LandCore + */ +@RequiredArgsConstructor +public class RankListMenu extends PaginatedMenu { + + private final CoreProfile coreProfile; + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.PRIMARY + "Rank List"; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + buttons.put(35, new CloseButton()); + + buttons.put(4, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Available Ranks&7: " + CC.PRIMARY + Rank.values().length); + lore.add(CC.SECONDARY + "Staff Ranks&7: " + CC.PRIMARY + "6"); + lore.add(CC.SECONDARY + "Media Ranks&7: " + CC.PRIMARY + "3"); + lore.add(CC.SECONDARY + "Donator Ranks&7: " + CC.PRIMARY + "5"); + lore.add(CC.SECONDARY + "Special Ranks&7: " + CC.PRIMARY + "3"); + return new ItemBuilder(Material.NETHER_STAR).lore(CC.translate(lore)).name(CC.PRIMARY + "Information").build(); + } + }); + + buttons.put(27, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.GRAY + "Click here to change"); + lore.add(CC.GRAY + "make a grant."); + return new ItemBuilder(Material.PAPER).lore(CC.translate(lore)).name(CC.PRIMARY + "Make Grant").build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + new QuickGrantMenu().openMenu(player); + } + }); + + surroundButtons(false, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(7).build()); + + return buttons; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + + Stream.of(Rank.values()).sorted(Comparator.comparingInt(Rank::ordinal).reversed()).forEach(rank -> { + buttons.put(buttons.size(), new Button() { + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.WOOL).durability(StringUtil.convertChatColorToWoolData(ChatColor.getByChar(rank.getColor().replace(String.valueOf('§'), "").replace("&", "").replace("o", "")))); + + List lore = new ArrayList<>(); + lore.add(""); + lore.add(CC.SECONDARY + "Color&7: " + rank.getColor() + "Color"); + lore.add(CC.SECONDARY + "Prefix&7: " + rank.getRawFormat()); + lore.add(""); + lore.add(CC.PRIMARY + "Permissions&7: "); + lore.add(CC.GRAY + " " + CC.CIRCLE + " " + CC.SECONDARY + "landcore." + rank.getName().toLowerCase()); + lore.add(""); + lore.add(CC.GRAY + "Click here to see"); + lore.add(CC.GRAY + "chat preview of this rank."); + return item.name(CC.translate(rank.getColor() + rank.getName())).lore(CC.translate(lore)).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + Clickable clickable = new Clickable(); + player.closeInventory(); + player.sendMessage(CC.GRAY + CC.SEPARATOR); + player.sendMessage(CC.PRIMARY + "Rank Preview" + CC.GRAY +":"); + player.sendMessage(CC.translate(CC.SECONDARY + " With Tag&7: " + "&7[&6&lG&e&lG&7] " + rank.getRawFormat() + rank.getColor() + rank.getName() + CC.GRAY + ": " + CC.WHITE + "Hello there!")); + player.sendMessage(CC.translate(CC.SECONDARY + " Without Tag&7: " + rank.getRawFormat() + rank.getColor() + rank.getName() + CC.GRAY + ": " + CC.WHITE + "Hello there!")); + player.sendMessage(""); + player.sendMessage(CC.SECONDARY + "Showed preview for " + rank.getColor() + rank.getName() + CC.SECONDARY + " rank."); + + clickable.add("&a&lClick to reopen!", "&aClick to open rank list menu!", "/ranklist"); + clickable.sendToPlayer(player); + player.sendMessage(CC.GRAY + CC.SEPARATOR); + } + }); + }); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 4; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/tags/PrefixCommand.java b/LandCore/src/main/java/me/devkevin/landcore/player/tags/PrefixCommand.java new file mode 100644 index 0000000..cf9055a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/tags/PrefixCommand.java @@ -0,0 +1,25 @@ +package me.devkevin.landcore.player.tags; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.commands.PlayerCommand; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 4:09 + * PrefixCommand / me.devkevin.landcore.player.tags / LandCore + */ +public class PrefixCommand extends PlayerCommand { + private final LandCore plugin; + + public PrefixCommand(LandCore plugin) { + super("prefix"); + this.plugin = plugin; + setAliases("symbols", "tags"); + } + + @Override + public void execute(Player player, String[] args) { + player.openInventory(this.plugin.getPrefixMenu().getMenu(player).getCurrentPage()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/CountriesPrefix.java b/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/CountriesPrefix.java new file mode 100644 index 0000000..b810e53 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/CountriesPrefix.java @@ -0,0 +1,56 @@ +package me.devkevin.landcore.player.tags.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 4:06 + * CountriesPrefix / me.devkevin.landcore.player.tags / LandCore + */ +@Getter +@AllArgsConstructor +public enum CountriesPrefix { + ESP(0, CC.RED + CC.B + "E" + CC.YELLOW + CC.B + "S" + CC.RED + CC.B + "P", Rank.BASIC), + MEX(1, CC.DARK_GREEN + CC.B + "M" + CC.WHITE + CC.B + "E" + CC.D_RED + CC.B + "X", Rank.BASIC), + ARG(2, CC.AQUA + CC.B + "A" + CC.WHITE + CC.B + "R" + CC.AQUA + CC.B + "G", Rank.BASIC), + USA(3, CC.D_RED + CC.B + "U" + CC.WHITE + CC.B + "S" + CC.BLUE + CC.B + "A", Rank.BASIC), + CRC(4, CC.D_BLUE + CC.B + "C" + CC.D_RED + CC.B + "R" + CC.D_BLUE + CC.B + "C", Rank.BASIC), + BOL(5, CC.D_RED + CC.B + "B" + CC.YELLOW + CC.B + "O" + CC.DARK_GREEN + CC.B + "L", Rank.BASIC), + BRZ(6, CC.DARK_GREEN + CC.B + "B" + CC.YELLOW + CC.B + "R" + CC.BLUE + CC.B + "Z", Rank.BASIC), + CAN(7, CC.RED + CC.B + "C" + CC.WHITE + CC.B + "A" + CC.RED + CC.B + "N", Rank.BASIC), + CHL(8, CC.BLUE + CC.B + "C" + CC.WHITE + CC.B + "H" + CC.D_RED + CC.B + "L", Rank.BASIC), + COL(9, CC.YELLOW + CC.B + "C" + CC.BLUE + CC.B + "O" + CC.D_RED + CC.B + "L", Rank.BASIC), + ENG(10, CC.WHITE + CC.B + "E" + CC.RED + CC.B + "N" + CC.WHITE + CC.B + "G", Rank.BASIC), + ECU(11, CC.YELLOW + CC.B + "E" + CC.BLUE + CC.B + "C" + CC.D_RED + CC.B + "N", Rank.BASIC), + EU(12, CC.BLUE + CC.B + "EU" + CC.YELLOW + CC.B + "★", Rank.BASIC), + FRA(13, CC.BLUE + CC.B + "F" + CC.WHITE + CC.B + "R" + CC.D_RED + CC.B + "A", Rank.BASIC), + GER(14, CC.D_GRAY + CC.B + "G" + CC.D_RED + CC.B + "E" + CC.YELLOW + CC.B + "R", Rank.BASIC), + GTM(15, CC.D_AQUA + CC.B + "G" + CC.WHITE + CC.B + "T" + CC.D_AQUA + CC.B + "M", Rank.BASIC), + HN(16, CC.BLUE + CC.B + "H" + CC.WHITE + CC.B + "N", Rank.BASIC), + ITA(17, CC.DARK_GREEN + CC.B + "I" + CC.WHITE + CC.B + "T" + CC.D_RED + CC.B + "A", Rank.BASIC), + PAR(18, CC.D_RED + CC.B + "P" + CC.WHITE + CC.B + "A" + CC.BLUE + CC.B + "R", Rank.BASIC), + PER(19,CC.D_RED + CC.B + "P" + CC.WHITE + CC.B + "E" + CC.D_RED + CC.B + "R", Rank.BASIC), + PR(20, CC.BLUE + CC.B + "P" + CC.D_RED + CC.B + "R", Rank.BASIC), + RD(21, CC.BLUE + CC.B + "R" + CC.D_RED + CC.B + "D", Rank.BASIC), + UY(22, CC.WHITE + CC.B + "U" + CC.AQUA + CC.B + "Y", Rank.BASIC), + VNZ(23, CC.YELLOW + CC.B + "V" + CC.BLUE + CC.B + "N" + CC.D_RED + "Z", Rank.BASIC); + + private final int id; + private final String prefix; + private final Rank rank; + + public static CountriesPrefix getPrefixOrDefault(String name) { + CountriesPrefix prefix; + + try { + prefix = CountriesPrefix.valueOf(name.toUpperCase()); + } catch (Exception e) { + prefix = CountriesPrefix.ESP; + } + + return prefix; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/SymbolPrefix.java b/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/SymbolPrefix.java new file mode 100644 index 0000000..37a065d --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/SymbolPrefix.java @@ -0,0 +1,44 @@ +package me.devkevin.landcore.player.tags.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 3:50 + * SymbolPrefix / me.devkevin.landcore.player.tags / LandCore + */ +@Getter +@AllArgsConstructor +public enum SymbolPrefix { + LOVE(0, CC.RED + " ❤", Rank.BASIC), + START(1, CC.GOLD + CC.B + " ★", Rank.BASIC), + DOLLAR(2, CC.DARK_GREEN + CC.B + " $", Rank.BASIC), + XXX(3, CC.BLACK + CC.B + " ✖✖✖", Rank.BASIC), + OTAKU(4, CC.PINK + CC.B + " 。◕‿ ◕。", Rank.BASIC), + TREBOL(5, CC.DARK_GREEN + CC.B + " ♣", Rank.BASIC), + SYMBOL_1(6, CC.B + CC.B + " ^◕‿◕^", Rank.BASIC), + SYMBOL_2(7, CC.B + CC.B + " (◕^^◕)", Rank.BASIC), + KING(8, CC.GOLD + CC.B + " ♛", Rank.BASIC), + PEACE(9, CC.YELLOW + CC.B + " ✌", Rank.BASIC), + TOXIC(10, CC.YELLOW + CC.B + " ☢", Rank.BASIC), + PLUS(11, CC.GREEN + CC.B + " ✚", Rank.BASIC); + + private final int id; + private final String prefix; + private final Rank rank; + + public static SymbolPrefix getPrefixOrDefault(String name) { + SymbolPrefix prefix; + + try { + prefix = SymbolPrefix.valueOf(name.toUpperCase()); + } catch (Exception e) { + prefix = SymbolPrefix.LOVE; + } + + return prefix; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/TextSymbolPrefix.java b/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/TextSymbolPrefix.java new file mode 100644 index 0000000..87a0ccb --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/player/tags/enums/TextSymbolPrefix.java @@ -0,0 +1,33 @@ +package me.devkevin.landcore.player.tags.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 06/02/2023 @ 3:45 + * TextSymbolPrefix / me.devkevin.landcore.player.tags / LandCore + */ +@Getter +@AllArgsConstructor +public enum TextSymbolPrefix { + LOLGANG(0, CC.GOLD + " #LOLGang", Rank.BASIC), + L(1, CC.RED + CC.B + " L", Rank.BASIC), + GG(2, CC.YELLOW + " GG", Rank.BASIC), + EZ(3, CC.AQUA + " EZ", Rank.BASIC), + DAB(4, CC.RED + " { + if (LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).hasRank(Rank.TRIAL_MOD)) { + player.sendMessage(CC.GRAY + "[Silent] " + + profile.getGrant().getRank().getColor() + target.getName() + CC.GREEN + " has been " + getContext() + " by " + sender); + } + }); + } else { + Bukkit.broadcastMessage(profile.getGrant().getRank().getColor() + target.getName() + CC.GREEN + " has been " + getContext() + " by " + sender); + } + } + + public String getKickMessage() { + String kickMessage; + + if (type == PunishmentType.BAN) { + kickMessage = "&cYour account is {context} from PracLOL.{temporary}\n\n&cIf you feel this punishment is unjust, you may appeal at:\n&ehttps://www.prac.lol"; + String temporary = ""; + + if (!isPermanent()) { + temporary = "\n&cThis punishment expires in &e{time-remaining}&c."; + temporary = temporary.replace("{time-remaining}", getTimeRemaining()); + } + + kickMessage = kickMessage.replace("{context}", getContext()) + .replace("{temporary}", temporary); + } else if (type == PunishmentType.KICK) { + kickMessage = "&cYou were kicked by a staff member.\nReason: &e" + addedReason; + } else { + kickMessage = null; + } + + return CC.translate(kickMessage); + } + + @Override + public boolean equals(Object object) { + return object instanceof Punishment && ((Punishment) object).uuid.equals(uuid); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentJsonDeserializer.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentJsonDeserializer.java new file mode 100644 index 0000000..a4387bc --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentJsonDeserializer.java @@ -0,0 +1,47 @@ +package me.devkevin.landcore.punishment; + +import com.google.gson.JsonObject; +import me.devkevin.landcore.utils.json.JsonDeserializer; + +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:31 + * PunishmentJsonDeserializer / me.devkevin.landcore.punishment / LandCore + */ +public class PunishmentJsonDeserializer implements JsonDeserializer { + + @Override + public Punishment deserialize(JsonObject object) { + Punishment punishment = new Punishment( + UUID.fromString(object.get("uuid").getAsString()), + PunishmentType.valueOf(object.get("type").getAsString()), + object.get("addedAt").getAsLong(), + object.get("addedReason").getAsString(), + object.get("duration").getAsLong() + ); + + if (!object.get("addedBy").isJsonNull()) { + punishment.setAddedBy(UUID.fromString(object.get("addedBy").getAsString())); + } + + if (!object.get("pardonedBy").isJsonNull()) { + punishment.setPardonedBy(UUID.fromString(object.get("pardonedBy").getAsString())); + } + + if (!object.get("pardonedAt").isJsonNull()) { + punishment.setPardonedAt(object.get("pardonedAt").getAsLong()); + } + + if (!object.get("pardonedReason").isJsonNull()) { + punishment.setPardonedReason(object.get("pardonedReason").getAsString()); + } + + if (!object.get("pardoned").isJsonNull()) { + punishment.setPardoned(object.get("pardoned").getAsBoolean()); + } + + return punishment; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentJsonSerializer.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentJsonSerializer.java new file mode 100644 index 0000000..5f3d70f --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentJsonSerializer.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.punishment; + +import com.google.gson.JsonObject; +import me.devkevin.landcore.utils.json.JsonSerializer; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:32 + * PunishmentJsonSerializer / me.devkevin.landcore.punishment / LandCore + */ +public class PunishmentJsonSerializer implements JsonSerializer { + + @Override + public JsonObject serialize(Punishment punishment) { + JsonObject object = new JsonObject(); + object.addProperty("uuid", punishment.getUuid().toString()); + object.addProperty("type", punishment.getType().name()); + object.addProperty("addedBy", punishment.getAddedBy() == null ? null : punishment.getAddedBy().toString()); + object.addProperty("addedAt", punishment.getAddedAt()); + object.addProperty("addedReason", punishment.getAddedReason()); + object.addProperty("duration", punishment.getDuration()); + object.addProperty("pardonedBy", punishment.getPardonedBy() == null ? null : punishment.getPardonedBy().toString()); + object.addProperty("pardonedAt", punishment.getPardonedAt()); + object.addProperty("pardonedReason", punishment.getPardonedReason()); + object.addProperty("pardoned", punishment.isPardoned()); + return object; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentType.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentType.java new file mode 100644 index 0000000..ab9ca50 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/PunishmentType.java @@ -0,0 +1,36 @@ +package me.devkevin.landcore.punishment; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.bukkit.ChatColor; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:32 + * PunishmentType / me.devkevin.landcore.punishment / LandCore + */ +@Getter +@AllArgsConstructor +public enum PunishmentType { + + BLACKLIST("blacklisted", "unblacklisted", true, true, new PunishmentTypeData("Blacklists", ChatColor.DARK_RED, 14)), + BAN("banned", "unbanned", true, true, new PunishmentTypeData("Bans", ChatColor.GOLD, 1)), + MUTE("muted", "unmuted", false, true, new PunishmentTypeData("Mutes", ChatColor.YELLOW, 4)), + WARN("warned", null, false, false, new PunishmentTypeData("Warnings", ChatColor.GREEN, 13)), + KICK("kicked", null, false, false, new PunishmentTypeData("Kicks", ChatColor.GRAY, 7)); + + private String context; + private String undoContext; + private boolean ban; + private boolean canBePardoned; + private PunishmentTypeData typeData; + + + @Getter + @AllArgsConstructor + public static class PunishmentTypeData { + private String readable; + private ChatColor color; + private int durability; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/listener/PunishmentListener.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/listener/PunishmentListener.java new file mode 100644 index 0000000..19486da --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/listener/PunishmentListener.java @@ -0,0 +1,63 @@ +package me.devkevin.landcore.punishment.listener; + +import me.devkevin.landcore.punishment.procedure.PunishmentProcedure; +import me.devkevin.landcore.punishment.procedure.PunishmentProcedureStage; +import me.devkevin.landcore.punishment.procedure.PunishmentProcedureType; +import me.devkevin.landcore.utils.menu.TypeCallback; +import me.devkevin.landcore.utils.menu.menus.ConfirmMenu; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerChatEvent; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:57 + * PunishmentListener / me.devkevin.landcore.punishment.listener / LandCore + */ +public class PunishmentListener implements Listener { + + @EventHandler(priority = EventPriority.LOWEST) + public void onAsyncPlayerChatEvent(AsyncPlayerChatEvent event) { + if (!event.getPlayer().hasPermission("zoot.staff.grant")) { + return; + } + + PunishmentProcedure procedure = PunishmentProcedure.getByPlayer(event.getPlayer()); + + if (procedure != null && procedure.getStage() == PunishmentProcedureStage.REQUIRE_TEXT) { + event.setCancelled(true); + + if (event.getMessage().equalsIgnoreCase("cancel")) { + PunishmentProcedure.getProcedures().remove(procedure); + event.getPlayer().sendMessage(CC.RED + "You have cancelled the punishment procedure."); + return; + } + + if (procedure.getType() == PunishmentProcedureType.PARDON) { + new ConfirmMenu(CC.YELLOW + "Pardon this punishment?", (TypeCallback) data -> { + if (data) { + procedure.getPunishment().setPardonedBy(event.getPlayer().getUniqueId()); + procedure.getPunishment().setPardonedAt(System.currentTimeMillis()); + procedure.getPunishment().setPardonedReason(event.getMessage()); + procedure.getPunishment().setPardoned(true); + procedure.finish(); + + event.getPlayer().sendMessage(CC.GREEN + "The punishment has been pardoned."); + } else { + event.getPlayer().sendMessage(CC.RED + "You did not confirm to pardon the punishment."); + } + }, true) { + @Override + public void onClose(Player player) { + if (!isClosedByMenu()) { + event.getPlayer().sendMessage(CC.RED + "You did not confirm to pardon the punishment."); + } + } + }.openMenu(event.getPlayer()); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/menu/PunishmentsListMenu.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/menu/PunishmentsListMenu.java new file mode 100644 index 0000000..a69ee5b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/menu/PunishmentsListMenu.java @@ -0,0 +1,122 @@ +package me.devkevin.landcore.punishment.menu; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.punishment.Punishment; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.punishment.procedure.PunishmentProcedure; +import me.devkevin.landcore.punishment.procedure.PunishmentProcedureStage; +import me.devkevin.landcore.punishment.procedure.PunishmentProcedureType; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.time.TimeUtil; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:53 + * PunishmentsListMenu / me.devkevin.landcore.punishment.menu / LandCore + */ +@AllArgsConstructor +public class PunishmentsListMenu extends PaginatedMenu { + + private CoreProfile profile; + private PunishmentType punishmentType; + + @Override + public String getPrePaginatedTitle(Player player) { + return "&6" + punishmentType.getTypeData().getReadable() + " &7- &f" + profile.getGrant().getRank().getColor() + profile.getName(); + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + + for (Punishment punishment : profile.getPunishments()) { + if (punishment.getType() == punishmentType) { + buttons.put(buttons.size(), new PunishmentInfoButton(punishment)); + } + } + + return buttons; + } + + @AllArgsConstructor + private class PunishmentInfoButton extends Button { + + private Punishment punishment; + + @Override + public ItemStack getButtonItem(Player player) { + String addedBy = "Console"; + + if (punishment.getAddedBy() != null) { + try { + CoreProfile addedByProfile = LandCore.getInstance().getProfileManager().getProfile(punishment.getAddedBy()); + addedBy = addedByProfile.getName(); + } catch (Exception e) { + addedBy = "Could not fetch..."; + } + } + + List lore = new ArrayList<>(); + + lore.add(CC.BOARD_SEPARATOR); + lore.add("&eAdded by: &c" + addedBy); + lore.add("&eAdded for: &c" + punishment.getAddedReason()); + + if (punishment.isActive() && !punishment.isPermanent() && punishment.getDuration() != -1) { + lore.add("&eDuration: &c" + punishment.getTimeRemaining()); + } + + if (punishment.isPardoned()) { + String removedBy = "Console"; + + if (punishment.getPardonedBy() != null) { + try { + CoreProfile removedByProfile = LandCore.getInstance().getProfileManager().getProfile(punishment.getPardonedBy()); + removedBy = removedByProfile.getName(); + } catch (Exception e) { + removedBy = "Could not fetch..."; + } + } + + lore.add(CC.BOARD_SEPARATOR); + lore.add("&ePardoned at: &c" + TimeUtil.dateToString(new Date(punishment.getPardonedAt()))); + lore.add("&ePardoned by: &c" + removedBy); + lore.add("&ePardoned for: &c" + punishment.getPardonedReason()); + } + + lore.add(CC.BOARD_SEPARATOR); + + if (!punishment.isPardoned() && punishment.getType().isCanBePardoned()) { + lore.add("&eRight click to pardon this punishment"); + lore.add(CC.BOARD_SEPARATOR); + } + + return new ItemBuilder(Material.PAPER) + .name("&6" + TimeUtil.dateToString(new Date(punishment.getAddedAt()))) + .lore(lore) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + if (clickType == ClickType.RIGHT && !punishment.isPardoned() && punishment.getType().isCanBePardoned()) { + PunishmentProcedure procedure = new PunishmentProcedure(player, profile, PunishmentProcedureType.PARDON, PunishmentProcedureStage.REQUIRE_TEXT); + procedure.setPunishment(punishment); + + player.sendMessage(CC.GREEN + "Type a reason for pardoning this punishment in chat..."); + player.closeInventory(); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/menu/PunishmentsMenu.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/menu/PunishmentsMenu.java new file mode 100644 index 0000000..3b2519b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/menu/PunishmentsMenu.java @@ -0,0 +1,72 @@ +package me.devkevin.landcore.punishment.menu; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.punishment.PunishmentType; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.message.CC; +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; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:52 + * PunishmentsMenu / me.devkevin.landcore.punishment.menu / LandCore + */ +@AllArgsConstructor +public class PunishmentsMenu extends Menu { + + private CoreProfile profile; + + @Override + public String getTitle(Player player) { + return "&6Punishments of " + profile.getGrant().getRank().getColor() + profile.getName(); + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(9, new SelectPunishmentTypeButton(profile, PunishmentType.BLACKLIST)); + buttons.put(11, new SelectPunishmentTypeButton(profile, PunishmentType.BAN)); + buttons.put(13, new SelectPunishmentTypeButton(profile, PunishmentType.MUTE)); + buttons.put(15, new SelectPunishmentTypeButton(profile, PunishmentType.WARN)); + buttons.put(17, new SelectPunishmentTypeButton(profile, PunishmentType.KICK)); + + return buttons; + } + + @Override + public int getSize() { + return 27; + } + + @AllArgsConstructor + private static class SelectPunishmentTypeButton extends Button { + + private CoreProfile profile; + private PunishmentType punishmentType; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.WOOL) + .name(punishmentType.getTypeData().getColor() + CC.B + punishmentType.getTypeData().getReadable()) + .lore(CC.GRAY + profile.getPunishmentCountByType(punishmentType) + " " + (punishmentType.getTypeData().getReadable().toLowerCase()) + " on record") + .durability(punishmentType.getTypeData().getDurability()) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + new PunishmentsListMenu(profile, punishmentType).openMenu(player); + } + } + +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedure.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedure.java new file mode 100644 index 0000000..031fd05 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedure.java @@ -0,0 +1,49 @@ +package me.devkevin.landcore.punishment.procedure; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.punishment.Punishment; +import org.bukkit.entity.Player; +import java.util.HashSet; +import java.util.Set; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:51 + * PunishmentProcedure / me.devkevin.landcore.punishment.procedure / LandCore + */ +@Getter +public class PunishmentProcedure { + @Getter private static final Set procedures = new HashSet<>(); + + private final Player issuer; + private final CoreProfile recipient; + private final PunishmentProcedureType type; + private PunishmentProcedureStage stage; + @Setter private Punishment punishment; + + public PunishmentProcedure(Player issuer, CoreProfile recipient, PunishmentProcedureType type, PunishmentProcedureStage stage) { + this.issuer = issuer; + this.recipient = recipient; + this.type = type; + this.stage = stage; + + procedures.add(this); + } + + public void finish() { + this.recipient.save(true); + procedures.remove(this); + } + + public static PunishmentProcedure getByPlayer(Player player) { + for (PunishmentProcedure procedure : procedures) { + if (procedure.issuer.equals(player)) { + return procedure; + } + } + + return null; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedureStage.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedureStage.java new file mode 100644 index 0000000..2c77545 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedureStage.java @@ -0,0 +1,10 @@ +package me.devkevin.landcore.punishment.procedure; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:50 + * PunishmentProcedureStage / me.devkevin.landcore.punishment.procedure / LandCore + */ +public enum PunishmentProcedureStage { + REQUIRE_CLICK, REQUIRE_TEXT, REQUIRE_CONFIRMATION +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedureType.java b/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedureType.java new file mode 100644 index 0000000..8c53a69 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/punishment/procedure/PunishmentProcedureType.java @@ -0,0 +1,10 @@ +package me.devkevin.landcore.punishment.procedure; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 3:50 + * PunishmentProcedureType / me.devkevin.landcore.punishment.procedure / LandCore + */ +public enum PunishmentProcedureType { + ADD, PARDON +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/redis/RedisMessenger.java b/LandCore/src/main/java/me/devkevin/landcore/redis/RedisMessenger.java new file mode 100644 index 0000000..532f282 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/redis/RedisMessenger.java @@ -0,0 +1,116 @@ +package me.devkevin.landcore.redis; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.redis.annotation.RedisHandler; +import me.devkevin.landcore.redis.message.RedisMessage; +import lombok.Getter; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.JedisPool; +import redis.clients.jedis.JedisPubSub; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 10:24 + * RedisMessenger / land.pvp.core.redis / LandCore + */ +@Getter +public class RedisMessenger { + + private final JedisPool jedisPool; + private final LandCore plugin; + private Set listeners = new HashSet<>(); + + private boolean active = false; + + public RedisMessenger(LandCore plugin, String host, int port, int timeout, String password) { + this.plugin = plugin; + GenericObjectPoolConfig config = new GenericObjectPoolConfig(); + config.setMaxTotal(20); + this.jedisPool = new JedisPool(config, host, port, timeout, password); + } + + public void initialize() { + + //In order to avoid subscribing twice to the same redis channel, we add a simple set. + Set subscribedChannels = Sets.newHashSet(); + Map> map = Maps.newHashMap(); + + //We schedule an asynchronous task to handle our subscriptions. + listeners.forEach(listener -> { + //After looping through each listener, we get that listener's methods, and try to find where the RedisHandler annotation is used, we add that to a set. + Set methods = getMethodsOfAnnotation(listener.getClass(), RedisHandler.class); + + for (Method method : methods) { + //For each of these sets, we get the redis handler, check if we're already subscribed, if not, we subscribe to the channel. + RedisHandler handler = method.getAnnotation(RedisHandler.class); + if (!subscribedChannels.contains(handler.value())) { + map.put(handler.value(), new ImmutablePair<>(listener, method)); + subscribedChannels.add(handler.value()); + active = true; + } + } + }); + + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { + try (Jedis jedis = jedisPool.getResource()) { + jedis.subscribe(new JedisPubSub() { + @Override + public void onMessage(String channel, String message) { + map.forEach((c, pair) -> { + if (channel.equalsIgnoreCase(c)) { + try { + pair.getValue().invoke(pair.getKey(), RedisMessage.deserialize(message)); + } catch (IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + } + }); + } + }, subscribedChannels.toArray(new String[0])); + } + }); + } + + public void send(String channel, Map message) { + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { + try (Jedis jedis = jedisPool.getResource()) { + jedis.publish(channel, RedisMessage.serialize(message)); + } + }); + } + + public void sendOff(String channel, Map message) { + try (Jedis jedis = jedisPool.getResource()) { + jedis.publish(channel, RedisMessage.serialize(message)); + } + } + + public boolean isRedisConnected() { + return this.jedisPool != null && !this.jedisPool.isClosed(); + } + + public void registerListeners(Object... objects) { + for (Object object : objects) { + getListeners().add(object); + } + } + + private Set getMethodsOfAnnotation(Class clazz, Class annotation) { + return Stream.of(clazz.getDeclaredMethods()) + .filter(method -> method.isAnnotationPresent(annotation)) + .collect(Collectors.toSet()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/redis/annotation/RedisHandler.java b/LandCore/src/main/java/me/devkevin/landcore/redis/annotation/RedisHandler.java new file mode 100644 index 0000000..d7f1342 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/redis/annotation/RedisHandler.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.redis.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 10:27 + * RedisHandler / land.pvp.core.redis.annotation / LandCore + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface RedisHandler { + String value(); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/redis/message/RedisMessage.java b/LandCore/src/main/java/me/devkevin/landcore/redis/message/RedisMessage.java new file mode 100644 index 0000000..c726670 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/redis/message/RedisMessage.java @@ -0,0 +1,25 @@ +package me.devkevin.landcore.redis.message; + +import com.google.gson.reflect.TypeToken; +import me.devkevin.landcore.LandCore; +import java.lang.reflect.Type; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 17/01/2023 @ 10:24 + * RedisMessage / land.pvp.core.redis.message / LandCore + */ +public class RedisMessage { + + public static Map deserialize(String string) { + Type type = new TypeToken>() { + }.getType(); + return LandCore.GSON.fromJson(string, type); + } + + public static String serialize(Map map) { + return LandCore.GSON.toJson(map); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/server/ServerSettings.java b/LandCore/src/main/java/me/devkevin/landcore/server/ServerSettings.java new file mode 100644 index 0000000..b0cd760 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/server/ServerSettings.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.server; + +import com.google.common.collect.ImmutableMap; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.storage.flatfile.Config; +import me.devkevin.landcore.task.ShutdownTask; +import me.devkevin.landcore.utils.message.CC; +import lombok.Getter; +import lombok.Setter; + +@Getter +public class ServerSettings { + private final Config coreConfig; + private final String whitelistMessage; + @Setter + private WhitelistMode serverWhitelistMode; + @Setter + private ShutdownTask shutdownTask; + @Setter + private boolean globalChatMuted; + @Setter + private int slowChatTime = -1; + + public ServerSettings(LandCore plugin) { + this.coreConfig = new Config(plugin, "LandCore"); + + coreConfig.addDefaults(ImmutableMap.builder() + .put("whitelist.mode", WhitelistMode.NONE.name()) + .put("whitelist.message", CC.RED + "The server is whitelisted. Come back later!") + .build()); + coreConfig.copyDefaults(); + + this.serverWhitelistMode = WhitelistMode.valueOf(coreConfig.getString("whitelist.mode")); + this.whitelistMessage = coreConfig.getString("whitelist.message"); + } + + public void saveConfig() { + coreConfig.save(); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/server/WhitelistMode.java b/LandCore/src/main/java/me/devkevin/landcore/server/WhitelistMode.java new file mode 100644 index 0000000..abc4de3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/server/WhitelistMode.java @@ -0,0 +1,42 @@ +package me.devkevin.landcore.server; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public enum WhitelistMode { + NONE { + @Override + public boolean isProfileIneligible(CoreProfile profile) { + return false; + } + }, + RANKS { + @Override + public boolean isProfileIneligible(CoreProfile profile) { + return !profile.hasDonor(); + } + }, + STAFF { + @Override + public boolean isProfileIneligible(CoreProfile profile) { + return !profile.hasStaff(); + } + }; + + private static final String WHITELIST_MESSAGE = CC.RED + "The server has been whitelisted. Come back later!"; + + public void activate() { + for (Player player : Bukkit.getOnlinePlayers()) { + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (isProfileIneligible(profile)) { + player.kickPlayer(WHITELIST_MESSAGE); + } + } + } + + public abstract boolean isProfileIneligible(CoreProfile profile); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/server/filter/Filter.java b/LandCore/src/main/java/me/devkevin/landcore/server/filter/Filter.java new file mode 100644 index 0000000..9070e84 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/server/filter/Filter.java @@ -0,0 +1,256 @@ +package me.devkevin.landcore.server.filter; + +import com.google.common.collect.ImmutableList; +import me.devkevin.landcore.utils.StringUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.regex.Matcher; + +public class Filter { + private static final List FILTERED_PHRASES = ImmutableList.of( + "nigger", "suck", "retard", "faggot", "bitch", "slut", "maricon", "beaner", "tercermundista", "pedofilo", "librecraft", "universocraft", "ghostly", "minemen", + "minemora", "gh", "aternos", "autoclicker", "bypass", "reach", "velocity", "clicker", "transexual", "lgbt", "capullo", "imbecil", "mierda", "comunismo", "nazi", + "hitler", "minecaca", "euca", "eucacraft", "minekk", "adolf", "aborto", "ecuacraft", "latinplay", "survivaldub", "omegacraft", "pvpland", "tranza", "transa", + "travelo", "trapito", "kys", "cheat", "veltus", "ecua", "niggr", "niguer", "niger", "nigguer", "niggr", "nigr", "ngger", "nger" + ); + private static final List NEGATIVE_WORD_PAIRS; + private static final String[] SINGLE_FILTERED_WORDS = {"L", "ez", "kb", "#"}; + private static final String[] WHITELISTED_LINKS = { + "udrop.club", "youtube.com", "youtu.be", "imgur.com", "prntscr.com", "prnt.sc", "gfycat.com", "gyazo.com", + "twitter.com", "spotify.com", "twitch.tv", "tinypic.com" + }; + + static { + String[] words = new String[]{"fuck", "shit", "ass", "trash", "garbage", "horrible"}; + String[] matches = new String[]{"kb", "knockback", "server", "staff", "pots"}; + + List pairs = new ArrayList<>(); + + for (String word : words) { + pairs.add(new NegativeWordPair(word, matches)); + } + + NEGATIVE_WORD_PAIRS = ImmutableList.copyOf(pairs); + } + + public boolean isFiltered(String msg) { + msg = msg.toLowerCase().trim(); + + for (String word : msg.split(" ")) { + Matcher matcher = StringUtil.IP_REGEX.matcher(word); + + if (matcher.matches()) { + return true; + } + } + + for (String word : msg + .replace("3", "e") + .replace("1", "i") + .replace("!", "i") + .replace("/\\", "a") + .replace("/-\\", "a") + .replace("()", "o") + .replace("2", "z") + .replace("@", "a") + .replace("|", "l") + .replace("7", "t") + .replace("4", "a") + .replace("0", "o") + .replace("5", "s") + .replace("8", "b") + .trim().split(" ")) { + Matcher matcher = StringUtil.URL_REGEX.matcher(word); + + boolean filtered = false; + + if (matcher.matches()) { + int matches = 0; + + for (String link : WHITELISTED_LINKS) { + if (word.contains(link)) { + matches++; + } + } + + filtered = matches == 0; + } + + if (filtered) { + return true; + } + } + + for (String word : msg + .replace("3", "e") + .replace("1", "i") + .replace("!", "i") + .replace("/\\", "a") + .replace("/-\\", "a") + .replace("()", "o") + .replace("2", "z") + .replace("@", "a") + .replace("|", "l") + .replace("7", "t") + .replace("4", "a") + .replace("0", "o") + .replace("5", "s") + .replace("8", "b") + .replace(" ", "") + .trim().split(" ")) { + Matcher matcher = StringUtil.URL_REGEX.matcher(word); + + boolean filtered = false; + + if (matcher.matches()) { + int matches = 0; + + for (String link : WHITELISTED_LINKS) { + if (word.contains(link)) { + matches++; + } + } + + filtered = matches == 0; + } + + if (filtered) { + return true; + } + } + + for (String word : msg + .replace("3", "e") + .replace("1", "i") + .replace("!", "i") + .replace("/\\", "a") + .replace("/-\\", "a") + .replace("()", "o") + .replace("2", "z") + .replace("@", "a") + .replace("|", "l") + .replace("7", "t") + .replace("4", "a") + .replace("0", "o") + .replace("5", "s") + .replace("8", "b") + .trim().replaceAll("\\p{Punct}|\\d", ":").replace(":dot:", ".").split(" ")) { + Matcher matcher = StringUtil.URL_REGEX.matcher(word); + + boolean filtered = false; + + if (matcher.matches()) { + int matches = 0; + + for (String link : WHITELISTED_LINKS) { + if (word.contains(link)) { + matches++; + } + } + + filtered = matches == 0; + } + + if (filtered) { + return true; + } + } + + + for (String word : msg + .replace("3", "e") + .replace("1", "i") + .replace("!", "i") + .replace("/\\", "a") + .replace("/-\\", "a") + .replace("()", "o") + .replace("2", "z") + .replace("@", "a") + .replace("|", "l") + .replace("7", "t") + .replace("4", "a") + .replace("0", "o") + .replace("5", "s") + .replace("8", "b") + .replace(" ", "") + .trim().replaceAll("\\p{Punct}|\\d", ":").replace(":dot:", ".").split(" ")) { + Matcher matcher = StringUtil.URL_REGEX.matcher(word); + + boolean filtered = false; + + if (matcher.matches()) { + int matches = 0; + + for (String link : WHITELISTED_LINKS) { + if (word.contains(link)) { + matches++; + } + } + + filtered = matches == 0; + } + + if (filtered) { + return true; + } + } + + String parsed = msg + .replace("3", "e") + .replace("1", "i") + .replace("!", "i") + .replace("/\\", "a") + .replace("/-\\", "a") + .replace("()", "o") + .replace("2", "z") + .replace("@", "a") + .replace("|", "l") + .replace("7", "t") + .replace("4", "a") + .replace("0", "o") + .replace("5", "s") + .replace("8", "b") + .trim(); + + String noPuncParsed = parsed.replaceAll("\\p{Punct}|\\d", "").trim(); + + for (String word : SINGLE_FILTERED_WORDS) { + if (noPuncParsed.equalsIgnoreCase(word) || noPuncParsed.startsWith(word + " ") + || noPuncParsed.endsWith(" " + word) || noPuncParsed.contains(" " + word + " ")) { + return true; + } + } + + for (NegativeWordPair pair : NEGATIVE_WORD_PAIRS) { + for (String match : pair.getMatches()) { + if (noPuncParsed.contains(pair.getWord()) && noPuncParsed.contains(match)) { + return true; + } + } + } + + for (String phrase : FILTERED_PHRASES) { + if (parsed.contains(phrase)) { + return true; + } + } + + Optional filterablePhrase = FILTERED_PHRASES.stream().map(phrase -> phrase.replaceAll(" ", "")).filter(parsed::contains).findFirst(); + + if (filterablePhrase.isPresent()) { + return true; + } + + String[] split = parsed.trim().split(" "); + + for (String word : split) { + if (FILTERED_PHRASES.contains(word)) { + return true; + } + } + + return false; + } +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/server/filter/NegativeWordPair.java b/LandCore/src/main/java/me/devkevin/landcore/server/filter/NegativeWordPair.java new file mode 100644 index 0000000..c8c8b16 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/server/filter/NegativeWordPair.java @@ -0,0 +1,14 @@ +package me.devkevin.landcore.server.filter; + +import lombok.Getter; + +@Getter +class NegativeWordPair { + private final String word; + private final String[] matches; + + NegativeWordPair(String word, String... matches) { + this.word = word; + this.matches = matches; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/storage/database/MongoRequest.java b/LandCore/src/main/java/me/devkevin/landcore/storage/database/MongoRequest.java new file mode 100644 index 0000000..c5bb79c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/storage/database/MongoRequest.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.storage.database; + +import me.devkevin.landcore.LandCore; +import lombok.AccessLevel; +import lombok.RequiredArgsConstructor; + +import java.util.HashMap; +import java.util.Map; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class MongoRequest { + private final String collectionName; + private final Object documentObject; + private final Map updatePairs = new HashMap<>(); + + public static MongoRequest newRequest(String collectionName, Object value) { + return new MongoRequest(collectionName, value); + } + + public MongoRequest put(String key, Object value) { + updatePairs.put(key, value); + return this; + } + + public void run() { + LandCore.getInstance().getMongoStorage().massUpdate(collectionName, documentObject, updatePairs); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/storage/database/MongoStorage.java b/LandCore/src/main/java/me/devkevin/landcore/storage/database/MongoStorage.java new file mode 100644 index 0000000..6d11f93 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/storage/database/MongoStorage.java @@ -0,0 +1,89 @@ +package me.devkevin.landcore.storage.database; + +import com.mongodb.client.*; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Updates; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.callback.DocumentCallback; +import lombok.Getter; +import org.bson.Document; + +import java.util.Map; + +@Getter +public class MongoStorage { + @Getter private static MongoStorage instance; + + private final MongoDatabase database; + private final MongoCollection disguiseCollection; + private final MongoCollection factionsCollection; + private final MongoCollection factionsPlayersCollection; + + private final boolean connected; + + public MongoStorage(LandCore plugin) { + if (instance != null) { + throw new RuntimeException("The mongo database has already been instantiated."); + } + + instance = this; + + MongoClient mongoClient = MongoClients.create( + LandCore.getInstance().getConfig().getString("mongodb.uri") + ); + + database = mongoClient.getDatabase("land_core"); + + disguiseCollection = this.database.getCollection("disguises"); + factionsCollection = this.database.getCollection("factions"); + factionsPlayersCollection = this.database.getCollection("playersFactions"); + connected = true; + } + + public void getOrCreateDocument(String collectionName, Object documentObject, DocumentCallback callback) { + MongoCollection collection = database.getCollection(collectionName); + Document document = new Document("_id", documentObject); + + try (MongoCursor cursor = collection.find(document).iterator()) { + if (cursor.hasNext()) { + callback.call(cursor.next(), true); + } else { + collection.insertOne(document); + callback.call(document, false); + } + } + } + + public MongoCursor getAllDocuments(String collectionName) { + MongoCollection collection = database.getCollection(collectionName); + return collection.find().iterator(); + } + + public Document getDocumentByFilter(String collectionName, String filter, Object documentObject) { + MongoCollection collection = database.getCollection(collectionName); + return collection.find(Filters.eq(filter, documentObject)).first(); + } + + public FindIterable getDocumentsByFilter(String collectionName, Object documentObject) { + MongoCollection collection = database.getCollection(collectionName); + return collection.find(Filters.eq("_id", documentObject)); + } + + public Document getDocument(String collectionName, Object documentObject) { + MongoCollection collection = database.getCollection(collectionName); + return collection.find(Filters.eq("_id", documentObject)).first(); + } + + public void updateDocument(String collectionName, Object documentObject, String key, Object newValue) { + MongoCollection collection = database.getCollection(collectionName); + collection.updateOne(Filters.eq(documentObject), Updates.set(key, newValue)); + } + + public void massUpdate(String collectionName, Object documentObject, Map updates) { + MongoCollection collection = database.getCollection(collectionName); + + for (Map.Entry entry : updates.entrySet()) { + collection.updateOne(Filters.eq(documentObject), Updates.set(entry.getKey(), entry.getValue())); + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/storage/flatfile/Config.java b/LandCore/src/main/java/me/devkevin/landcore/storage/flatfile/Config.java new file mode 100644 index 0000000..de8d98b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/storage/flatfile/Config.java @@ -0,0 +1,115 @@ +package me.devkevin.landcore.storage.flatfile; + +import me.devkevin.landcore.utils.structure.Cuboid; +import org.bukkit.Location; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.ItemStack; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Config { + private final File file; + private YamlConfiguration delegate; + + public Config(JavaPlugin plugin, String name) { + file = new File(plugin.getDataFolder() + "/" + name + ".yml"); + reload(); + } + + public void reload() { + delegate = YamlConfiguration.loadConfiguration(file); + } + + public void clear() { + file.delete(); + + reload(); + save(); + } + + public void save() { + try { + delegate.save(file); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void addDefault(String path, Object defaultValue) { + delegate.addDefault(path, defaultValue); + } + + public void addDefaults(Map defaults) { + delegate.addDefaults(defaults); + } + + public void copyDefaults() { + delegate.options().copyDefaults(true); + save(); + } + + public void set(String path, Object value) { + delegate.set(path, value); + } + + public boolean contains(String path) { + return delegate.contains(path); + } + + public int getInt(String path) { + return delegate.getInt(path); + } + + public boolean getBoolean(String path) { + return delegate.getBoolean(path); + } + + public String getString(String path) { + return delegate.getString(path); + } + + public List getStringList(String path) { + return delegate.getStringList(path); + } + + public Location getLocation(String path) { + return (Location) delegate.get(path); + } + + public Cuboid getCuboid(String path) { + return (Cuboid) delegate.get(path); + } + + public ItemStack getItem(String path) { + return delegate.getItemStack(path); + } + + @SuppressWarnings("unchecked") + public List getItemList(String path) { + return (List) delegate.get(path); + } + + public ItemStack[] getItemArray(String path) { + List itemList = getItemList(path); + + if (itemList == null) { + return null; + } + + return itemList.toArray(new ItemStack[0]); + } + + public ConfigurationSection getSection(String path) { + return delegate.getConfigurationSection(path); + } + + public Set getKeys() { + return delegate.getKeys(false); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/store/StorePCoinMenu.java b/LandCore/src/main/java/me/devkevin/landcore/store/StorePCoinMenu.java new file mode 100644 index 0000000..5ebd79c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/store/StorePCoinMenu.java @@ -0,0 +1,164 @@ +package me.devkevin.landcore.store; + +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.utils.inventory.InventoryUI; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.Arrays; + +import static me.devkevin.landcore.LandCoreAPI.PLACEHOLDER_ITEM; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/03/2023 @ 20:02 + * StorePCoinMenu / me.devkevin.landcore.store / LandCore + */ +@Getter +public class StorePCoinMenu { + private final LandCore plugin = LandCore.getInstance(); + + private final InventoryUI menu = new InventoryUI(CC.GRAY + "PCoins Store Menu", 5); + + public InventoryUI menu(Player player) { + CoreProfile coreProfile = this.plugin.getProfileManager().getProfile(player.getUniqueId()); + + int[] slots = {9, 10, 11, 13, 14, 15, 16, 17, 19, 26, 27, 28, 35, 37, 38, 39, 40, 41, 42, 43, 44}; + Arrays.stream(slots).forEach(slot -> this.menu.setItem(slot, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM))); + + this.menu.setItem(12, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.STAINED_GLASS_PANE) + .durability(5) + .name(CC.YELLOW + "You're viewing this category!") + .hideFlags() + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + } + }); + + this.menu.setItem(36, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.BED) + .name(CC.RED + "Close Store") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + } + }); + + this.menu.setItem(3, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.EMERALD) + .name(CC.GOLD + "Permanent Ranks") + .lore("") + .lore(CC.GRAY + "Improve your experience with ranks") + .lore(CC.GRAY + "which offers you extra features!") + .lore("") + .lore(CC.RED + "Note: " + CC.GRAY + "Each ranks contains all") + .lore(CC.GRAY + "features from previous ones.") + .lore("") + .lore(CC.YELLOW + "You're viewing this category!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.openInventory(menu(player).getCurrentPage()); + } + }); + + this.menu.setItem(4, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND) + .name(CC.GOLD + "Temporary Ranks") + .lore("") + .lore(CC.GRAY + "Improve your experience with ranks") + .lore(CC.GRAY + "which offers you extra features!") + .lore("") + .lore(CC.RED + "Note: " + CC.GRAY + "Each ranks contains all") + .lore(CC.GRAY + "features from previous ones.") + .lore("") + .lore(CC.GREEN + "Purchased days will accumulate at any") + .lore(CC.GREEN + "time you decide to purchase this again!") + .lore("") + .lore(CC.YELLOW + "Click to view this category!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + //TODO: + } + }); + + this.menu.setItem(5, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.IRON_INGOT) + .name(CC.GOLD + "Upgrade Ranks") + .lore("") + .lore(CC.GRAY + "Improve your experience with ranks") + .lore(CC.GRAY + "which offers you extra features!") + .lore("") + .lore(CC.RED + "Note: " + CC.GRAY + "Each ranks contains all") + .lore(CC.GRAY + "features from previous ones.") + .lore("") + .lore(CC.YELLOW + "Click to view this category!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + //TODO: + } + }); + + this.menu.setItem(0, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.SKULL_ITEM).durability(3).owner(player.getName()) + .name(CC.GREEN + "Buying for: " + coreProfile.getGrant().getRank().getColor() + player.getName()) + .lore(CC.GRAY + "You're buying for yourself!") + .lore("") + .lore(CC.RED + "Note: " + CC.GRAY + "If you want buying for another") + .lore(CC.GRAY + "player, both must be connected to same server.") + .lore("") + .lore(CC.YELLOW + "Click to know more about buy for another player.") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + + player.sendMessage(CC.GRAY + CC.B + "To buy for another player you must transfer PCoins to his account using"); + player.sendMessage(CC.YELLOW + CC.U + "/ppay (player) (amount)"); + } + }); + + this.menu.setItem(18, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.GOLD_INGOT) + .name(CC.GOLD + "PCoins: " + CC.R + coreProfile.getP_coin() + CC.COIN) + .lore("") + .lore(CC.GRAY + "PCoin are used to acquire server") + .lore(CC.GRAY + "ranks, chat tags, chat color themes,") + .lore(CC.GRAY + "buy features in the entire network") + .lore(CC.GRAY + "and access to exclusive gamemodes") + .lore("") + .lore(CC.YELLOW + CC.U + "You can purchase PCoins at store.prac.lol") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + player.sendMessage(CC.GRAY + "● " + CC.YELLOW + "Store: " + CC.GOLD + "https://store.prac.lol".replace("https://", "")); + } + }); + + + + + return menu; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/task/BroadcastTask.java b/LandCore/src/main/java/me/devkevin/landcore/task/BroadcastTask.java new file mode 100644 index 0000000..b75f262 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/task/BroadcastTask.java @@ -0,0 +1,41 @@ +package me.devkevin.landcore.task; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.utils.message.CC; +import lombok.RequiredArgsConstructor; +import org.bukkit.ChatColor; +import org.bukkit.Server; +import xyz.refinedev.spigot.plugin; + +public class BroadcastTask implements Runnable { + private final LandCore plugin; + + private static final String[] MESSAGES = { + CC.YELLOW + "Butterfly/double clicking is discouraged and may get you banned.", + CC.YELLOW + "Check out our website to view statistics, leaderboards, the forum, and more: " + CC.GRAY + ChatColor.UNDERLINE + "http://prac.lol", + CC.YELLOW + "Want a free rank? Vote for us on NameMC!\n" + CC.GRAY + ChatColor.UNDERLINE + "https://namemc.com/server/prac.lol", + CC.YELLOW + "Follow us on Twitter for giveaways, updates, and more!\n" + CC.GRAY + ChatColor.UNDERLINE + "http://twitter.prac.lol", + CC.YELLOW + "Join our Discord server!\n" + CC.GRAY + ChatColor.UNDERLINE + "http://invite.gg/prac", + CC.YELLOW + "Get cool perks and help support us by getting a rank on the store!\n" + CC.GRAY + ChatColor.UNDERLINE + "https://store.prac.lol", + CC.YELLOW + "Staff applications are open! Apply here: " + CC.GRAY + ChatColor.UNDERLINE + "http://apply.prac.lol" + }; + + private int currentIndex = -1; + private static final String LINE_SEPARATOR = "\n"; + + public BroadcastTask(LandCore plugin) { + this.plugin = plugin; + } + + @Override + public void run() { + if (++currentIndex >= MESSAGES.length) { + currentIndex = 0; + } + + String message = MESSAGES[currentIndex]; + + String broadcastMessage = LINE_SEPARATOR + message + LINE_SEPARATOR; + plugin.getServer().broadcastMessage(broadcastMessage); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/task/GrantDisguiseCheckTask.java b/LandCore/src/main/java/me/devkevin/landcore/task/GrantDisguiseCheckTask.java new file mode 100644 index 0000000..6dafeb8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/task/GrantDisguiseCheckTask.java @@ -0,0 +1,32 @@ +package me.devkevin.landcore.task; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.nametag.impl.InternalNametag; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import xyz.haoshoku.nick.api.NickAPI; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/02/2023 @ 12:12 + * GrantDisguiseCheckTask / me.devkevin.landcore.task / LandCore + */ +public class GrantDisguiseCheckTask extends BukkitRunnable { + + public GrantDisguiseCheckTask() { + this.runTaskTimerAsynchronously(LandCore.getInstance(), 20L, 20L); + } + + @Override + public void run() { + for (Player online : Bukkit.getOnlinePlayers()) { + if (NickAPI.isNicked(online)) { + InternalNametag.reloadPlayer(online); + InternalNametag.reloadOthersFor(online); + + NickAPI.refreshPlayerSync(online); + } + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/task/ShutdownTask.java b/LandCore/src/main/java/me/devkevin/landcore/task/ShutdownTask.java new file mode 100644 index 0000000..126851f --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/task/ShutdownTask.java @@ -0,0 +1,25 @@ +package me.devkevin.landcore.task; + +import me.devkevin.landcore.utils.message.CC; +import me.devkevin.landcore.utils.time.TimeUtil; +import lombok.AllArgsConstructor; +import org.bukkit.Bukkit; +import org.bukkit.scheduler.BukkitRunnable; + +@AllArgsConstructor +public class ShutdownTask extends BukkitRunnable { + private int shutdownSeconds; + + @Override + public void run() { + if (shutdownSeconds == 0) { + Bukkit.shutdown(); + } else if (shutdownSeconds % 60 == 0 || shutdownSeconds == 30 || shutdownSeconds == 10 || shutdownSeconds <= 5) { + Bukkit.broadcastMessage(""); + Bukkit.broadcastMessage(CC.D_RED + "[Alert] " + CC.RED + "The server is restarting in " + TimeUtil.formatTimeSeconds(shutdownSeconds) + "."); + Bukkit.broadcastMessage(""); + } + + shutdownSeconds--; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/BukkitReflection.java b/LandCore/src/main/java/me/devkevin/landcore/utils/BukkitReflection.java new file mode 100644 index 0000000..c22a1cb --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/BukkitReflection.java @@ -0,0 +1,118 @@ +package me.devkevin.landcore.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Copyright 09/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class BukkitReflection { + + private static final String CRAFT_BUKKIT_PACKAGE; + private static final String NET_MINECRAFT_SERVER_PACKAGE; + + private static final Class CRAFT_SERVER_CLASS; + private static final Method CRAFT_SERVER_GET_HANDLE_METHOD; + + private static final Class PLAYER_LIST_CLASS; + private static final Field PLAYER_LIST_MAX_PLAYERS_FIELD; + + private static final Class CRAFT_PLAYER_CLASS; + private static final Method CRAFT_PLAYER_GET_HANDLE_METHOD; + + private static final Class ENTITY_PLAYER_CLASS; + private static final Field ENTITY_PLAYER_PING_FIELD; + + private static final Class CRAFT_ITEM_STACK_CLASS; + private static final Method CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD; + private static final Class ENTITY_ITEM_STACK_CLASS; + private static final Method ENTITY_ITEM_STACK_GET_NAME; + + private static final Class SPIGOT_CONFIG_CLASS; + private static final Field SPIGOT_CONFIG_BUNGEE_FIELD; + + static { + try { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + + CRAFT_BUKKIT_PACKAGE = "org.bukkit.craftbukkit." + version + "."; + NET_MINECRAFT_SERVER_PACKAGE = "net.minecraft.server." + version + "."; + + CRAFT_SERVER_CLASS = Class.forName(CRAFT_BUKKIT_PACKAGE + "CraftServer"); + CRAFT_SERVER_GET_HANDLE_METHOD = CRAFT_SERVER_CLASS.getDeclaredMethod("getHandle"); + CRAFT_SERVER_GET_HANDLE_METHOD.setAccessible(true); + + PLAYER_LIST_CLASS = Class.forName(NET_MINECRAFT_SERVER_PACKAGE + "PlayerList"); + PLAYER_LIST_MAX_PLAYERS_FIELD = PLAYER_LIST_CLASS.getDeclaredField("maxPlayers"); + PLAYER_LIST_MAX_PLAYERS_FIELD.setAccessible(true); + + CRAFT_PLAYER_CLASS = Class.forName(CRAFT_BUKKIT_PACKAGE + "entity.CraftPlayer"); + CRAFT_PLAYER_GET_HANDLE_METHOD = CRAFT_PLAYER_CLASS.getDeclaredMethod("getHandle"); + CRAFT_PLAYER_GET_HANDLE_METHOD.setAccessible(true); + + ENTITY_PLAYER_CLASS = Class.forName(NET_MINECRAFT_SERVER_PACKAGE + "EntityPlayer"); + ENTITY_PLAYER_PING_FIELD = ENTITY_PLAYER_CLASS.getDeclaredField("ping"); + ENTITY_PLAYER_PING_FIELD.setAccessible(true); + + CRAFT_ITEM_STACK_CLASS = Class.forName(CRAFT_BUKKIT_PACKAGE + "inventory.CraftItemStack"); + CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD = + CRAFT_ITEM_STACK_CLASS.getDeclaredMethod("asNMSCopy", ItemStack.class); + CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD.setAccessible(true); + + ENTITY_ITEM_STACK_CLASS = Class.forName(NET_MINECRAFT_SERVER_PACKAGE + "ItemStack"); + ENTITY_ITEM_STACK_GET_NAME = ENTITY_ITEM_STACK_CLASS.getDeclaredMethod("getName"); + + SPIGOT_CONFIG_CLASS = Class.forName("org.spigotmc.SpigotConfig"); + SPIGOT_CONFIG_BUNGEE_FIELD = SPIGOT_CONFIG_CLASS.getDeclaredField("bungee"); + SPIGOT_CONFIG_BUNGEE_FIELD.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + + throw new RuntimeException("Failed to initialize Bukkit/NMS Reflection"); + } + } + + public static int getPing(Player player) { + try { + int ping = ENTITY_PLAYER_PING_FIELD.getInt(CRAFT_PLAYER_GET_HANDLE_METHOD.invoke(player)); + + return ping > 0 ? ping : 0; + } catch (Exception e) { + return 1; + } + } + + public static void setMaxPlayers(Server server, int slots) { + try { + PLAYER_LIST_MAX_PLAYERS_FIELD.set(CRAFT_SERVER_GET_HANDLE_METHOD.invoke(server), slots); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static String getItemStackName(ItemStack itemStack) { + try { + return (String) ENTITY_ITEM_STACK_GET_NAME.invoke(CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD.invoke(itemStack, itemStack)); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + public static boolean isBungeeServer() { + try { + return (boolean) SPIGOT_CONFIG_BUNGEE_FIELD.get(null); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/Clickable.java b/LandCore/src/main/java/me/devkevin/landcore/utils/Clickable.java new file mode 100644 index 0000000..edb68f7 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/Clickable.java @@ -0,0 +1,42 @@ +package me.devkevin.landcore.utils; + +import me.devkevin.landcore.utils.message.CC; +import net.md_5.bungee.api.chat.*; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 12:20 + * Clickable / land.pvp.core.utils / LandCore + */ +public class Clickable { + + private List components = new ArrayList<>(); + + public TextComponent add(String msg, String hoverMsg, String clickString) { + TextComponent message = new TextComponent(CC.translate(msg)); + if (hoverMsg != null) { + message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(CC.translate(hoverMsg)).create())); + } + if (clickString != null) { + message.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, clickString)); + } + components.add(message); + return message; + } + + public void add(String message) { + components.add(new TextComponent(message)); + } + + public void sendToPlayer(Player player) { + player.spigot().sendMessage((BaseComponent[])asComponents()); + } + + public TextComponent[] asComponents() { + return components.toArray(new TextComponent[0]); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/Duration.java b/LandCore/src/main/java/me/devkevin/landcore/utils/Duration.java new file mode 100644 index 0000000..3fcd7d1 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/Duration.java @@ -0,0 +1,70 @@ +package me.devkevin.landcore.utils; + +import lombok.Getter; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 15:13 + * Duration / me.devkevin.landcore.utils / LandCore + */ +public class Duration { + + @Getter + private long value; + + public Duration(long value) { + this.value = value; + } + + public static Duration fromString(String source) { + if (source.equalsIgnoreCase("perm") || source.equalsIgnoreCase("permanent")) { + return new Duration(Integer.MAX_VALUE); + } + + long totalTime = 0L; + boolean found = false; + Matcher matcher = Pattern.compile("\\d+\\D+").matcher(source); + + 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 new Duration(!found ? -1 : totalTime * 1000); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/FieldBoundReflections.java b/LandCore/src/main/java/me/devkevin/landcore/utils/FieldBoundReflections.java new file mode 100644 index 0000000..7b51eb3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/FieldBoundReflections.java @@ -0,0 +1,208 @@ +package me.devkevin.landcore.utils; + +import org.apache.commons.lang.Validate; + +import java.lang.reflect.Field; + +public class FieldBoundReflections { + + private Field field; + + public FieldBoundReflections() { + } + + public FieldBoundReflections(Field field) { + this.field = field; + } + + public static FieldBoundReflections access(Class clazz, String name) { + Validate.notNull(clazz); + + try { + Field field = clazz.getDeclaredField(name); + return access(field); + } catch (NoSuchFieldException exception) { + throw new RuntimeException(exception); + } + } + + public static FieldBoundReflections access(Field field) { + if (!field.isAccessible()) { + field.setAccessible(true); + } + + return new FieldBoundReflections(field); + } + + public FieldBoundReflections set(Object instance, Object value) { + try { + field.set(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setInt(Object instance, int value) { + try { + field.setInt(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setFloat(Object instance, float value) { + try { + field.setFloat(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setDouble(Object instance, double value) { + try { + field.setDouble(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setByte(Object instance, byte value) { + try { + field.setByte(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setLong(Object instance, long value) { + try { + field.setLong(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setShort(Object instance, short value) { + try { + field.setShort(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setChar(Object instance, char value) { + try { + field.setChar(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public FieldBoundReflections setBoolean(Object instance, boolean value) { + try { + field.setBoolean(instance, value); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + + return this; + } + + public E get(Object instance) { + try { + return (E) field.get(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public int getInt(Object instance) { + try { + return field.getInt(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public double getDouble(Object instance) { + try { + return field.getDouble(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public float getFloat(Object instance) { + try { + return field.getFloat(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public byte getByte(Object instance) { + try { + return field.getByte(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public char getChar(Object instance) { + try { + return field.getChar(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public long getLong(Object instance) { + try { + return field.getLong(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public short getShort(Object instance) { + try { + return field.getShort(instance); + } catch (IllegalAccessException exception) { + throw new RuntimeException(exception); + } + } + + public FieldBoundReflections bind(Field field) { + this.field = field; + return this; + } + + public Field unbind() { + Field oldField = field; + this.field = null; + return oldField; + } + + public boolean isBound() { + return this.field != null; + } + +} + + diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/Menu.java b/LandCore/src/main/java/me/devkevin/landcore/utils/Menu.java new file mode 100644 index 0000000..678c777 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/Menu.java @@ -0,0 +1,101 @@ +package me.devkevin.landcore.utils; + +import lombok.Getter; +import lombok.Setter; +import org.bukkit.Bukkit; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.stream.IntStream; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/01/2023 @ 14:15 + * Menu / me.devkevin.landcore.utils / LandCore + */ +public abstract class Menu { + + @Getter + private static Map menus = new HashMap<>(); + + private UUID uuid; + private int rows; + + @Getter + @Setter + private boolean updateOnClick = true; + + @Getter + private Inventory inventory; + + public Menu(Player player, String title, int rows, boolean update) { + this.uuid = player.getUniqueId(); + this.rows = rows; + this.inventory = Bukkit.createInventory(null, rows * 9, title); + + if(update) { + this.updateInventory(player); + } + + TaskUtil.run(() -> menus.put(player.getUniqueId(), this)); + } + + public abstract void updateInventory(Player player); + + public abstract void onClickItem(Player player, ItemStack stack, boolean isRightClicked); + + public void onClose() {} + + public void fill(ItemStack itemStack) { + IntStream.range(0, this.inventory.getSize()).filter(i -> this.inventory.getItem(i) == null).forEach(i -> this.inventory.setItem(i, itemStack)); + } + + public void surround(ItemStack itemStack) { + IntStream.range(0, this.inventory.getSize()).filter(i -> this.inventory.getItem(i) == null).forEach(i -> { + if (i < 9 || i > this.inventory.getSize() - 10 || i % 9 == 0 || (i + 1) % 9 == 0) { + this.inventory.setItem(i, itemStack); + } + }); + } + + public void playSound(boolean confirm) { + this.getPlayer().playSound(this.getPlayer().getLocation(), confirm ? Sound.NOTE_PIANO : Sound.GLASS, 20F, confirm ? 15F : 5F); + } + + public void openInventory() { + this.getPlayer().openInventory(this.inventory); + } + + public void set(int slot, ItemStack material) { + this.inventory.setItem(slot, material); + } + + public void add(ItemStack material) { + this.inventory.addItem(material); + } + + public void close() { + this.getPlayer().closeInventory(); + } + + public void destroy() { + menus.remove(this.uuid); + } + + public static Menu getByUuid(UUID uuid) { + return menus.get(uuid); + } + + public Player getPlayer() { + return Bukkit.getPlayer(this.uuid); + } + + public int getSize() { + return rows * 9; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/NumberUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/NumberUtil.java new file mode 100644 index 0000000..d2d8479 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/NumberUtil.java @@ -0,0 +1,14 @@ +package me.devkevin.landcore.utils; + +import lombok.experimental.UtilityClass; + +@UtilityClass +public class NumberUtil { + public static Integer getInteger(String s) { + try { + return Integer.parseInt(s); + } catch (NumberFormatException ex) { + return null; + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/NumberUtils.java b/LandCore/src/main/java/me/devkevin/landcore/utils/NumberUtils.java new file mode 100644 index 0000000..de5246c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/NumberUtils.java @@ -0,0 +1,36 @@ +package me.devkevin.landcore.utils; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 12:25 + * NumberUtils / land.pvp.core.utils / LandCore + */ +public class NumberUtils { + public static boolean isInteger(String input) { + try { + Integer.parseInt(input); + return true; + } catch (NumberFormatException var2) { + return false; + } + } + + public static boolean isShort(String input) { + try { + Short.parseShort(input); + return true; + } catch (NumberFormatException var2) { + return false; + } + } + + public static boolean isDouble(String input) { + try { + Double.parseDouble(input); + return true; + } catch (NumberFormatException var2) { + return false; + } + } +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/PlayerList.java b/LandCore/src/main/java/me/devkevin/landcore/utils/PlayerList.java new file mode 100644 index 0000000..0596e48 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/PlayerList.java @@ -0,0 +1,55 @@ +package me.devkevin.landcore.utils; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public class PlayerList { + public static final String ORDERED_RANKS = String.join(", ", Arrays.stream(Rank.values()) + .sorted(Comparator.reverseOrder()) + .map(rank -> rank.getColor() + rank.getName() + CC.R) + .collect(Collectors.toList())); + private static final Comparator RANK_ORDER = (a, b) -> { + CoreProfile profileA = LandCore.getInstance().getProfileManager().getProfile(a.getUniqueId()); + CoreProfile profileB = LandCore.getInstance().getProfileManager().getProfile(b.getUniqueId()); + return profileB.getRank().compareTo(profileA.getRank()); + }; + + @Getter + private final List onlinePlayers; + + public static PlayerList newList() { + return new PlayerList(new ArrayList<>(Bukkit.getOnlinePlayers())); + } + + public int size() { + return onlinePlayers.size(); + } + + public PlayerList sortedByRank() { + onlinePlayers.sort(RANK_ORDER); + return this; + } + + public String asColoredNames() { + List namesList = onlinePlayers.stream() + .map(Player::getUniqueId) + .map(LandCore.getInstance().getProfileManager()::getProfile) + .map(profile -> profile.getRank().getColor() + profile.getName() + CC.R) + .collect(Collectors.toList()); + return String.join(", ", namesList); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/PlayerVersion.java b/LandCore/src/main/java/me/devkevin/landcore/utils/PlayerVersion.java new file mode 100644 index 0000000..28947ca --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/PlayerVersion.java @@ -0,0 +1,32 @@ +package me.devkevin.landcore.utils; + +import lombok.Getter; + +import java.util.Arrays; + +@Getter +public enum PlayerVersion { + + v1_7(4, 5), + v1_8(47), + v1_9(107, 108, 109, 110), + v1_10(210), + v1_11(315, 316), + v1_12(335, 338, 340), + v1_13(393, 401, 404); + + private final Integer[] rawVersion; + + PlayerVersion(Integer... rawVersionNumbers) { + this.rawVersion = rawVersionNumbers; + } + + public static PlayerVersion getVersionFromRaw(Integer input) { + for (PlayerVersion playerVersion : PlayerVersion.values()) { + if (Arrays.asList(playerVersion.rawVersion).contains(input)) { + return playerVersion; + } + } + return v1_8; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/ProfileUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/ProfileUtil.java new file mode 100644 index 0000000..a2fd2b6 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/ProfileUtil.java @@ -0,0 +1,136 @@ +package me.devkevin.landcore.utils; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@UtilityClass +public final class ProfileUtil { + private static final String API_URL = "https://api.mojang.com/users/profiles/minecraft/"; + private static final String SESSION_SERVER_URL = "https://sessionserver.mojang.com/session/minecraft/profile/"; + private static final Cache NAME_CACHE = CacheBuilder + .newBuilder() + .expireAfterAccess(15L, TimeUnit.MINUTES) + .build(); + private static final Cache ID_CACHE = CacheBuilder + .newBuilder() + .expireAfterAccess(15L, TimeUnit.MINUTES) + .build(); + + public static MojangProfile lookupProfile(UUID id) { + MojangProfile cachedProfile = ID_CACHE.getIfPresent(id); + + if (cachedProfile != null) { + return cachedProfile; + } + + Player player = Bukkit.getPlayer(id); + + if (player != null) { + return cacheProfile(player.getName(), player.getUniqueId()); + } + + String name = lookupNameFromId(id); + + if (name != null) { + return cacheProfile(name, id); + } + + return null; + } + + public static MojangProfile lookupProfile(String name) { + MojangProfile cachedProfile = ID_CACHE.getIfPresent(name.toLowerCase()); + + if (cachedProfile != null) { + return cachedProfile; + } + + Player player = Bukkit.getPlayerExact(name); + + if (player != null) { + return cacheProfile(player.getName(), player.getUniqueId()); + } + + UUID id = lookupIdFromName(name); + + if (id != null) { + MojangProfile profile = lookupProfile(id); + + if (profile != null) { + return profile; + } + } + + return null; + } + + private static MojangProfile cacheProfile(String name, UUID id) { + MojangProfile profile = new MojangProfile(name, id); + + NAME_CACHE.put(name.toLowerCase(), profile); + ID_CACHE.put(id, profile); + + return profile; + } + + private static UUID parseId(String idString) { + return UUID.fromString(idString.substring(0, 8) + "-" + idString.substring(8, 12) + "-" + + idString.substring(12, 16) + "-" + idString.substring(16, 20) + "-" + idString.substring(20, 32)); + } + + private static UUID lookupIdFromName(String name) { + try { + URL url = new URL(API_URL + name); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { + String id = reader.readLine(); + + if (id != null) { + return parseId(id.split("\"")[3]); + } + } + } catch (IOException ex) { + ex.printStackTrace(); + } + + return null; + } + + private static String lookupNameFromId(UUID id) { + try { + URL url = new URL(SESSION_SERVER_URL + id.toString().replace("-", "")); + + try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()))) { + String name = reader.readLine(); + + if (name != null) { + return name.split("\"")[7]; + } + } + } catch (IOException ex) { + ex.printStackTrace(); + } + + return null; + } + + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) + @Getter + public static class MojangProfile { + private final String name; + private final UUID id; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/Protocol.java b/LandCore/src/main/java/me/devkevin/landcore/utils/Protocol.java new file mode 100644 index 0000000..10c724a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/Protocol.java @@ -0,0 +1,34 @@ +package me.devkevin.landcore.utils; + +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.Packet; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/02/2023 @ 2:56 + * Protocol / me.devkevin.landcore.utils / LandCore + */ +public class Protocol { + public EntityPlayer getEntity(Player player) { + return ((CraftPlayer) player).getHandle(); + } + + public void sendPacket(Player player, Packet packet) { + getEntity(player).playerConnection.sendPacket(packet); + } + + public void broadcastWorld(Packet packet, Player player) { + for (Player online : player.getWorld().getPlayers()) { + if ((online != null) && (online.getEntityId() != player.getEntityId()) && (online.canSee(player))) + sendPacket(online, packet); + } + } + + public void broadcastServer(Packet packet, Player player) { + for (Player all : Bukkit.getServer().getOnlinePlayers()) + sendPacket(all, packet); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/ReflectionUtils.java b/LandCore/src/main/java/me/devkevin/landcore/utils/ReflectionUtils.java new file mode 100644 index 0000000..d185e6b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/ReflectionUtils.java @@ -0,0 +1,623 @@ +package me.devkevin.landcore.utils; + +import org.bukkit.Bukkit; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * ReflectionUtils + *

+ * This class provides useful methods which makes dealing with reflection much easier, especially when working with Bukkit + *

+ * You are welcome to use it, modify it and redistribute it under the following conditions: + *

    + *
  • Don't claim this class as your own + *
  • Don't remove this disclaimer + *
+ *

+ * It would be nice if you provide credit to me if you use this class in a published project + * + * @author DarkBlade12 + * @version 1.1 + */ +public final class ReflectionUtils { + // Prevent accidental construction + private ReflectionUtils() {} + + /** + * Returns the constructor of a given class with the given parameter types + * + * @param clazz Target class + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @see DataType + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Constructor constructor : clazz.getConstructors()) { + if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { + continue; + } + return constructor; + } + throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); + } + + /** + * Returns the constructor of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param parameterTypes Parameter types of the desired constructor + * @return The constructor of the desired target class with the specified parameter types + * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found + * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass(String, PackageType) + * @see #getConstructor(Class, Class...) + */ + public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getConstructor(packageType.getClass(className), parameterTypes); + } + + /** + * Returns an instance of a class with the given arguments + * + * @param clazz Target class + * @param arguments Arguments which are used to construct an object of the target class + * @return The instance of the target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + */ + public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); + } + + /** + * Returns an instance of a desired class with the given arguments + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param arguments Arguments which are used to construct an object of the desired target class + * @return The instance of the desired target class with the specified arguments + * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass(String, PackageType) + * @see #instantiateObject(Class, Object...) + */ + public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return instantiateObject(packageType.getClass(className), arguments); + } + + /** + * Returns a method of a class with the given parameter types + * + * @param clazz Target class + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found + * @see DataType#getPrimitive(Class[]) + * @see DataType#compare(Class[], Class[]) + */ + public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { + Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); + for (Method method : clazz.getMethods()) { + if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { + continue; + } + return method; + } + throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); + } + + /** + * Returns a method of a desired class with the given parameter types + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param parameterTypes Parameter types of the desired method + * @return The method of the desired target class with the specified name and parameter types + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass(String, PackageType) + * @see #getMethod(Class, String, Class...) + */ + public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { + return getMethod(packageType.getClass(className), methodName, parameterTypes); + } + + /** + * Invokes a method on an object with the given arguments + * + * @param instance Target object + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } + + /** + * Invokes a method of the target class on an object with the given arguments + * + * @param instance Target object + * @param clazz Target class + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found + * @see #getMethod(Class, String, Class...) + * @see DataType#getPrimitive(Object[]) + */ + public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); + } + + /** + * Invokes a method of a desired class on an object with the given arguments + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param methodName Name of the desired method + * @param arguments Arguments which are used to invoke the desired method + * @return The result of invoking the desired method on the target object + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) + * @throws InvocationTargetException If the desired method cannot be invoked on the target object + * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getClass(String, PackageType) + * @see #invokeMethod(Object, Class, String, Object...) + */ + public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { + return invokeMethod(instance, packageType.getClass(className), methodName, arguments); + } + + /** + * Returns a field of the target class with the given name + * + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the target class with the specified name + * @throws NoSuchFieldException If the desired field of the given class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + */ + public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { + Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); + field.setAccessible(true); + return field; + } + + /** + * Gets a field in {@param clazz} + * @param clazz The class owning the class + * @param fieldName The name of the field to get + * @return The field + */ + public static Field getField(Class clazz, String fieldName) { + try { + Field field = clazz.getDeclaredField(fieldName); + field.setAccessible(true); + + return field; + } catch (NoSuchFieldException e) { + throw new IllegalArgumentException(clazz.getSimpleName() + ":" + fieldName); + } + } + + /** + * Returns a field of a desired class with the given name + * + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The field of the desired target class with the specified name + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getField(Class, boolean, String) + */ + public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { + return getField(packageType.getClass(className), declared, fieldName); + } + + /** + * Returns the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getField(clazz, declared, fieldName).get(instance); + } + + /** + * Returns the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + return getValue(instance, packageType.getClass(className), declared, fieldName); + } + + /** + * Returns the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @return The value of field of the target object + * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getValue(Object, Class, boolean, String) + */ + public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + return getValue(instance, instance.getClass(), declared, fieldName); + } + + /** + * Sets the value of a field of the given class of an object + * + * @param instance Target object + * @param clazz Target class + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #getField(Class, boolean, String) + */ + public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + getField(clazz, declared, fieldName).set(instance, value); + } + + /** + * Sets the value of a field of a desired class of an object + * + * @param instance Target object + * @param className Name of the desired target class + * @param packageType Package where the desired target class is located + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the desired class cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { + setValue(instance, packageType.getClass(className), declared, fieldName, value); + } + + /** + * Sets the value of a field with the given name of an object + * + * @param instance Target object + * @param declared Whether the desired field is declared or not + * @param fieldName Name of the desired field + * @param value New value + * @throws IllegalArgumentException If the type of the value does not match the type of the desired field + * @throws IllegalAccessException If the desired field cannot be accessed + * @throws NoSuchFieldException If the desired field of the target object cannot be found + * @throws SecurityException If the desired field cannot be made accessible + * @see #setValue(Object, Class, boolean, String, Object) + */ + public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { + setValue(instance, instance.getClass(), declared, fieldName, value); + } + + /** + * Represents an enumeration of dynamic packages of NMS and CraftBukkit + *

+ * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum PackageType { + MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), + CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), + CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), + CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), + CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), + CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), + CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), + CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), + CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), + CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), + CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), + CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), + CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), + CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), + CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), + CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), + CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), + CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), + CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), + CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); + + private final String path; + + /** + * Construct a new package type + * + * @param path Path of the package + */ + private PackageType(String path) { + this.path = path; + } + + /** + * Construct a new package type + * + * @param parent Parent package of the package + * @param path Path of the package + */ + private PackageType(PackageType parent, String path) { + this(parent + "." + path); + } + + /** + * Returns the path of this package type + * + * @return The path + */ + public String getPath() { + return path; + } + + /** + * Returns the class with the given name + * + * @param className Name of the desired class + * @return The class with the specified name + * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found + */ + public Class getClass(String className) throws ClassNotFoundException { + return Class.forName(this + "." + className); + } + + // Override for convenience + @Override + public String toString() { + return path; + } + + /** + * Returns the version of your server + * + * @return The server version + */ + public static String getServerVersion() { + return Bukkit.getServer().getClass().getPackage().getName().substring(23); + } + } + + /** + * Represents an enumeration of Java data types with corresponding classes + *

+ * This class is part of the ReflectionUtils and follows the same usage conditions + * + * @author DarkBlade12 + * @since 1.0 + */ + public enum DataType { + BYTE(byte.class, Byte.class), + SHORT(short.class, Short.class), + INTEGER(int.class, Integer.class), + LONG(long.class, Long.class), + CHARACTER(char.class, Character.class), + FLOAT(float.class, Float.class), + DOUBLE(double.class, Double.class), + BOOLEAN(boolean.class, Boolean.class); + + private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); + private final Class primitive; + private final Class reference; + + // Initialize map for quick class lookup + static { + for (DataType type : values()) { + CLASS_MAP.put(type.primitive, type); + CLASS_MAP.put(type.reference, type); + } + } + + /** + * Construct a new data type + * + * @param primitive Primitive class of this data type + * @param reference Reference class of this data type + */ + private DataType(Class primitive, Class reference) { + this.primitive = primitive; + this.reference = reference; + } + + /** + * Returns the primitive class of this data type + * + * @return The primitive class + */ + public Class getPrimitive() { + return primitive; + } + + /** + * Returns the reference class of this data type + * + * @return The reference class + */ + public Class getReference() { + return reference; + } + + /** + * Returns the data type with the given primitive/reference class + * + * @param clazz Primitive/Reference class of the data type + * @return The data type + */ + public static DataType fromClass(Class clazz) { + return CLASS_MAP.get(clazz); + } + + /** + * Returns the primitive class of the data type with the given reference class + * + * @param clazz Reference class of the data type + * @return The primitive class + */ + public static Class getPrimitive(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getPrimitive(); + } + + /** + * Returns the reference class of the data type with the given primitive class + * + * @param clazz Primitive class of the data type + * @return The reference class + */ + public static Class getReference(Class clazz) { + DataType type = fromClass(clazz); + return type == null ? clazz : type.getReference(); + } + + /** + * Returns the primitive class array of the given class array + * + * @param classes Given class array + * @return The primitive class array + */ + public static Class[] getPrimitive(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(classes[index]); + } + return types; + } + + /** + * Returns the reference class array of the given class array + * + * @param classes Given class array + * @return The reference class array + */ + public static Class[] getReference(Class[] classes) { + int length = classes == null ? 0 : classes.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(classes[index]); + } + return types; + } + + /** + * Returns the primitive class array of the given object array + * + * @param object Given object array + * @return The primitive class array + */ + public static Class[] getPrimitive(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getPrimitive(objects[index].getClass()); + } + return types; + } + + /** + * Returns the reference class array of the given object array + * + * @param object Given object array + * @return The reference class array + */ + public static Class[] getReference(Object[] objects) { + int length = objects == null ? 0 : objects.length; + Class[] types = new Class[length]; + for (int index = 0; index < length; index++) { + types[index] = getReference(objects[index].getClass()); + } + return types; + } + + /** + * Compares two class arrays on equivalence + * + * @param primary Primary class array + * @param secondary Class array which is compared to the primary array + * @return Whether these arrays are equal or not + */ + public static boolean compare(Class[] primary, Class[] secondary) { + if (primary == null || secondary == null || primary.length != secondary.length) { + return false; + } + for (int index = 0; index < primary.length; index++) { + Class primaryClass = primary[index]; + Class secondaryClass = secondary[index]; + if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { + continue; + } + return false; + } + return true; + } + } +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/SkinUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/SkinUtil.java new file mode 100644 index 0000000..1bd1531 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/SkinUtil.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.utils; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 17:55 + * SkinUtil / me.devkevin.landcore.utils / LandCore + */ +public class SkinUtil { + + public static void changeName(final Player p, final String newName) { + for (final Player pl : Bukkit.getOnlinePlayers()) { + if (p == pl) { + continue; + } + final GameProfile gp = ((CraftPlayer) p).getProfile(); + try { + final Field nameField = GameProfile.class.getDeclaredField("name"); + nameField.setAccessible(true); + final Field modifiersField = Field.class.getDeclaredField("modifiers"); + modifiersField.setAccessible(true); + modifiersField.setInt(nameField, nameField.getModifiers() & 0xFFFFFFEF); + nameField.set(gp, newName); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + public static void setSkin(GameProfile profile) { + profile.getProperties().put("textures", new Property("textures", "eyJ0aW1lc3RhbXAiOjE1NjQ0MzI5ODkyMDMsInByb2ZpbGVJZCI6IjY5OTEzMzU5NDVjZDRhNWJiNTYxYmM3OWYzNWU5NzQ0IiwicHJvZmlsZU5hbWUiOiJWZXJ6aWRlIiwic2lnbmF0dXJlUmVxdWlyZWQiOnRydWUsInRleHR1cmVzIjp7IlNLSU4iOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9iY2NjMjk2Y2QxNzFjMTU4ZWVjOTNlYzAzYzVhNjVlYWRjNTM4MDdlMzQ3ZWRhMmEzMzRiNjcwMzQ1ODk3YTU4In0sIkNBUEUiOnsidXJsIjoiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9lN2RmZWExNmRjODNjOTdkZjAxYTEyZmFiYmQxMjE2MzU5YzBjZDBlYTQyZjk5OTliNmU5N2M1ODQ5NjNlOTgwIn19fQ==", "R8fsaMkLfOxWwza/f0tuO5+uOKQcZvty1S2UHO9m+rvRFkP8Q3X90peQyLOPU4oJF6KDeZWp+xQrTJxtuCPT7cQ1I9zlatLmY5w9titm0DqA3LF2YGEz3IX86iRn7jyDUJjJNNZDvH6725BMLnK8h+nBwUdhIvwVx9f3uePxPhk0dzw+m7f9eg1Y8lLxwDm4cb+7y+8wlqslE1xvEFjlaR7+kBsIq4J4HUfvXRxBkVnheTRAKsXT6D/d9oPy3+RXpOrQB8CxOExtlM3KKYZrMHRYi3HWRrs4Fq87fRM3QnOl5/E7bAbI50XI5rc4HLWka0AfcYSzEhT8sBlDujVzY3PwRDnGlhDiFxpgY4yfijjP2lNoD4muH7yJFA9K/VBgEc8lEwhWt+AXBTRRntN6VdHsJ7xCIYsbQ6wjjyE0DeVZ4HdyNV/B7bk4wVtq03GQK+l6KDppp3VAbMzV5nnkOJSj4jHxA8t8GuUY2ecSTD2u1o7+55puFSSXKlK2DiEAPpinRyGhVT6+I/6Ac7cUOVGn5omspTgQEk2i+NCGFnsmZ5JGadvbHPEpx5NGKNzwElQF2i9UnCRUSEqCgRQqqvvkJb8DXPZaeOYPsIA+zffBmdOx3EX9tAW4W6yeplBLWErFEW0D4DcgL3gEXrCQRFB9OUakUQXmxXh5/r9rI7E=")); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/StringUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/StringUtil.java new file mode 100644 index 0000000..9b63c4b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/StringUtil.java @@ -0,0 +1,89 @@ +package me.devkevin.landcore.utils; + +import com.google.common.base.Joiner; +import lombok.experimental.UtilityClass; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.ChatColor; +import org.omg.CORBA.NO_PERMISSION; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.regex.Pattern; + +@UtilityClass +public class StringUtil { + public static final Pattern URL_REGEX = Pattern.compile("^(http://www\\.|https://www\\.|http://|https://)?[a-z0-9]+([\\-.][a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(/.*)?$"); + public static final Pattern IP_REGEX = Pattern.compile("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])([.,])){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$"); + + public static String buildString(String[] args, int start) { + return String.join(" ", Arrays.copyOfRange(args, start, args.length)); + } + + private final List COLORS; + + static { + COLORS = new ArrayList(Arrays.asList(new ChatColor[]{ChatColor.WHITE, ChatColor.GOLD, ChatColor.LIGHT_PURPLE, ChatColor.AQUA, ChatColor.YELLOW, ChatColor.GREEN, ChatColor.DARK_GRAY, ChatColor.GRAY, ChatColor.DARK_AQUA, ChatColor.DARK_PURPLE, ChatColor.BLUE, ChatColor.BLACK, ChatColor.DARK_GREEN, ChatColor.RED})); + } + + public static int convertChatColorToWoolData(ChatColor color) { + return color != ChatColor.DARK_RED && color != ChatColor.RED ? (color == ChatColor.DARK_GREEN ? 13 : (color == ChatColor.BLUE ? 11 : (color == ChatColor.DARK_PURPLE ? 10 : (color == ChatColor.DARK_AQUA ? 9 : (color == ChatColor.DARK_GRAY ? 7 : COLORS.indexOf(color)))))) : 14; + } + + public static String joinListGrammaticallyWithGuava(final List list) { + if (list == null || list.isEmpty()) { + return ""; + } + return list.size() > 1 + ? Joiner.on(", ").join(list.subList(0, list.size() - 1)) + .concat(String.format("%s and ", list.size() > 2 ? "," : "")) + .concat(list.get(list.size() - 1)) + : list.get(0); + } + + private static final ArrayList woolColors = new ArrayList<>(Arrays.asList( + ChatColor.WHITE, + ChatColor.GOLD, + ChatColor.LIGHT_PURPLE, + ChatColor.AQUA, + ChatColor.YELLOW, + ChatColor.GREEN, + ChatColor.LIGHT_PURPLE, + ChatColor.DARK_GRAY, + ChatColor.GRAY, + ChatColor.DARK_AQUA, + ChatColor.DARK_PURPLE, + ChatColor.BLUE, + ChatColor.BLACK, + ChatColor.DARK_GREEN, + ChatColor.RED, + ChatColor.BLACK + )); + + private static final ArrayList woolCCs = new ArrayList<>(Arrays.asList( + CC.WHITE, + CC.GOLD, + CC.PINK, + CC.AQUA, + CC.YELLOW, + CC.GREEN, + CC.D_GRAY, + CC.GRAY, + CC.D_AQUA, + CC.PURPLE, + CC.BLUE, + CC.BLACK, + CC.DARK_GREEN, + CC.RED, + CC.BLACK + )); + + public static int convertCCToWoolData(String color) { + if (Objects.equals(color, CC.D_RED)) { + color = CC.RED; + } + + return woolCCs.indexOf(color); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/TaskUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/TaskUtil.java new file mode 100644 index 0000000..d320018 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/TaskUtil.java @@ -0,0 +1,18 @@ +package me.devkevin.landcore.utils; + +import me.devkevin.landcore.LandCore; + +public class TaskUtil { + + public static void run(Runnable runnable) { + LandCore.getInstance().getServer().getScheduler().runTask(LandCore.getInstance(), runnable); + } + + public static void runLater(Runnable runnable, long delay) { + LandCore.getInstance().getServer().getScheduler().runTaskLater(LandCore.getInstance(), runnable, delay); + } + + public static void runAsync(Runnable runnable) { + LandCore.getInstance().getServer().getScheduler().runTaskAsynchronously(LandCore.getInstance(), runnable); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/UUIDUtils.java b/LandCore/src/main/java/me/devkevin/landcore/utils/UUIDUtils.java new file mode 100644 index 0000000..ce0cd5c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/UUIDUtils.java @@ -0,0 +1,9 @@ +package me.devkevin.landcore.utils; + + +import lombok.experimental.UtilityClass; +@UtilityClass +public class UUIDUtils { + + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/Utilities.java b/LandCore/src/main/java/me/devkevin/landcore/utils/Utilities.java new file mode 100644 index 0000000..efb192a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/Utilities.java @@ -0,0 +1,19 @@ +package me.devkevin.landcore.utils; + +import org.bukkit.Bukkit; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 19/01/2023 @ 16:56 + * Utilities / land.pvp.core.utils / LandCore + */ +public class Utilities { + + public static String SERVER_VERSION_PACKAGE; + + static { + String packageName = Bukkit.getServer().getClass().getPackage().getName(); + + SERVER_VERSION_PACKAGE = packageName.substring(packageName.lastIndexOf('.') + 1); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/WoolUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/WoolUtil.java new file mode 100644 index 0000000..8612bf5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/WoolUtil.java @@ -0,0 +1,60 @@ +package me.devkevin.landcore.utils; + +import com.mongodb.lang.Nullable; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.ChatColor; +import org.bukkit.Material; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Objects; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 20/01/2023 @ 12:24 + * WoolUtil / land.pvp.core.utils / LandCore + */ +public class WoolUtil { + + private static final ArrayList woolColors = new ArrayList(Arrays.asList(ChatColor.WHITE, ChatColor.GOLD, ChatColor.LIGHT_PURPLE, + ChatColor.AQUA, ChatColor.YELLOW, ChatColor.GREEN, ChatColor.LIGHT_PURPLE, ChatColor.DARK_GRAY, + ChatColor.GRAY, ChatColor.DARK_AQUA, ChatColor.DARK_PURPLE, ChatColor.BLUE, ChatColor.BLACK, + ChatColor.DARK_GREEN, ChatColor.RED, ChatColor.BLACK)); + + public static int convertChatColorToWoolData(ChatColor color) { + //if(color == ChatColor.DARK_RED) color = ChatColor.RED; + + return WoolUtil.woolColors.indexOf(color); + } + + @Nullable + public static Material getMaterial(String value) { + if (NumberUtils.isInteger(value)) { + return Material.getMaterial(Integer.parseInt(value)); + } else { + return Material.getMaterial(value.toUpperCase()); + } + } + + public static int convertCCToWoolData(String color) { + if (Objects.equals(color, CC.D_RED)) { + color = CC.RED; + } + + return WoolUtil.woolColors.indexOf(color); + } + + private static final ArrayList woolKalors = new ArrayList<>(Arrays.asList(ChatColor.WHITE, ChatColor.GOLD, ChatColor.LIGHT_PURPLE, + ChatColor.AQUA, ChatColor.YELLOW, ChatColor.GREEN, ChatColor.LIGHT_PURPLE, ChatColor.DARK_GRAY, + ChatColor.GRAY, ChatColor.DARK_AQUA, ChatColor.DARK_PURPLE, ChatColor.BLUE, ChatColor.BLACK, + ChatColor.DARK_GREEN, ChatColor.RED, ChatColor.BLACK)); + + public static int getWoolData(ChatColor color) { + if (color == ChatColor.DARK_RED) color = ChatColor.RED; + if (color == ChatColor.DARK_BLUE) color = ChatColor.BLUE; + + return WoolUtil.woolKalors.indexOf(color); + } +} + + diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/http/Skin.java b/LandCore/src/main/java/me/devkevin/landcore/utils/http/Skin.java new file mode 100644 index 0000000..f711231 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/http/Skin.java @@ -0,0 +1,67 @@ +package me.devkevin.landcore.utils.http; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +import java.io.InputStreamReader; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CompletableFuture; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 19/01/2023 @ 18:34 + * Skin / land.pvp.core.utils.http / LandCore + */ +@Getter +@Setter +@AllArgsConstructor +public class Skin { + public static final String ID_API = "https://api.mojang.com/users/profiles/minecraft/"; + public static final String WEB_API = "https://sessionserver.mojang.com/session/minecraft/profile/"; + public static final Map SKINS = new HashMap<>(); + + public static Skin DEFAULT_SKIN = new Skin("", "", ""); + + private String name; + private String value; + private String signature; + + public static CompletableFuture getSkinByName(String name) { + return CompletableFuture.supplyAsync(() -> { + if (SKINS.containsKey(name)) { + return SKINS.get(name); + } + + String texture = null; + String signature = null; + + try { + String idChecker = ID_API + name; + URL urlChecker = new URL(idChecker); + + InputStreamReader reader = new InputStreamReader(urlChecker.openStream()); + JsonObject object = new JsonParser().parse(reader).getAsJsonObject(); + String id = object.get("id").getAsString(); + + String link = WEB_API + id + "?unsigned=false"; + urlChecker = new URL(link); + reader = new InputStreamReader(urlChecker.openStream()); + JsonObject properties = new JsonParser().parse(reader).getAsJsonObject().get("properties").getAsJsonArray().get(0).getAsJsonObject(); + + texture = properties.get("value").getAsString(); + signature = properties.get("signature").getAsString(); + reader.close(); + } catch (Exception ex) { + return Skin.DEFAULT_SKIN; + } + Skin skin = new Skin(name, texture, signature); + SKINS.put(name, skin); + return skin; + }); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryMaker.java b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryMaker.java new file mode 100644 index 0000000..897d4f1 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryMaker.java @@ -0,0 +1,300 @@ +package me.devkevin.landcore.utils.inventory; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.utils.item.ItemMaker; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.LinkedList; +import java.util.List; + +/** + * Copyright 25/04/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class InventoryMaker { + + private List inventories = new LinkedList<>(); + + private String title; + + private int rowOffset; + private int rows; + + private int offset; + private int page; + + public InventoryMaker(String title, int rows) { + this(title, rows, 0); + } + + private InventoryMaker(String title, int rows, int rowOffset) { + this.title = CC.translate(title); + this.rows = rows; + this.rowOffset = rowOffset; + } + + public Inventory2D getCurrentUI() { + return this.inventories.get(page); + } + + public Inventory getCurrentPage() { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + return this.inventories.get(page).toInventory(); + } + + private ClickableItem getItem(int slot) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + return lastInventory.getItem(slot); + } + + private int getSize() { + return this.rows * 9; + } + + private void createNewInventory() { + Inventory2D inventory = new Inventory2D(this.title, this.rows, this.rowOffset); + + if (this.inventories.size() > 0) { + inventory.setItem(0, this.rows - 1, new ClickableItem() { + @Override + public void onClick(InventoryClickEvent event) { + InventoryMaker.this.page--; + try { + Inventory2D inventory2D = InventoryMaker.this.inventories.get(InventoryMaker.this.page); + if (inventory2D != null) { + Player player = (Player) event.getWhoClicked(); + player.playSound(player.getLocation(), Sound.DIG_GRASS, 1, 1); + player.openInventory(InventoryMaker.this.getCurrentPage()); + } + } catch (IndexOutOfBoundsException ignored) { + + } + } + + @Override + public ItemStack getItemStack() { + return new ItemMaker(Material.CARPET).setDisplayName("&6Previous Page").create(); + } + }); + + if (inventory.currentY == this.rows - 1 && inventory.currentX == -1) { + inventory.currentX++; + } + } + + this.inventories.add(inventory); + } + + private void setItem(int x, int y, ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + lastInventory.setItem(x - 1, y - 1, item); + } + + public void setItem(int slot, ClickableItem item) { + setItem(slot, item, null, false); + } + + public void setItem(int slot, ClickableItem item, Player player, boolean update) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + lastInventory.setItem(slot, item, player, update); + } + + public void addItem(ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + + if (lastInventory.currentY == this.rows - 1 && lastInventory.currentX >= 7 - this.offset) { + lastInventory.setItem(8, this.rows - 1, new ClickableItem() { + @Override + public void onClick(InventoryClickEvent event) { + InventoryMaker.this.page++; + try { + Inventory2D inventory2D = InventoryMaker.this.inventories.get(InventoryMaker.this.page); + if (inventory2D == null) { + InventoryMaker.this.page--; + } else { + Player player = (Player) event.getWhoClicked(); + player.playSound(player.getLocation(), Sound.DIG_GRASS, 1, 1); + player.openInventory(InventoryMaker.this.getCurrentPage()); + } + } catch (IndexOutOfBoundsException e) { + InventoryMaker.this.page--; + } + } + + @Override + public ItemStack getItemStack() { + return new ItemMaker(Material.CARPET).setDisplayName("&6Next Page").create(); + } + }); + this.createNewInventory(); + this.addItem(item); + } else { + lastInventory.setItem(++lastInventory.currentX + this.offset, lastInventory.currentY, item); + } + + if (lastInventory.currentX >= 8 - this.offset) { + lastInventory.currentX = this.offset - 1; + lastInventory.currentY++; + } + } + + public void removeItem(int slot) { + Inventory2D inventory2D = this.inventories.get(this.page); + this.setItem(slot, null); + for (int i = slot + 1; i < this.getSize(); i++) { + ClickableItem item = this.getItem(i); + + this.setItem(i - 1, item); + this.setItem(i, null); + } + if (inventory2D.currentX >= 0) { + inventory2D.currentX--; + } else { + if (inventory2D.currentY > 0) { + inventory2D.currentY--; + inventory2D.currentX = 7; + } + } + } + + public interface ClickableItem { + + void onClick(InventoryClickEvent event); + + ItemStack getItemStack(); + + } + + public static class InventoryMakerHolder implements InventoryHolder { + + private InventoryMaker InventoryMaker; + + private InventoryMakerHolder(InventoryMaker InventoryMaker) { + this.InventoryMaker = InventoryMaker; + } + + @Override + public Inventory getInventory() { + return this.InventoryMaker.getCurrentPage(); + } + + public InventoryMaker getInventoryMaker() { + return InventoryMaker; + } + } + + public class Inventory2D { + + private ClickableItem[][] items; + private String title; + private int rows, currentX = -1, currentY; + + private Inventory cachedInventory; + + Inventory2D(String title, int rows, int rowOffset) { + this.currentY = rowOffset; + this.title = title; + this.rows = rows; + this.items = new ClickableItem[9][this.rows]; + } + + void setItem(int x, int y, ClickableItem clickableItem) { + this.items[x][y] = clickableItem; + + if (this.cachedInventory != null) { + int slot = (y * 9) + x; + if (clickableItem != null && clickableItem.getItemStack() != null) { + cachedInventory.setItem(slot, clickableItem.getItemStack()); + } + } + } + + public void setItem(int slot, ClickableItem clickableItem) { + setItem(slot, clickableItem, null, false); + } + + public void setItem(int slot, ClickableItem clickableItem, Player player, boolean update) { + int y = Math.abs(slot / 9); + int x = -(y * 9 - slot); + + if (update && player != null) { + new BukkitRunnable() { + + @Override + public void run() { + if (!player.isOnline() || !player.getOpenInventory().getTitle().equalsIgnoreCase(title)) { + cancel(); + return; + } + setItem(x, y, clickableItem); + } + }.runTaskTimer(LandCore.getInstance(), 2L, 5L); + } else { + setItem(x, y, clickableItem); + } + } + + ClickableItem getItem(int slot) { + int y = Math.abs(slot / 9); + int x = -(y * 9 - slot); + if (this.items.length <= x) { + return null; + } + ClickableItem[] items = this.items[x]; + if (items.length <= y) { + return null; + } + return items[y]; + } + + Inventory toInventory() { + if (this.cachedInventory != null) { + return this.cachedInventory; + } + + Inventory inventory = Bukkit.getServer().createInventory(new InventoryMakerHolder(InventoryMaker.this), this.rows * 9, this.title); + for (int y = 0; y < this.rows; y++) { + for (int x = 0; x < 9; x++) { + int slot = y * 9 + x; + ClickableItem item = this.items[x][y]; + if (item != null) { + inventory.setItem(slot, item.getItemStack()); + } + } + } + this.cachedInventory = inventory; + return inventory; + } + + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryUI.java b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryUI.java new file mode 100644 index 0000000..98105bc --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryUI.java @@ -0,0 +1,377 @@ +package me.devkevin.landcore.utils.inventory; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.utils.item.ItemUtil; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +public class InventoryUI { + + private final List inventories; + private final String title; + private final int rowOffset; + private final int rows; + private int offset; + private int page; + + public InventoryUI(final String title, final int rows) { + this(title, rows, 0); + } + + public InventoryUI(final String title, final boolean bool, final int rows) { + this(title, rows, 0); + } + + public InventoryUI(final String title, final int rows, final int rowOffset) { + this.inventories = new LinkedList(); + this.title = title; + this.rows = rows; + this.rowOffset = rowOffset; + } + + public Inventory2D getCurrentUI() { + return this.inventories.get(this.page); + } + + public Inventory getCurrentPage() { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + return this.inventories.get(this.page).toInventory(); + } + + public ClickableItem getItem(final int slot) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + final Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + return lastInventory.getItem(slot); + } + + public int getSize() { + return this.rows * 9; + } + + private void createNewInventory() { + final Inventory2D inventory = new Inventory2D(this.title, this.rows, this.rowOffset); + if (this.inventories.size() > 0) { + inventory.setItem(0, this.rows - 1, new AbstractClickableItem(ItemUtil.createItem(Material.ARROW, ChatColor.RED + "Page #" + this.inventories.size())) { + @Override + public void onClick(final InventoryClickEvent event) { + InventoryUI.this.page--; + try { + final Inventory2D inventory2D = InventoryUI.this.inventories.get(InventoryUI.this.page); + if (inventory2D == null) { + InventoryUI.this.page++; + } else { + event.getWhoClicked().openInventory(InventoryUI.this.getCurrentPage()); + } + } catch (IndexOutOfBoundsException e) { + InventoryUI.this.page++; + } + } + }); + if (inventory.currentY == this.rows - 1 && inventory.currentX == -1) { + inventory.currentX++; + } + } + this.inventories.add(inventory); + } + + public void setItem(final int x, final int y, final ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + final Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + lastInventory.setItem(x - 1, y - 1, item); + } + + public void setItem(final int slot, final ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + final Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + lastInventory.setItem(slot, item); + } + + public void addItem(final ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + final Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + if (lastInventory.currentY == this.rows - 1 && lastInventory.currentX >= 7 - this.offset) { + lastInventory.setItem(8, this.rows - 1, new AbstractClickableItem(ItemUtil.createItem(Material.ARROW, ChatColor.RED + "Page #" + (this.inventories.size() + 1))) { + @Override + public void onClick(final InventoryClickEvent event) { + InventoryUI.this.page++; + try { + final Inventory2D inventory2D = InventoryUI.this.inventories.get(InventoryUI.this.page); + if (inventory2D == null) { + InventoryUI.this.page--; + } else { + event.getWhoClicked().openInventory(InventoryUI.this.getCurrentPage()); + } + } catch (IndexOutOfBoundsException e) { + InventoryUI.this.page--; + } + } + }); + this.createNewInventory(); + this.addItem(item); + } else { + lastInventory.setItem(++lastInventory.currentX + this.offset, lastInventory.currentY, item); + } + if (lastInventory.currentX >= 8 - this.offset) { + lastInventory.currentX = this.offset - 1; + lastInventory.currentY++; + } + } + + public void removeItem(final int slot) { + final Inventory2D inventory2D = this.inventories.get(this.page); + this.setItem(slot, null); + for (int i = slot + 1; i < this.getSize(); ++i) { + final ClickableItem item = this.getItem(i); + this.setItem(i - 1, item); + this.setItem(i, null); + } + if (inventory2D.currentX >= 0) { + inventory2D.currentX--; + } else if (inventory2D.currentY > 0) { + inventory2D.currentY--; + inventory2D.currentX = 7; + } + } + + public String getTitle() { + return this.title; + } + + public int getRowOffset() { + return this.rowOffset; + } + + public int getRows() { + return this.rows; + } + + public int getOffset() { + return this.offset; + } + + public void setOffset(final int offset) { + this.offset = offset; + } + + public int getPage() { + return this.page; + } + + public List getInventories() { + return this.inventories; + } + + public interface ClickableItem { + void onClick(final InventoryClickEvent p0); + + ItemStack getItemStack(); + + void setItemStack(final ItemStack p0); + + ItemStack getDefaultItemStack(); + } + + public static class EmptyClickableItem implements ClickableItem { + private final ItemStack defaultItemStack; + private ItemStack itemStack; + + public EmptyClickableItem(final ItemStack itemStack) { + this.itemStack = itemStack; + this.defaultItemStack = itemStack; + } + + @Override + public void onClick(final InventoryClickEvent event) { + } + + @Override + public ItemStack getDefaultItemStack() { + return this.defaultItemStack; + } + + @Override + public ItemStack getItemStack() { + return this.itemStack; + } + + @Override + public void setItemStack(final ItemStack itemStack) { + this.itemStack = itemStack; + } + } + + public abstract static class AbstractClickableItem implements ClickableItem { + private final ItemStack defaultItemStack; + private ItemStack itemStack; + + public AbstractClickableItem(final ItemStack itemStack) { + this.itemStack = itemStack; + this.defaultItemStack = itemStack; + } + + @Override + public ItemStack getDefaultItemStack() { + return this.defaultItemStack; + } + + @Override + public ItemStack getItemStack() { + return this.itemStack; + } + + @Override + public void setItemStack(final ItemStack itemStack) { + this.itemStack = itemStack; + } + } + + public static class InventoryUIHolder implements InventoryHolder, me.devkevin.landcore.utils.inventory.InventoryUIHolder { + private InventoryUI inventoryUI; + private String title; + private int slots; + + private InventoryUIHolder(final InventoryUI inventoryUI, final String title, final int slots) { + this.inventoryUI = inventoryUI; + this.title = title; + this.slots = slots; + } + + public Inventory getInventory() { + return this.inventoryUI.getCurrentPage(); + } + + public InventoryUI getInventoryUI() { + return this.inventoryUI; + } + + public String getTitle() { + return this.title; + } + + public int getSlots() { + return this.slots; + } + + public World getWorld() { + return null; + } + } + + public static void removeCrafting(Material material) { + Iterator iterator = LandCore.getInstance().getServer().recipeIterator(); + + while (iterator.hasNext()) { + Recipe recipe = iterator.next(); + + if (recipe != null && recipe.getResult().getType() == material) { + iterator.remove(); + } + } + } + + public class Inventory2D { + private final ClickableItem[][] items; + private final String title; + private final int rows; + private Inventory cachedInventory; + private int currentX; + private int currentY; + + public Inventory2D(final String title, final int rows, final int rowOffset) { + this.currentX = -1; + this.currentY = rowOffset; + this.title = title; + this.rows = rows; + this.items = new ClickableItem[9][this.rows]; + } + + public void setItem(final int x, final int y, final ClickableItem clickableItem) { + this.items[x][y] = clickableItem; + if (this.cachedInventory != null) { + final int slot = y * 9 + x; + this.cachedInventory.setItem(slot, (clickableItem != null) ? clickableItem.getItemStack() : null); + } + } + + public void setItem(final int slot, final ClickableItem clickableItem) { + final int y = Math.abs(slot / 9); + final int x = -(y * 9 - slot); + this.setItem(x, y, clickableItem); + } + + public ClickableItem getItem(final int slot) { + final int y = Math.abs(slot / 9); + final int x = -(y * 9 - slot); + if (this.items.length <= x) { + return null; + } + final ClickableItem[] items = this.items[x]; + if (items.length <= y) { + return null; + } + return items[y]; + } + + public Inventory toInventory() { + if (this.cachedInventory != null) { + return this.cachedInventory; + } + final Inventory inventory = Bukkit.getServer().createInventory(new InventoryUIHolder(InventoryUI.this, this.title, this.rows * 9), this.rows * 9, this.title); + for (int y = 0; y < this.rows; ++y) { + for (int x = 0; x < 9; ++x) { + final int slot = y * 9 + x; + final ClickableItem item = this.items[x][y]; + if (item != null) { + inventory.setItem(slot, item.getItemStack()); + } + } + } + return this.cachedInventory = inventory; + } + + public ClickableItem[][] getItems() { + return this.items; + } + + public String getTitle() { + return this.title; + } + + public int getRows() { + return this.rows; + } + + public Inventory getCachedInventory() { + return this.cachedInventory; + } + + public int getCurrentX() { + return this.currentX; + } + + public int getCurrentY() { + return this.currentY; + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryUIHolder.java b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryUIHolder.java new file mode 100644 index 0000000..b9ccdb1 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/InventoryUIHolder.java @@ -0,0 +1,4 @@ +package me.devkevin.landcore.utils.inventory; + +public interface InventoryUIHolder { +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/UIListener.java b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/UIListener.java new file mode 100644 index 0000000..3116500 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/UIListener.java @@ -0,0 +1,32 @@ +package me.devkevin.landcore.utils.inventory; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class UIListener implements Listener { + + @EventHandler + public void onClick(InventoryClickEvent event) { + if (event.getInventory() == null) { + return; + } + if (!(event.getInventory().getHolder() instanceof InventoryUI.InventoryUIHolder)) { + return; + } + if (event.getCurrentItem() == null) { + return; + } + InventoryUI.InventoryUIHolder inventoryUIHolder = (InventoryUI.InventoryUIHolder) event.getInventory().getHolder(); + event.setCancelled(true); + if (event.getClickedInventory() == null || !event.getInventory().equals(event.getClickedInventory())) { + return; + } + InventoryUI ui = inventoryUIHolder.getInventoryUI(); + InventoryUI.ClickableItem item = ui.getCurrentUI().getItem(event.getSlot()); + if (item == null) { + return; + } + item.onClick(event); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/UtilItem.java b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/UtilItem.java new file mode 100644 index 0000000..a0f5bdd --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/inventory/UtilItem.java @@ -0,0 +1,83 @@ +package me.devkevin.landcore.utils.inventory; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.List; + +public class UtilItem { + + public static ItemStack createItem(final Material m, final int amount) { + return new ItemStack(m, amount); + } + + public static ItemStack createItem(final Material m, final int amount, final short durability) { + return new ItemStack(m, amount, durability); + } + + public static ItemStack createItem(final Material m, final int amount, final short durability, final String name) { + ItemStack itemStack = new ItemStack(m, amount, durability); + if (name != null) { + itemStack = name(itemStack, name); + } + return itemStack; + } + + public static ItemStack createItem(final Material m, final int amount, final short durability, final String name, final Enchantment enchantment, final int level) { + ItemStack itemStack = new ItemStack(m, amount, durability); + if (name != null) { + itemStack = name(itemStack, name); + } + return enchantItem(itemStack, enchantment, level); + } + + public static ItemStack createItem(final Material m, final int amount, final short durability, final String name, final List lore) { + ItemStack itemStack = new ItemStack(m, amount, durability); + if (name != null) { + itemStack = name(itemStack, name); + } + if (lore != null) { + itemStack = lore(itemStack, lore); + } + return itemStack; + } + + public static ItemStack skull(final ItemStack itemStack, final String playerName) { + final SkullMeta meta = (SkullMeta) itemStack.getItemMeta(); + meta.setOwner(playerName); + itemStack.setItemMeta(meta); + return itemStack; + } + + public static ItemStack name(final ItemStack itemStack, final String itemName) { + final ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setDisplayName(itemName); + itemStack.setItemMeta(itemMeta); + return itemStack; + } + + public static ItemStack lore(final ItemStack itemStack, final List lore) { + final ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setLore(lore); + itemStack.setItemMeta(itemMeta); + return itemStack; + } + + public static ItemStack enchantItem(final ItemStack itemStack, final Enchantment enchantment, final int level) { + itemStack.addUnsafeEnchantment(enchantment, level); + return itemStack; + } + + public static ItemStack effectItem(final ItemStack itemStack, final PotionEffectType potionEffectType, final int time, final int amplifier) { + final PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); + potionMeta.addCustomEffect(new PotionEffect(potionEffectType, time * 20, amplifier), true); + itemStack.setItemMeta(potionMeta); + return itemStack; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemBuilder.java b/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemBuilder.java new file mode 100644 index 0000000..d1a1e5b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemBuilder.java @@ -0,0 +1,179 @@ +package me.devkevin.landcore.utils.item; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import org.apache.commons.codec.binary.Base64; +import org.bukkit.ChatColor; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.material.MaterialData; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ItemBuilder implements Listener { + + public final ItemStack is; + + public ItemBuilder(final Material mat) { + is = new ItemStack(mat); + } + + public ItemBuilder(final ItemStack is) { + this.is = is; + } + + public ItemBuilder amount(final int amount) { + is.setAmount(amount); + + return this; + } + + public ItemBuilder name(final String name) { + final ItemMeta meta = is.getItemMeta(); + meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder lore(final String name) { + final ItemMeta meta = is.getItemMeta(); + List lore = meta.getLore(); + if (lore == null) { + lore = new ArrayList<>(); + } + + lore.add(name); + meta.setLore(lore); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder lore(final 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(final int durability) { + is.setDurability((short) durability); + + return this; + } + + public ItemBuilder head(String url) { + SkullMeta headMeta = (SkullMeta) is.getItemMeta(); + GameProfile profile = new GameProfile(UUID.randomUUID(), null); + byte[] encodedData = Base64.encodeBase64(String.format("{textures:{SKIN:{url:\"%s\"}}}", url).getBytes()); + profile.getProperties().put("textures", new Property("textures", new String(encodedData))); + Field profileField; + + try { + profileField = headMeta.getClass().getDeclaredField("profile"); + profileField.setAccessible(true); + profileField.set(headMeta, profile); + } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) { + e1.printStackTrace(); + } + + is.setItemMeta(headMeta); + return this; + } + + public ItemBuilder owner(String owner) { + if (this.is.getType() == Material.SKULL_ITEM) { + SkullMeta meta = (SkullMeta) this.is.getItemMeta(); + meta.setOwner(owner); + this.is.setItemMeta(meta); + return this; + } + + throw new IllegalArgumentException("setOwner() only applicable for Skull Item"); + } + + @SuppressWarnings("deprecation") + public ItemBuilder data(final int data) { + is.setData(new MaterialData(is.getType(), (byte) data)); + + return this; + } + + public ItemBuilder unbreakable(boolean unbreakable) { + is.getItemMeta().spigot().setUnbreakable(unbreakable); + return this; + } + + public ItemBuilder enchantment(final Enchantment enchantment, final int level) { + is.addUnsafeEnchantment(enchantment, level); + return this; + } + + public ItemBuilder enchantment(final Enchantment enchantment) { + is.addUnsafeEnchantment(enchantment, 1); + return this; + } + + public ItemBuilder hideFlags() { + final ItemMeta meta = is.getItemMeta(); + meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_ATTRIBUTES); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder type(final Material material) { + is.setType(material); + return this; + } + + public ItemBuilder clearLore() { + final ItemMeta meta = is.getItemMeta(); + meta.setLore(new ArrayList<>()); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder clearEnchantments() { + for (final Enchantment e : is.getEnchantments().keySet()) { + is.removeEnchantment(e); + } + + return this; + } + + public ItemBuilder color(Color color) { + if (is.getType() == Material.LEATHER_BOOTS || is.getType() == Material.LEATHER_CHESTPLATE + || is.getType() == Material.LEATHER_HELMET || is.getType() == Material.LEATHER_LEGGINGS) { + LeatherArmorMeta meta = (LeatherArmorMeta) is.getItemMeta(); + meta.setColor(color); + is.setItemMeta(meta); + + return this; + } else { + throw new IllegalArgumentException("color() only applicable for leather armor!"); + } + } + + public ItemStack build() { + return is; + } +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemMaker.java b/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemMaker.java new file mode 100644 index 0000000..71ecc7e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemMaker.java @@ -0,0 +1,109 @@ +package me.devkevin.landcore.utils.item; + +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ItemMaker { + + private ItemStack itemStack; + private ItemMeta itemMeta; + + private Map enchantments = new HashMap<>(); + + + public ItemMaker(Material material) { + this.itemStack = new ItemStack(material); + this.itemMeta = itemStack.getItemMeta(); + } + + public ItemMaker(ItemStack itemStack) { + this.itemStack = itemStack; + this.itemMeta = itemStack.getItemMeta(); + } + + public ItemMaker setOwner(String name) { + SkullMeta meta = (SkullMeta) itemMeta; + meta.setOwner(name); + itemMeta.setDisplayName(name); + return this; + } + + public ItemMaker setAmount(int amount) { + itemStack.setAmount(amount); + return this; + } + + public ItemMaker setDisplayName(String name) { + itemMeta.setDisplayName(CC.translate(name)); + return this; + } + + public ItemMaker setDurability(int durability) { + itemStack.setDurability((short) durability); + return this; + } + + public ItemMaker addLore(String lore) { + Object object = itemMeta.getLore(); + if (object == null) object = new ArrayList<>(); + + ((List) object).add(CC.translate(lore)); + itemMeta.setLore((List) object); + return this; + } + + public ItemMaker addLore(List lore) { + itemMeta.setLore(CC.translate(lore)); + return this; + } + + public ItemMaker addLore(String... lore) { + List strings = new ArrayList<>(); + for (String string : lore) { + strings.add(CC.translate(string)); + } + itemMeta.setLore(strings); + return this; + } + + public ItemMaker setEnchant(Enchantment enchantment, int level) { + enchantments.put(enchantment, level); + return this; + } + + public ItemMaker setUnbreakable(boolean unbreakable) { + itemMeta.spigot().setUnbreakable(unbreakable); + return this; + } + + public ItemMaker setColor(Color color) { + if (itemStack.getType() != null && itemStack.getType().name().contains("LEATHER")) { + LeatherArmorMeta armorMeta = (LeatherArmorMeta) itemMeta; + armorMeta.setColor(color); + } + return this; + } + + public ItemStack create() { + if (itemMeta != null) { + itemStack.setItemMeta(itemMeta); + } + + for (Enchantment enchantment : enchantments.keySet()) { + itemStack.addEnchantment(enchantment, enchantments.get(enchantment)); + } + + return itemStack; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemUtil.java new file mode 100644 index 0000000..107bb4c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/item/ItemUtil.java @@ -0,0 +1,167 @@ +package me.devkevin.landcore.utils.item; + +import me.devkevin.landcore.utils.BukkitReflection; +import lombok.RequiredArgsConstructor; +import org.apache.commons.lang.WordUtils; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +public class ItemUtil { + + private ItemUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + public static String getName(ItemStack item) { + if (item.getDurability() != 0) { + String reflectedName = BukkitReflection.getItemStackName(item); + if (reflectedName != null) { + if (reflectedName.contains(".")) + reflectedName = WordUtils.capitalize(item.getType().toString().toLowerCase().replace("_", " ")); + return reflectedName; + } + } + String string = item.getType().toString().replace("_", " "); + char[] chars = string.toLowerCase().toCharArray(); + boolean found = false; + for (int i = 0; i < chars.length; i++) { + if (!found && Character.isLetter(chars[i])) { + chars[i] = Character.toUpperCase(chars[i]); + found = true; + } else if (Character.isWhitespace(chars[i]) || chars[i] == '.' || chars[i] == '\'') { + found = false; + } + } + return String.valueOf(chars); + } + + public static String formatMaterial(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(ItemStack itemStack, ItemEnchant... enchantments) { + Arrays.asList(enchantments).forEach(enchantment -> itemStack.addUnsafeEnchantment(enchantment.enchantment, enchantment.level)); + return itemStack; + } + + public static ItemStack createItem(Material material, String name) { + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createItem(Material material, String name, int amount) { + ItemStack item = new ItemStack(material, amount); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack renameItem(ItemStack item, String name) { + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack reloreItem(ItemStack item, String... lores) { + return reloreItem(ReloreType.OVERWRITE, item, lores); + } + + public static ItemStack reloreItem(ReloreType type, ItemStack item, String... lores) { + ItemMeta meta = item.getItemMeta(); + + List lore = meta.getLore(); + if (lore == null) { + lore = new LinkedList<>(); + } + + switch (type) { + case APPEND: + lore.addAll(Arrays.asList(lores)); + meta.setLore(lore); + break; + case PREPEND: + 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 enum ReloreType { + OVERWRITE, + PREPEND, + APPEND + } + + public static void removeItems(Inventory inventory, ItemStack item, int amount) { + for (int size = inventory.getSize(), slot = 0; slot < size; ++slot) { + ItemStack is = inventory.getItem(slot); + if (is != null && item.getType() == is.getType() && item.getDurability() == is.getDurability()) { + 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; + } + } + } + } + } + + @RequiredArgsConstructor + public static class ItemEnchant { + private final Enchantment enchantment; + private final int level; + } + +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonChain.java b/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonChain.java new file mode 100644 index 0000000..415d80e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonChain.java @@ -0,0 +1,42 @@ +package me.devkevin.landcore.utils.json; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:41 + * JsonChain / me.devkevin.landcore.utils.json / LandCore + */ +public class JsonChain { + private JsonObject json = new JsonObject(); + + public JsonChain addProperty(String property, String value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Number value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Boolean value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Character value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain add(String property, JsonElement element) { + this.json.add(property, element); + return this; + } + + public JsonObject get() { + return this.json; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonDeserializer.java b/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonDeserializer.java new file mode 100644 index 0000000..bcc0c8e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonDeserializer.java @@ -0,0 +1,12 @@ +package me.devkevin.landcore.utils.json; + +import com.google.gson.JsonObject; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:40 + * JsonDeserializer / me.devkevin.landcore.utils.json / LandCore + */ +public interface JsonDeserializer { + T deserialize(JsonObject object); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonSerializer.java b/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonSerializer.java new file mode 100644 index 0000000..d046d26 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/json/JsonSerializer.java @@ -0,0 +1,12 @@ +package me.devkevin.landcore.utils.json; + +import com.google.gson.JsonObject; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/01/2023 @ 2:38 + * JsonSerializer / me.devkevin.landcore.utils / LandCore + */ +public interface JsonSerializer { + JsonObject serialize(T t); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/location/CustomLocation.java b/LandCore/src/main/java/me/devkevin/landcore/utils/location/CustomLocation.java new file mode 100644 index 0000000..db16c09 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/location/CustomLocation.java @@ -0,0 +1,142 @@ +package me.devkevin.landcore.utils.location; + +import me.devkevin.landcore.LandCore; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.StringJoiner; + + +/** + * Highly efficient version of the ${@link org.bukkit.Location} class. + * Recommended to store ${@link CustomLocation} + * instead of using Bukkit's interpretation. + */ +@Getter +@Setter +@AllArgsConstructor +public class CustomLocation { + + private final long timestamp = System.currentTimeMillis(); + + private String world; + + private double x; + private double y; + private double z; + + private float yaw; + private float pitch; + + public CustomLocation(double x, double y, double z) { + this(x, y, z, 0.0F, 0.0F); + } + + public CustomLocation(String world, double x, double y, double z) { + this(world, x, y, z, 0.0F, 0.0F); + } + + public CustomLocation(double x, double y, double z, float yaw, float pitch) { + this("world", x, y, z, yaw, pitch); + } + + public static CustomLocation fromBukkitLocation(Location location) { + return new CustomLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), + location.getYaw(), location.getPitch()); + } + + public static CustomLocation stringToLocation(String string) { + String[] split = string.split(", "); + + double x = Double.parseDouble(split[0]); + double y = Double.parseDouble(split[1]); + double z = Double.parseDouble(split[2]); + + CustomLocation customLocation = new CustomLocation(x, y, z); + + if (split.length == 4) { + customLocation.setWorld(split[3]); + } else if (split.length >= 5) { + customLocation.setYaw(Float.parseFloat(split[3])); + customLocation.setPitch(Float.parseFloat(split[4])); + + if (split.length >= 6) { + customLocation.setWorld(split[5]); + } + } + return customLocation; + } + + public static String locationToString(CustomLocation loc) { + StringJoiner joiner = new StringJoiner(", "); + joiner.add(Double.toString(loc.getX())); + joiner.add(Double.toString(loc.getY())); + joiner.add(Double.toString(loc.getZ())); + if (loc.getYaw() == 0.0f && loc.getPitch() == 0.0f) { + if (loc.getWorld().equals("world")) { + return joiner.toString(); + } else { + joiner.add(loc.getWorld()); + return joiner.toString(); + } + } else { + joiner.add(Float.toString(loc.getYaw())); + joiner.add(Float.toString(loc.getPitch())); + if (loc.getWorld().equals("world")) { + return joiner.toString(); + } else { + joiner.add(loc.getWorld()); + return joiner.toString(); + } + } + } + + public Location toBukkitLocation() { + return new Location(this.toBukkitWorld(), this.x, this.y, this.z, this.yaw, this.pitch); + } + + public double getGroundDistanceTo(CustomLocation location) { + return Math.sqrt(Math.pow(this.x - location.x, 2) + Math.pow(this.z - location.z, 2)); + } + + public double getDistanceTo(CustomLocation location) { + return Math.sqrt(Math.pow(this.x - location.x, 2) + Math.pow(this.y - location.y, 2) + Math.pow(this.z - location.z, 2)); + } + + public World toBukkitWorld() { + if (this.world == null) { + return LandCore.getInstance().getServer().getWorlds().get(0); + } else { + return LandCore.getInstance().getServer().getWorld(this.world); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CustomLocation)) { + return false; + } + + CustomLocation location = (CustomLocation) obj; + return location.x == this.x && location.y == this.y && location.z == this.z + && location.pitch == this.pitch && location.yaw == this.yaw; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("x", this.x) + .append("y", this.y) + .append("z", this.z) + .append("yaw", this.yaw) + .append("pitch", this.pitch) + .append("world", this.world) + .append("timestamp", this.timestamp) + .toString(); + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/Button.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/Button.java new file mode 100644 index 0000000..7338239 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/Button.java @@ -0,0 +1,59 @@ +package me.devkevin.landcore.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; + +import java.io.IOException; + +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, int slot, ClickType clickType, int hotbarButton){ + } + + public boolean shouldCancel(Player player, int slot, ClickType clickType) { + return (true); + } + + public boolean shouldUpdate(Player player, int slot, ClickType clickType) { + return (false); + } + + public static void playSound(Player player, ButtonSound buttonSound) { + player.playSound(player.getLocation(), buttonSound.getSound(), 20.0F, 1.0F); + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/ButtonListener.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/ButtonListener.java new file mode 100644 index 0000000..bfe9613 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/ButtonListener.java @@ -0,0 +1,122 @@ +package me.devkevin.landcore.utils.menu; + +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.utils.menu.pagination.PaginatedMenu; +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; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.metadata.FixedMetadataValue; + +public class ButtonListener implements Listener { + + public ButtonListener() { + Bukkit.getPluginManager().registerEvents(this, LandCore.getInstance()); + } + + @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.getSlot(), 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.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.getSlot(), event.getClick()); + + if (buttonUpdate) { + openMenu.setClosedByMenu(true); + newMenu.openMenu(player); + } + } + } else if (button.shouldUpdate(player, event.getSlot(), event.getClick())) { + openMenu.setClosedByMenu(true); + openMenu.openMenu(player); + } + + if (event.isCancelled()) { + Bukkit.getScheduler().runTaskLater(LandCore.getInstance(), player::updateInventory, 1L); + } + } else { + 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()); + + if (openMenu instanceof PaginatedMenu) { + return; + } + } + + player.setMetadata("scanglitch", new FixedMetadataValue(LandCore.getInstance(), true)); + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + + if (player.hasMetadata("scanglitch")) { + player.removeMetadata("scanglitch", LandCore.getInstance()); + + for (ItemStack it : player.getInventory().getContents()) { + if (it != null) { + ItemMeta meta = it.getItemMeta(); + if (meta != null && meta.hasDisplayName()) { + + if (meta.getDisplayName().contains("§b§c§d§e")) { + player.getInventory().remove(it); + } + } + } + } + } + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/ButtonSound.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/ButtonSound.java new file mode 100644 index 0000000..1c1ae02 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/ButtonSound.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.utils.menu; + +import lombok.Getter; +import org.bukkit.Sound; + +public enum ButtonSound { + + CLICK(Sound.CLICK),//Sound.CLICK stari + SUCCESS(Sound.SUCCESSFUL_HIT), + FAIL(Sound.DIG_GRASS); + + @Getter private Sound sound; + + ButtonSound(Sound sound) { + this.sound = sound; + } +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/Menu.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/Menu.java new file mode 100644 index 0000000..1ea96a2 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/Menu.java @@ -0,0 +1,161 @@ +package me.devkevin.landcore.utils.menu; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Bukkit; +import org.bukkit.Material; +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; +import java.util.stream.IntStream; + +@Getter +@Setter +public abstract class Menu { + + @Getter public static Map currentlyOpenedMenus = new HashMap<>(); + private Map buttons = new HashMap<>(); + private boolean autoUpdate = false; + private boolean updateAfterClick = true; + private boolean closedByMenu = false; + private boolean placeholder = false; + private Button placeholderButton = 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 fill(Map buttons, ItemStack itemStack) { + IntStream.range(0, getSize()).filter((slot) -> { + return buttons.get(slot) == null; + }).forEach((slot) -> { + buttons.put(slot, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return itemStack; + } + }); + }); + } + + public void openMenu(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 = 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); + player.closeInventory(); + } + } + } + + if (inventory == null) { + inventory = Bukkit.createInventory(player, size, CC.translate(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 getSlot(int x, int y) { + return ((9 * y) + x); + } + + public int getSize() { + return -1; + } + + public abstract String getTitle(Player player); + + public abstract Map getButtons(Player player); + + public void onOpen(Player player) { + } + + public void onClose(Player player) { + } + + protected void surroundButtons(boolean full, Map buttons, ItemStack itemStack) { + IntStream.range(0, getSize()).filter(slot -> buttons.get(slot) == null).forEach(slot -> { + if (slot < 9 || slot > getSize() - 10 || full && (slot % 9 == 0 || (slot+1) % 9 == 0)) { + buttons.put(slot, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return itemStack; + } + }); + } + }); + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/MenuUpdateTask.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/MenuUpdateTask.java new file mode 100644 index 0000000..4cbd2f2 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/MenuUpdateTask.java @@ -0,0 +1,31 @@ +package me.devkevin.landcore.utils.menu; + +import me.devkevin.landcore.LandCore; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Map; + +public class MenuUpdateTask extends BukkitRunnable { + + public MenuUpdateTask() { + runTaskTimerAsynchronously(LandCore.getInstance(), 2L, 2L); + } + + @Override + public void run() { + for (Map.Entry entry : Menu.getCurrentlyOpenedMenus().entrySet()) { + String key = entry.getKey(); + Menu value = entry.getValue(); + Player player = Bukkit.getPlayer(key); + + if (player != null) { + if (value.isAutoUpdate()) { + value.openMenu(player); + } + } + } + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/TypeCallback.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/TypeCallback.java new file mode 100644 index 0000000..fc89ee3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/TypeCallback.java @@ -0,0 +1,9 @@ +package me.devkevin.landcore.utils.menu; + +import java.io.Serializable; + +public interface TypeCallback extends Serializable { + + void callback(T data); + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/BackButton.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/BackButton.java new file mode 100644 index 0000000..1f1652a --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/BackButton.java @@ -0,0 +1,31 @@ +package me.devkevin.landcore.utils.menu.buttons; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class BackButton extends Button { + + private Menu back; + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.ARROW).name(CC.translate("&cGo back")); + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + Button.playNeutral(player); + + this.back.openMenu(player); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/CloseButton.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/CloseButton.java new file mode 100644 index 0000000..948acdf --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/CloseButton.java @@ -0,0 +1,28 @@ +package me.devkevin.landcore.utils.menu.buttons; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class CloseButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.INK_SACK).durability(1).name(CC.translate("&cClose")); + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + Button.playNeutral(player); + + player.closeInventory(); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/ConfirmationButton.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/ConfirmationButton.java new file mode 100644 index 0000000..df937e0 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/ConfirmationButton.java @@ -0,0 +1,46 @@ +package me.devkevin.landcore.utils.menu.buttons; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.TypeCallback; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class ConfirmationButton extends Button { + + private boolean confirm; + private TypeCallback callback; + private boolean closeAfterResponse; + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.WOOL); + + item.durability(this.confirm ? ((byte) 5) : ((byte) 14)); + item.name(CC.translate(this.confirm ? "&aConfirm" : "&cCancel")); + + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + 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) { + player.closeInventory(); + } + + this.callback.callback(this.confirm); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/DisplayButton.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/DisplayButton.java new file mode 100644 index 0000000..6a94bca --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/DisplayButton.java @@ -0,0 +1,34 @@ +package me.devkevin.landcore.utils.menu.buttons; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.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, int slot, ClickType clickType) { + return this.cancel; + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/Glass.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/Glass.java new file mode 100644 index 0000000..02270af --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/buttons/Glass.java @@ -0,0 +1,26 @@ +package me.devkevin.landcore.utils.menu.buttons; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class Glass extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.STAINED_GLASS_PANE).durability(7).name(CC.translate(" ")); + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + //Button.playNeutral(player); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/menus/ConfirmMenu.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/menus/ConfirmMenu.java new file mode 100644 index 0000000..a6f52ff --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/menus/ConfirmMenu.java @@ -0,0 +1,71 @@ +package me.devkevin.landcore.utils.menu.menus; + +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.menu.TypeCallback; +import me.devkevin.landcore.utils.menu.buttons.ConfirmationButton; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +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<>(); + + Integer[] cPanes = new Integer[] { 0,1,2,9,11,18,19,20}; + for (int i : cPanes) { + buttons.put(i, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability((byte) 5).build(); + } + }); + buttons.put(10, new ConfirmationButton(true, response, closeAfterResponse)); + } + + Integer[] dPanes = new Integer[] { 6,7,8,15,17,24,25,26}; + for (int i : dPanes) { + buttons.put(i, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability((byte) 14).build(); + } + }); + buttons.put(16, 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/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/GlassFill.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/GlassFill.java new file mode 100644 index 0000000..d630271 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/GlassFill.java @@ -0,0 +1,33 @@ +package me.devkevin.landcore.utils.menu.pagination; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class GlassFill extends Button { + + private PaginatedMenu menu; + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.STAINED_GLASS_PANE); + + item.durability((byte) 7); + + item.name(CC.translate(" ")); + + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + } + + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/JumpToPageButton.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/JumpToPageButton.java new file mode 100644 index 0000000..8987d32 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/JumpToPageButton.java @@ -0,0 +1,36 @@ +package me.devkevin.landcore.utils.menu.pagination; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class JumpToPageButton extends Button { + + private int page; + private PaginatedMenu menu; + private boolean current; + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(this.current ? Material.EMPTY_MAP : Material.PAPER); + + item.amount(this.page); + item.name(CC.translate("&7Page " + this.page)); + if (this.current) item.lore("&7Current Page"); + + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + this.menu.modPage(player, this.page - this.menu.getPage()); + Button.playNeutral(player); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/PageButton.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/PageButton.java new file mode 100644 index 0000000..456d0b3 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/PageButton.java @@ -0,0 +1,57 @@ +package me.devkevin.landcore.utils.menu.pagination; + +import lombok.AllArgsConstructor; +import me.devkevin.landcore.utils.item.ItemBuilder; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +@AllArgsConstructor +public class PageButton extends Button { + + private int mod; + private PaginatedMenu menu; + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder item = new ItemBuilder(Material.LEVER); + + if (this.hasNext(player)) { + if (mod > 0) { + item.durability((byte) 13); + } else { + item.durability((byte) 14); + } + item.name(CC.translate(this.mod > 0 ? "&aNext page" : "&cPrevious page")); + } else { + item.durability((byte) 7); + item.name(CC.translate((this.mod > 0 ? "&7Last page" : "&7First page"))); + } + + return item.build(); + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + if (clickType == ClickType.RIGHT) { + new ViewAllPagesMenu(this.menu).openMenu(player); + playNeutral(player); + } else { + if (hasNext(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 pg > 0 && this.menu.getPages(player) >= pg; + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu.java new file mode 100644 index 0000000..9a5b5e8 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu.java @@ -0,0 +1,106 @@ +package me.devkevin.landcore.utils.menu.pagination; + +import lombok.Getter; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.message.CC; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.IntStream; + +public abstract class PaginatedMenu extends Menu { + + @Getter private int page = 1; + + { + setUpdateAfterClick(false); + } + + @Override + public String getTitle(Player player) { + return CC.translate(getPrePaginatedTitle(player) + " &8[" + page + "/" + getPages(player)+ "]"); + } + + public final void modPage(Player player, int mod) { + page += mod; + getButtons().clear(); + openMenu(player); + } + + 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)); + + HashMap buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + /*buttons.put(1, new GlassFill(this)); + buttons.put(2, new GlassFill(this)); + buttons.put(3, new GlassFill(this)); + buttons.put(4, new GlassFill(this)); + buttons.put(5, new GlassFill(this)); + buttons.put(6, new GlassFill(this)); + buttons.put(7, new GlassFill(this));*/ + + + 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()); + } + } + + 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; + } + + public Map getGlobalButtons(Player player) { + return null; + } + + public abstract String getPrePaginatedTitle(Player player); + + public abstract Map getAllPagesButtons(Player player); + + protected void surroundButtons(boolean full, Map buttons, ItemStack itemStack) { + IntStream.range(0, getSize()).filter(slot -> buttons.get(slot) == null).forEach(slot -> { + if (slot < 9 || slot > getSize() - 10 || full && (slot % 9 == 0 || (slot+1) % 9 == 0)) { + buttons.put(slot, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return itemStack; + } + }); + } + }); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/ViewAllPagesMenu.java b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/ViewAllPagesMenu.java new file mode 100644 index 0000000..3987cb5 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/menu/pagination/ViewAllPagesMenu.java @@ -0,0 +1,51 @@ +package me.devkevin.landcore.utils.menu.pagination; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.utils.menu.Button; +import me.devkevin.landcore.utils.menu.Menu; +import me.devkevin.landcore.utils.menu.buttons.BackButton; +import me.devkevin.landcore.utils.message.CC; +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 CC.translate("&cJump 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/LandCore/src/main/java/me/devkevin/landcore/utils/message/CC.java b/LandCore/src/main/java/me/devkevin/landcore/utils/message/CC.java new file mode 100644 index 0000000..2be0c40 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/message/CC.java @@ -0,0 +1,60 @@ +package me.devkevin.landcore.utils.message; + +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; + +import java.util.ArrayList; +import java.util.List; + +@UtilityClass +public class CC { + public static final String WHITE = ChatColor.WHITE.toString(); + public static final String GREEN = ChatColor.GREEN.toString(); + public static final String DARK_GREEN = ChatColor.DARK_GREEN.toString(); + public static final String RED = ChatColor.RED.toString(); + public static final String D_RED = ChatColor.DARK_RED.toString(); + public static final String D_BLUE = ChatColor.DARK_BLUE.toString(); + public static final String GRAY = ChatColor.GRAY.toString(); + public static final String BLACK = ChatColor.BLACK.toString(); + public static final String D_GRAY = ChatColor.DARK_GRAY.toString(); + public static final String YELLOW = ChatColor.YELLOW.toString(); + public static final String GOLD = ChatColor.GOLD.toString(); + public static final String AQUA = ChatColor.AQUA.toString(); + public static final String D_AQUA = ChatColor.DARK_AQUA.toString(); + public static final String BLUE = ChatColor.BLUE.toString(); + public static final String PINK = ChatColor.LIGHT_PURPLE.toString(); + public static final String PURPLE = ChatColor.DARK_PURPLE.toString(); + public static final String B = ChatColor.BOLD.toString(); + public static final String I = ChatColor.ITALIC.toString(); + public static final String U = ChatColor.UNDERLINE.toString(); + public static final String S = ChatColor.STRIKETHROUGH.toString(); + public static final String R = ChatColor.RESET.toString(); + public static final String PRIMARY = ChatColor.GOLD.toString(); + public static final String SECONDARY = ChatColor.YELLOW.toString(); + public static final String ACCENT = ChatColor.GOLD.toString(); + public static final String SPLITTER = "┃"; + public static final String BOARD_SEPARATOR = GRAY + S + "--------------------"; + public static final String SEPARATOR = GRAY + S + "-------------------------------------"; + public static char CIRCLE = '●'; + public static final String BD_RED = D_RED + B; + public static final String COIN = CC.GOLD + " \u26C0"; + + public static void logConsole(String message) { + Bukkit.getConsoleSender().sendMessage(ChatColor.translateAlternateColorCodes('&', message)); + } + + 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; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/message/ClickableMessage.java b/LandCore/src/main/java/me/devkevin/landcore/utils/message/ClickableMessage.java new file mode 100644 index 0000000..35567a6 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/message/ClickableMessage.java @@ -0,0 +1,102 @@ +package me.devkevin.landcore.utils.message; + +import net.md_5.bungee.api.chat.*; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +public class ClickableMessage { + private final List components = new ArrayList<>(); + private TextComponent current; + + public ClickableMessage(String msg) { + add(msg); + } + + public ClickableMessage add(String msg) { + TextComponent component = new TextComponent(msg); + components.add(component); + current = component; + return this; + } + + private void hover(TextComponent component, String msg) { + component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(msg).create())); + } + + public ClickableMessage hover(String msg) { + hover(current, msg); + return this; + } + + public ClickableMessage hoverAll(String msg) { + for (TextComponent component : components) { + hover(component, msg); + } + return this; + } + + private void command(TextComponent component, String command) { + component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command)); + } + + public ClickableMessage command(String command) { + command(current, command); + return this; + } + + public ClickableMessage commandAll(String command) { + for (TextComponent component : components) { + command(component, command); + } + return this; + } + + public ClickableMessage color(String color) { + current.setColor(net.md_5.bungee.api.ChatColor.getByChar(color.charAt(1))); + return this; + } + + public ClickableMessage color(ChatColor color) { + current.setColor(color.asBungee()); + return this; + } + + public ClickableMessage style(ChatColor color) { + switch (color) { + case UNDERLINE: + current.setUnderlined(true); + break; + case BOLD: + current.setBold(true); + break; + case ITALIC: + current.setItalic(true); + break; + case MAGIC: + current.setObfuscated(true); + break; + } + return this; + } + + public void sendToPlayer(Player player) { + player.sendMessage(this.asComponents()); + } + + public TextComponent[] asComponents() { + return this.components.toArray(new TextComponent[0]); + } + + public void broadcast() { + Bukkit.getOnlinePlayers().forEach(this::sendToPlayer); + CommandSender console = Bukkit.getConsoleSender(); + String msg = String.join("", components.stream().map(TextComponent::getText).collect(Collectors.toList())); + console.sendMessage(msg); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/message/Messages.java b/LandCore/src/main/java/me/devkevin/landcore/utils/message/Messages.java new file mode 100644 index 0000000..4338a18 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/message/Messages.java @@ -0,0 +1,192 @@ +package me.devkevin.landcore.utils.message; + +import me.devkevin.landcore.LandCore; +import lombok.experimental.UtilityClass; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; + +@UtilityClass +public class Messages { + public static final String PLAYER_NOT_FOUND = CC.RED + "Player not found."; + public static final String DATA_LOAD_FAIL = CC.RED + "Something went wrong; try re-logging." + + "\nIf this problem persists, please contact staff for support."; + private static final String APPEAL_MESSAGE = CC.GRAY + "\nIf you believe this was a false ban, you can appeal it at " + + CC.YELLOW + "http://appeal.prac.lol" + CC.GRAY + " or buy an unban at " + CC.YELLOW + "http://prac.lol.buycraft.net" + CC.GRAY + "."; + public static final String BANNED_PERMANENTLY = CC.RED + "You are permanently banned." + APPEAL_MESSAGE; + public static final String BANNED_TEMPORARILY = CC.RED + "You are banned for %s." + APPEAL_MESSAGE; + public static final String DISCORD_LINK = "discord.me/" + LandCore.getInstance().getNetworkName(); + private static final int CENTER_PX = 154; + + public static final String[] FROZEN_MESSAGE = { + "&c&m------------------------------", + "&4You have been frozen.", + "&c&m------------------------------", + "&4To prove your innocence, join a support channel in:", + "&e" + DISCORD_LINK + }; + + public static void sendCenteredMessage(CommandSender sender, String message) { + if (message == null || message.equals("")) sender.sendMessage(""); + message = ChatColor.translateAlternateColorCodes('&', message); + + int messagePxSize = 0; + boolean previousCode = false; + boolean isBold = false; + + for (char c : message.toCharArray()) { + if (c == '§') { + previousCode = true; + continue; + } else if (previousCode == true) { + previousCode = false; + if (c == 'l' || c == 'L') { + isBold = true; + continue; + } else isBold = false; + } else { + DefaultFontInfo dFI = DefaultFontInfo.getDefaultFontInfo(c); + messagePxSize += isBold ? dFI.getBoldLength() : dFI.getLength(); + messagePxSize++; + } + } + + int halvedMessageSize = messagePxSize / 2; + int toCompensate = CENTER_PX - halvedMessageSize; + int spaceLength = DefaultFontInfo.SPACE.getLength() + 1; + int compensated = 0; + StringBuilder sb = new StringBuilder(); + while (compensated < toCompensate) { + sb.append(" "); + compensated += spaceLength; + } + sender.sendMessage(sb.toString() + message); + } + + public enum DefaultFontInfo { + + A('A', 5), + a('a', 5), + B('B', 5), + b('b', 5), + C('C', 5), + c('c', 5), + D('D', 5), + d('d', 5), + E('E', 5), + e('e', 5), + F('F', 5), + f('f', 4), + G('G', 5), + g('g', 5), + H('H', 5), + h('h', 5), + I('I', 3), + i('i', 1), + J('J', 5), + j('j', 5), + K('K', 5), + k('k', 4), + L('L', 5), + l('l', 1), + M('M', 5), + m('m', 5), + N('N', 5), + n('n', 5), + O('O', 5), + o('o', 5), + P('P', 5), + p('p', 5), + Q('Q', 5), + q('q', 5), + R('R', 5), + r('r', 5), + S('S', 5), + s('s', 5), + T('T', 5), + t('t', 4), + U('U', 5), + u('u', 5), + V('V', 5), + v('v', 5), + W('W', 5), + w('w', 5), + X('X', 5), + x('x', 5), + Y('Y', 5), + y('y', 5), + Z('Z', 5), + z('z', 5), + NUM_1('1', 5), + NUM_2('2', 5), + NUM_3('3', 5), + NUM_4('4', 5), + NUM_5('5', 5), + NUM_6('6', 5), + NUM_7('7', 5), + NUM_8('8', 5), + NUM_9('9', 5), + NUM_0('0', 5), + EXCLAMATION_POINT('!', 1), + AT_SYMBOL('@', 6), + NUM_SIGN('#', 5), + DOLLAR_SIGN('$', 5), + PERCENT('%', 5), + UP_ARROW('^', 5), + AMPERSAND('&', 5), + ASTERISK('*', 5), + LEFT_PARENTHESIS('(', 4), + RIGHT_PERENTHESIS(')', 4), + MINUS('-', 5), + UNDERSCORE('_', 5), + PLUS_SIGN('+', 5), + EQUALS_SIGN('=', 5), + LEFT_CURL_BRACE('{', 4), + RIGHT_CURL_BRACE('}', 4), + LEFT_BRACKET('[', 3), + RIGHT_BRACKET(']', 3), + COLON(':', 1), + SEMI_COLON(';', 1), + DOUBLE_QUOTE('"', 3), + SINGLE_QUOTE('\'', 1), + LEFT_ARROW('<', 4), + RIGHT_ARROW('>', 4), + QUESTION_MARK('?', 5), + SLASH('/', 5), + BACK_SLASH('\\', 5), + LINE('|', 1), + TILDE('~', 5), + TICK('`', 2), + PERIOD('.', 1), + COMMA(',', 1), + SPACE(' ', 3), + DEFAULT('a', 4); + + private char character; + private int length; + + DefaultFontInfo(char character, int length) { + this.character = character; + this.length = length; + } + + public static DefaultFontInfo getDefaultFontInfo(char c) { + for (DefaultFontInfo dFI : DefaultFontInfo.values()) { + if (dFI.getCharacter() == c) return dFI; + } + return DefaultFontInfo.DEFAULT; + } + + public char getCharacter() { + return this.character; + } + + public int getLength() { + return this.length; + } + + public int getBoldLength() { + if (this == DefaultFontInfo.SPACE) return this.getLength(); + return this.length + 1; + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/other/GameProfileUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/other/GameProfileUtil.java new file mode 100644 index 0000000..d5bbafa --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/other/GameProfileUtil.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.utils.other; + +import com.mojang.authlib.GameProfile; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.security.AccessController; +import java.security.PrivilegedAction; + +/** + * @since 10/9/2017 + */ +public class GameProfileUtil { + + public static GameProfile clone(GameProfile gameProfile) { + GameProfile newProfile = new GameProfile(gameProfile.getId(), gameProfile.getName()); + newProfile.getProperties().putAll(gameProfile.getProperties()); + return newProfile; + } + + public static GameProfile setName(GameProfile gameProfile, String newName) { + try { + Field modifiersField = Field.class.getDeclaredField("modifiers"); + + // wrapping setAccessible + AccessController.doPrivileged((PrivilegedAction) () -> { + modifiersField.setAccessible(true); + return null; + }); + + Field nameField = GameProfile.class.getDeclaredField("name"); + modifiersField.setInt(nameField, nameField.getModifiers() & ~Modifier.FINAL); + nameField.setAccessible(true); + nameField.set(gameProfile, newName); + } catch (Exception e) { + e.printStackTrace(); + } + return gameProfile; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/other/UUIDFetcher.java b/LandCore/src/main/java/me/devkevin/landcore/utils/other/UUIDFetcher.java new file mode 100644 index 0000000..376b54e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/other/UUIDFetcher.java @@ -0,0 +1,105 @@ +package me.devkevin.landcore.utils.other; + +/** + * @since 10/9/2017 + */ + +import com.google.common.collect.ImmutableList; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.ByteBuffer; +import java.util.*; +import java.util.concurrent.Callable; + +/** + * Interface to Mojang's API to fetch player UUIDs from player names. + *

+ * Thanks to evilmidget38: http://forums.bukkit.org/threads/player-name-uuid-fetcher.250926/ + */ +public class UUIDFetcher implements Callable> { + private static final double PROFILES_PER_REQUEST = 100; + private static final String PROFILE_URL = "https://api.mojang.com/profiles/minecraft"; + private final JSONParser jsonParser = new JSONParser(); + private final List names; + private final boolean rateLimiting; + + public UUIDFetcher(List names, boolean rateLimiting) { + this.names = ImmutableList.copyOf(names); + this.rateLimiting = rateLimiting; + } + + public UUIDFetcher(List names) { + this(names, true); + } + + private static void writeBody(HttpURLConnection connection, String body) throws Exception { + OutputStream stream = connection.getOutputStream(); + stream.write(body.getBytes()); + stream.flush(); + stream.close(); + } + + private static HttpURLConnection createConnection() throws Exception { + URL url = new URL(PROFILE_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setUseCaches(false); + connection.setDoInput(true); + connection.setDoOutput(true); + return connection; + } + + private static UUID getUUID(String id) { + return UUID.fromString(id.substring(0, 8) + "-" + id.substring(8, 12) + "-" + id.substring(12, 16) + "-" + id.substring(16, 20) + "-" + id.substring(20, 32)); + } + + public static byte[] toBytes(UUID uuid) { + ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[16]); + byteBuffer.putLong(uuid.getMostSignificantBits()); + byteBuffer.putLong(uuid.getLeastSignificantBits()); + return byteBuffer.array(); + } + + public static UUID fromBytes(byte[] array) { + if (array.length != 16) { + throw new IllegalArgumentException("Illegal byte array length: " + array.length); + } + ByteBuffer byteBuffer = ByteBuffer.wrap(array); + long mostSignificant = byteBuffer.getLong(); + long leastSignificant = byteBuffer.getLong(); + return new UUID(mostSignificant, leastSignificant); + } + + public static UUID getUUIDOf(String name) throws Exception { + return new UUIDFetcher(Arrays.asList(name)).call().get(name); + } + + public Map call() throws Exception { + Map uuidMap = new HashMap<>(); + int requests = (int) Math.ceil(names.size() / PROFILES_PER_REQUEST); + for (int i = 0; i < requests; i++) { + HttpURLConnection connection = createConnection(); + String body = JSONArray.toJSONString(names.subList(i * 100, Math.min((i + 1) * 100, names.size()))); + writeBody(connection, body); + JSONArray array = (JSONArray) jsonParser.parse(new InputStreamReader(connection.getInputStream())); + for (Object profile : array) { + JSONObject jsonProfile = (JSONObject) profile; + String id = (String) jsonProfile.get("id"); + String name = (String) jsonProfile.get("name"); + UUID uuid = UUIDFetcher.getUUID(id); + uuidMap.put(name, uuid); + } + if (rateLimiting && i != requests - 1) { + Thread.sleep(100L); + } + } + return uuidMap; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketAdapter.java b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketAdapter.java new file mode 100644 index 0000000..5195aab --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketAdapter.java @@ -0,0 +1,15 @@ +package me.devkevin.landcore.utils.packet; + +import net.minecraft.server.v1_8_R3.Packet; +import org.bukkit.entity.Player; + +@FunctionalInterface +public interface PacketAdapter> { + + Packet handle(Player player, E packet); + + default Packet handleAny(Player player, Packet packet) { + return handle(player, (E) packet); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketInterceptor.java b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketInterceptor.java new file mode 100644 index 0000000..8023d18 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketInterceptor.java @@ -0,0 +1,72 @@ +package me.devkevin.landcore.utils.packet; + + +import io.netty.channel.Channel; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import me.devkevin.landcore.utils.FieldBoundReflections; +import net.minecraft.server.v1_8_R3.NetworkManager; +import net.minecraft.server.v1_8_R3.Packet; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class PacketInterceptor extends ChannelDuplexHandler { + + private static final FieldBoundReflections CHANNEL_FIELD = FieldBoundReflections.access(NetworkManager.class, "m"); + + private static final String HANDLER_BASE_NAME = "packet_handler"; + private static final String HANDLER_NAME = "packet_handler_core"; + private final Player player; + private final Channel channel; + private final PacketListener packetListener; + + public PacketInterceptor(Player player, PacketListener packetListener) { + this.player = player; + this.packetListener = packetListener; + + NetworkManager networkManager = ((CraftPlayer) player).getHandle().playerConnection.networkManager; + this.channel = ((CraftPlayer) player).getHandle().playerConnection.networkManager.channel; + } + + public void attach() { + if (!isAttached()) { + channel.pipeline().addBefore(HANDLER_BASE_NAME, HANDLER_NAME, this); + } + } + + public void detach() { + if (!isAttached()) { + return; + } + + channel.pipeline().remove(HANDLER_NAME); + } + + + public boolean isAttached() { + return channel.pipeline().get(HANDLER_NAME) != null; + } + + @Override + public void write(ChannelHandlerContext channelHandlerContext, Object object, ChannelPromise channelPromise) throws Exception { + + if (object != null && object instanceof Packet) { + object = packetListener.handleOutgoingPacket(player, (Packet) object); + } + + super.write(channelHandlerContext, object, channelPromise); + } + + + @Override + public void channelRead(ChannelHandlerContext channelHandlerContext, Object object) throws Exception { + + if (object != null && object instanceof Packet) { + object = packetListener.handleIncomingPacket(player, (Packet) object); + } + + super.channelRead(channelHandlerContext, object); + } + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketListener.java b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketListener.java new file mode 100644 index 0000000..7980b7e --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PacketListener.java @@ -0,0 +1,47 @@ +package me.devkevin.landcore.utils.packet; + +import com.google.common.collect.HashMultimap; +import com.google.common.collect.Multimap; +import net.minecraft.server.v1_8_R3.Packet; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public class PacketListener { + + private final Multimap, PacketAdapter> registeredAdapters; + + public PacketListener() { + this.registeredAdapters = HashMultimap.create(); + } + + public Packet handleOutgoingPacket(Player player, Packet packet) { + return invokeAdapters(player, packet); + } + + + public Packet handleIncomingPacket(Player player, Packet packet) { + return invokeAdapters(player, packet); + } + + private Packet invokeAdapters(Player player, Packet packet) { + if (packet == null) { + return null; + } + + Collection> adapters = registeredAdapters.get(packet.getClass()); + + for (PacketAdapter adapter : adapters) { + packet = adapter.handleAny(player, packet); + } + + return packet; + } + + public > void registerAdapter(Class classType, PacketAdapter handler) { + this.registeredAdapters.put(classType, handler); + } + + +} + diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PlayerInfoPacketMod.java b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PlayerInfoPacketMod.java new file mode 100644 index 0000000..8ce8bbf --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/PlayerInfoPacketMod.java @@ -0,0 +1,40 @@ +package me.devkevin.landcore.utils.packet; + +import com.mojang.authlib.GameProfile; +import net.minecraft.server.v1_8_R3.PacketPlayOutPlayerInfo; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; + +public class PlayerInfoPacketMod { + + private PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(); + + public PlayerInfoPacketMod(String name, int ping, GameProfile profile, int action) { + this.setField("username", name); + this.setField("ping", ping); + this.setField("action", action); + this.setField("player", profile); + } + + public void setField(String field, Object value) { + + try { + + final Field fieldObject = this.packet.getClass().getDeclaredField(field); + + fieldObject.setAccessible(true); + fieldObject.set(this.packet, value); + } catch (Exception ex) { + ex.printStackTrace(); + } + + } + + public void sendToPlayer(Player player) { + ((CraftPlayer)player).getHandle().playerConnection.sendPacket(this.packet); + } + + +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/packet/ScoreboardTeamPacketMod.java b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/ScoreboardTeamPacketMod.java new file mode 100644 index 0000000..cd8c328 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/packet/ScoreboardTeamPacketMod.java @@ -0,0 +1,89 @@ +package me.devkevin.landcore.utils.packet; + +import net.minecraft.server.v1_8_R3.PacketPlayOutScoreboardTeam; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Collection; + +public final class ScoreboardTeamPacketMod { + + private PacketPlayOutScoreboardTeam packet; + + private static String fieldPrefix = "c"; + private static String fieldSuffix = "d"; + private static String fieldPlayers = "g"; + private static String fieldTeamName = "a"; + private static String fieldParamInt = "f"; + private static String fieldPackOption = "i"; + private static String fieldDisplayName = "b"; + + public ScoreboardTeamPacketMod(String name,String prefix,String suffix,Collection players,int paramInt) { + + this.packet = new PacketPlayOutScoreboardTeam(); + + this.setField(fieldTeamName, name); + this.setField(fieldParamInt, paramInt); + + if (paramInt == 0 || paramInt == 2) { + this.setField(fieldDisplayName, name); + this.setField(fieldPrefix, prefix); + this.setField(fieldSuffix, suffix); + this.setField(fieldPackOption,1); + } + + if (paramInt == 0) { + this.addAll(players); + } + + } + + public ScoreboardTeamPacketMod(String name, Collection players, int paramInt) { + + this.packet = new PacketPlayOutScoreboardTeam(); + + if (players == null) { + players = new ArrayList(); + } + + this.setField(fieldTeamName, name); + this.setField(fieldParamInt, paramInt); + + this.addAll(players); + } + + public void sendToPlayer(Player bukkitPlayer) { + ((CraftPlayer) bukkitPlayer).getHandle().playerConnection.sendPacket(this.packet); + } + + public void setField(String field, Object value) { + + try { + + final Field fieldObject = this.packet.getClass().getDeclaredField(field); + + fieldObject.setAccessible(true); + fieldObject.set(this.packet, value); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + private void addAll(Collection col) { + + try { + + final Field fieldObject = this.packet.getClass().getDeclaredField(fieldPlayers); + + fieldObject.setAccessible(true); + ((Collection) fieldObject.get(this.packet)).addAll(col); + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/structure/Cuboid.java b/LandCore/src/main/java/me/devkevin/landcore/utils/structure/Cuboid.java new file mode 100644 index 0000000..8976dfe --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/structure/Cuboid.java @@ -0,0 +1,509 @@ +package me.devkevin.landcore.utils.structure; + +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.craftbukkit.v1_8_R3.block.CraftBlock; + +import java.util.*; + +/** + * Represents a cuboid region from one location to another. + * + * @skidder Coords + */ +public class Cuboid implements Iterable, Cloneable, ConfigurationSerializable { + private final String worldName; + private final int x1, y1, z1; + private final int x2, y2, z2; + + public Cuboid(Location locationA, Location locationB) { + if (!locationA.getWorld().equals(locationB.getWorld())) { + throw new IllegalArgumentException("Locations must be in the same world"); + } + + this.worldName = locationA.getWorld().getName(); + this.x1 = Math.min(locationA.getBlockX(), locationB.getBlockX()); + this.y1 = Math.min(locationA.getBlockY(), locationB.getBlockY()); + this.z1 = Math.min(locationA.getBlockZ(), locationB.getBlockZ()); + this.x2 = Math.max(locationA.getBlockX(), locationB.getBlockX()); + this.y2 = Math.max(locationA.getBlockY(), locationB.getBlockY()); + this.z2 = Math.max(locationA.getBlockZ(), locationB.getBlockZ()); + } + + public Cuboid(Location location) { + this(location, location); + } + + public Cuboid(Cuboid other) { + this(other.worldName, other.x1, other.y1, other.z1, other.x2, other.y2, other.z2); + } + + public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = world.getName(); + this.x1 = Math.min(x1, x2); + this.x2 = Math.max(x1, x2); + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + + private Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = worldName; + this.x1 = Math.min(x1, x2); + this.x2 = Math.max(x1, x2); + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + + public Cuboid(Map map) { + this.worldName = (String) map.get("worldName"); + this.x1 = (Integer) map.get("x1"); + this.x2 = (Integer) map.get("x2"); + this.y1 = (Integer) map.get("y1"); + this.y2 = (Integer) map.get("y2"); + this.z1 = (Integer) map.get("z1"); + this.z2 = (Integer) map.get("z2"); + } + + @Override + public Map serialize() { + Map map = new HashMap<>(); + + map.put("worldName", this.worldName); + map.put("x1", this.x1); + map.put("y1", this.y1); + map.put("z1", this.z1); + map.put("x2", this.x2); + map.put("y2", this.y2); + map.put("z2", this.z2); + + return map; + } + + public Location getLowerNorthEast() { + return new Location(this.getWorld(), this.x1, this.y1, this.z1); + } + + public Location getUpperSouthWest() { + return new Location(this.getWorld(), this.x2, this.y2, this.z2); + } + + public List getBlocks() { + Iterator blockIterator = this.iterator(); + List copy = new ArrayList<>(); + + while (blockIterator.hasNext()) { + copy.add(blockIterator.next()); + } + + return copy; + } + + public Location getCenter() { + int x1 = this.getUpperX() + 1; + int y1 = this.getUpperY() + 1; + int z1 = this.getUpperZ() + 1; + + return new Location( + this.getWorld(), + this.getLowerX() + (x1 - this.getLowerX()) / 2.0, + this.getLowerY() + (y1 - this.getLowerY()) / 2.0, + this.getLowerZ() + (z1 - this.getLowerZ()) / 2.0 + ); + } + + public void place(Location location) { + place(location, false); + } + + @SuppressWarnings("deprecation") + public void place(Location location, boolean skipAir) { + World world = getWorld(); + Location center = getCenter(); + int diffX = location.getBlockX() - center.getBlockX(); + int diffZ = location.getBlockZ() - center.getBlockZ(); + + for (Block block : this) { + Material blockType = block.getType(); + + if (skipAir && blockType == Material.AIR) { + continue; + } + + Block placed = world.getBlockAt(block.getX() + diffX, block.getY(), block.getZ() + diffZ); + + ((CraftBlock) placed).setTypeIdAndData(blockType.getId(), block.getData(), false); + } + } + + public World getWorld() { + World world = Bukkit.getWorld(this.worldName); + + if (world == null) { + throw new IllegalStateException("World '" + this.worldName + "' is not loaded"); + } + + return world; + } + + public int getSizeX() { + return (this.x2 - this.x1) + 1; + } + + public int getSizeY() { + return (this.y2 - this.y1) + 1; + } + + public int getSizeZ() { + return (this.z2 - this.z1) + 1; + } + + public int getLowerX() { + return this.x1; + } + + public int getLowerY() { + return this.y1; + } + + public int getLowerZ() { + return this.z1; + } + + public int getUpperX() { + return this.x2; + } + + public int getUpperY() { + return this.y2; + } + + public int getUpperZ() { + return this.z2; + } + + public Block[] getCorners() { + Block[] cornerBlocks = new Block[8]; + World world = this.getWorld(); + + cornerBlocks[0] = world.getBlockAt(this.x1, this.y1, this.z1); + cornerBlocks[1] = world.getBlockAt(this.x1, this.y1, this.z2); + cornerBlocks[2] = world.getBlockAt(this.x1, this.y2, this.z1); + cornerBlocks[3] = world.getBlockAt(this.x1, this.y2, this.z2); + cornerBlocks[4] = world.getBlockAt(this.x2, this.y1, this.z1); + cornerBlocks[5] = world.getBlockAt(this.x2, this.y1, this.z2); + cornerBlocks[6] = world.getBlockAt(this.x2, this.y2, this.z1); + cornerBlocks[7] = world.getBlockAt(this.x2, this.y2, this.z2); + + return cornerBlocks; + } + + public Cuboid expand(CuboidDirection direction, int amount) { + switch (direction) { + case NORTH: + return new Cuboid(this.worldName, this.x1 - amount, this.y1, this.z1, this.x2, this.y2, this.z2); + case SOUTH: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2 + amount, this.y2, this.z2); + case EAST: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1 - amount, this.x2, this.y2, this.z2); + case WEST: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z2 + amount); + case DOWN: + return new Cuboid(this.worldName, this.x1, this.y1 - amount, this.z1, this.x2, this.y2, this.z2); + case UP: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2 + amount, this.z2); + default: + throw new IllegalArgumentException("Invalid direction: " + direction); + } + } + + public Cuboid shift(CuboidDirection direction, int amount) { + return expand(direction, amount).expand(direction.opposite(), -amount); + } + + public Cuboid outset(CuboidDirection direction, int amount) { + Cuboid cuboid; + + switch (direction) { + case HORIZONTAL: + cuboid = expand(CuboidDirection.NORTH, amount) + .expand(CuboidDirection.SOUTH, amount) + .expand(CuboidDirection.EAST, amount) + .expand(CuboidDirection.WEST, amount); + break; + case VERTICAL: + cuboid = expand(CuboidDirection.DOWN, amount) + .expand(CuboidDirection.UP, amount); + break; + case BOTH: + cuboid = outset(CuboidDirection.HORIZONTAL, amount) + .outset(CuboidDirection.VERTICAL, amount); + break; + default: + throw new IllegalArgumentException("Invalid direction " + direction); + } + + return cuboid; + } + + public Cuboid inset(CuboidDirection dir, int amount) { + return this.outset(dir, -amount); + } + + public boolean contains(int x, int y, int z) { + return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2 && z >= this.z1 && z <= this.z2; + } + + public boolean contains(Block block) { + return this.contains(block.getLocation()); + } + + public boolean contains(Location location) { + if (!this.worldName.equals(location.getWorld().getName())) { + return false; + } + + return this.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + public int getVolume() { + return this.getSizeX() * this.getSizeY() * this.getSizeZ(); + } + + public byte getAverageLightLevel() { + long total = 0; + int count = 0; + + for (Block block : this) { + if (block.isEmpty()) { + total += block.getLightLevel(); + ++count; + } + } + + return count > 0 ? (byte) (total / count) : 0; + } + + public Cuboid contract() { + return this.contract(CuboidDirection.DOWN) + .contract(CuboidDirection.SOUTH) + .contract(CuboidDirection.EAST) + .contract(CuboidDirection.UP) + .contract(CuboidDirection.NORTH) + .contract(CuboidDirection.WEST); + } + + public Cuboid contract(CuboidDirection direction) { + Cuboid face = getFace(direction.opposite()); + + switch (direction) { + case DOWN: + while (face.containsOnly(Material.AIR) && face.getLowerY() > this.getLowerY()) { + face = face.shift(CuboidDirection.DOWN, 1); + } + + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, face.getUpperY(), this.z2); + case UP: + while (face.containsOnly(Material.AIR) && face.getUpperY() < this.getUpperY()) { + face = face.shift(CuboidDirection.UP, 1); + } + + return new Cuboid(this.worldName, this.x1, face.getLowerY(), this.z1, this.x2, this.y2, this.z2); + case NORTH: + while (face.containsOnly(Material.AIR) && face.getLowerX() > this.getLowerX()) { + face = face.shift(CuboidDirection.NORTH, 1); + } + + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, face.getUpperX(), this.y2, this.z2); + case SOUTH: + while (face.containsOnly(Material.AIR) && face.getUpperX() < this.getUpperX()) { + face = face.shift(CuboidDirection.SOUTH, 1); + } + + return new Cuboid(this.worldName, face.getLowerX(), this.y1, this.z1, this.x2, this.y2, this.z2); + case EAST: + while (face.containsOnly(Material.AIR) && face.getLowerZ() > this.getLowerZ()) { + face = face.shift(CuboidDirection.EAST, 1); + } + + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, face.getUpperZ()); + case WEST: + while (face.containsOnly(Material.AIR) && face.getUpperZ() < this.getUpperZ()) { + face = face.shift(CuboidDirection.WEST, 1); + } + + return new Cuboid(this.worldName, this.x1, this.y1, face.getLowerZ(), this.x2, this.y2, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + direction); + } + } + + public Cuboid getFace(CuboidDirection direction) { + switch (direction) { + case DOWN: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y1, this.z2); + case UP: + return new Cuboid(this.worldName, this.x1, this.y2, this.z1, this.x2, this.y2, this.z2); + case NORTH: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x1, this.y2, this.z2); + case SOUTH: + return new Cuboid(this.worldName, this.x2, this.y1, this.z1, this.x2, this.y2, this.z2); + case EAST: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z1); + case WEST: + return new Cuboid(this.worldName, this.x1, this.y1, this.z2, this.x2, this.y2, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + direction); + } + } + + public boolean containsOnly(Material type) { + for (Block block : this) { + if (block.getType() != type) { + return false; + } + } + + return true; + } + + public Cuboid getBoundingCuboid(Cuboid other) { + if (other == null) { + return this; + } + + int xMin = Math.min(this.getLowerX(), other.getLowerX()); + int yMin = Math.min(this.getLowerY(), other.getLowerY()); + int zMin = Math.min(this.getLowerZ(), other.getLowerZ()); + int xMax = Math.max(this.getUpperX(), other.getUpperX()); + int yMax = Math.max(this.getUpperY(), other.getUpperY()); + int zMax = Math.max(this.getUpperZ(), other.getUpperZ()); + + return new Cuboid(this.worldName, xMin, yMin, zMin, xMax, yMax, zMax); + } + + public Block getRelativeBlock(int x, int y, int z) { + return this.getWorld().getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + public Block getRelativeBlock(World world, int x, int y, int z) { + return world.getBlockAt(this.x1 + x, y1 + y, this.z1 + z); + } + + public List getChunks() { + List chunks = new ArrayList<>(); + World world = this.getWorld(); + + int x1 = this.getLowerX() & ~0xf; + int x2 = this.getUpperX() & ~0xf; + int z1 = this.getLowerZ() & ~0xf; + int z2 = this.getUpperZ() & ~0xf; + + for (int x = x1; x <= x2; x += 16) { + for (int z = z1; z <= z2; z += 16) { + chunks.add(world.getChunkAt(x >> 4, z >> 4)); + } + } + + return chunks; + } + + @Override + public Iterator iterator() { + return new CuboidIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + @Override + public Cuboid clone() { + return new Cuboid(this); + } + + @Override + public String toString() { + return "Cuboid{" + + "worldName='" + worldName + '\'' + + ", x1=" + x1 + + ", y1=" + y1 + + ", z1=" + z1 + + ", x2=" + x2 + + ", y2=" + y2 + + ", z2=" + z2 + + '}'; + } + + public enum CuboidDirection { + NORTH, EAST, SOUTH, WEST, UP, DOWN, HORIZONTAL, VERTICAL, BOTH, UNKNOWN; + + public CuboidDirection opposite() { + switch (this) { + case NORTH: + return SOUTH; + case EAST: + return WEST; + case SOUTH: + return NORTH; + case WEST: + return EAST; + case HORIZONTAL: + return VERTICAL; + case VERTICAL: + return HORIZONTAL; + case UP: + return DOWN; + case DOWN: + return UP; + case BOTH: + return BOTH; + default: + return UNKNOWN; + } + } + } + + public class CuboidIterator implements Iterator { + private World world; + private int baseX, baseY, baseZ; + private int x, y, z; + private int sizeX, sizeY, sizeZ; + + public CuboidIterator(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.world = world; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.x = this.y = this.z = 0; + } + + @Override + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + @Override + public Block next() { + Block block = this.world.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + + if (++x >= this.sizeX) { + this.x = 0; + + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + + return block; + } + + @Override + public void remove() { + } + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/time/TimeFormatUtils.java b/LandCore/src/main/java/me/devkevin/landcore/utils/time/TimeFormatUtils.java new file mode 100644 index 0000000..7f55592 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/time/TimeFormatUtils.java @@ -0,0 +1,254 @@ +package me.devkevin.landcore.utils.time; + +import java.text.DecimalFormat; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TimeFormatUtils { + + private static DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); + + public static String getDetailedTime(long millis) { + long seconds = millis / 1000L; + + if (seconds <= 0) { + return "0 seconds"; + } + + long minutes = seconds / 60; + seconds = seconds % 60; + long hours = minutes / 60; + minutes = minutes % 60; + long day = hours / 24; + hours = hours % 24; + long years = day / 365; + day = day % 365; + + StringBuilder time = new StringBuilder(); + + if (years != 0) { + time.append(years).append(years == 1 ? "y" : "y").append(day == 0 ? "" : ","); + } + + if (day != 0) { + time.append(day).append(day == 1 ? "d" : "d").append(hours == 0 ? "" : ","); + } + + if (hours != 0) { + time.append(hours).append(hours == 1 ? "h" : "h").append(minutes == 0 ? "" : ","); + } + + if (minutes != 0) { + time.append(minutes).append(minutes == 1 ? "m" : "m").append(seconds == 0 ? "" : ","); + } + + if (seconds != 0) { + time.append(seconds).append(seconds == 1 ? "s" : "s"); + } + + return time.toString().trim(); + } + + public static String getSimpleDetailedTime(long millis) { + long seconds = millis / 1000L; + + if (seconds <= 0) { + return "0 seconds"; + } + + long minutes = seconds / 60; + seconds = seconds % 60; + long hours = minutes / 60; + minutes = minutes % 60; + long day = hours / 24; + hours = hours % 24; + long years = day / 365; + day = day % 365; + + StringBuilder time = new StringBuilder(); + + if (years != 0) { + time.append(years).append(years == 1 ? "y" : "y"); + } + + else if (day != 0) { + time.append(day).append(day == 1 ? "d" : "d"); + } + + else if (hours != 0) { + time.append(hours).append(hours == 1 ? "h" : "h"); + } + + else if (minutes != 0) { + time.append(minutes).append(minutes == 1 ? "m" : "m"); + } + + else if (seconds != 0) { + time.append(seconds).append(seconds == 1 ? "s" : "s"); + } + + return time.toString().trim(); + } + + public static String getMoreDetailedTime(long millis) { + long seconds = millis / 1000L; + + if (seconds <= 0) { + return "0 seconds"; + } + + long minutes = seconds / 60; + seconds = seconds % 60; + long hours = minutes / 60; + minutes = minutes % 60; + long day = hours / 24; + hours = hours % 24; + long years = day / 365; + day = day % 365; + + StringBuilder time = new StringBuilder(); + + if (years != 0) { + time.append(years).append(years == 1 ? " year" : " years").append(day == 0 ? "" : ","); + } + + if (day != 0) { + time.append(day).append(day == 1 ? " day" : " days").append(hours == 0 ? "" : ","); + } + + if (hours != 0) { + time.append(hours).append(hours == 1 ? " hour" : " hours").append(minutes == 0 ? "" : ","); + } + + if (minutes != 0) { + time.append(minutes).append(minutes == 1 ? " minute" : " minutes").append(seconds == 0 ? "" : ","); + } + + if (seconds != 0) { + time.append(seconds).append(seconds == 1 ? " second" : " seconds"); + } + + return time.toString().trim(); + } + + public static String getMoreDetailedTime(long millis, boolean milis) { + long seconds = millis / 1000L; + + if (seconds <= 0) { + return "0 seconds"; + } + + long minutes = seconds / 60; + if (!milis) { + seconds = seconds % 60; + } + long hours = minutes / 60; + minutes = minutes % 60; + long day = hours / 24; + hours = hours % 24; + long years = day / 365; + day = day % 365; + + StringBuilder time = new StringBuilder(); + + if (years != 0) { + time.append(years).append(years == 1 ? " year" : " years").append(day == 0 ? "" : ","); + } + + if (day != 0) { + time.append(day).append(day == 1 ? " day" : " days").append(hours == 0 ? "" : ","); + } + + if (hours != 0) { + time.append(hours).append(hours == 1 ? " hour" : " hours").append(minutes == 0 ? "" : ","); + } + + if (minutes != 0) { + time.append(minutes).append(minutes == 1 ? " minute" : " minutes").append(seconds == 0 ? "" : ","); + } + + if (!milis) { + time.append(seconds).append(seconds == 1 ? " second" : " seconds"); + } else { + time.append(DECIMAL_FORMAT.format(millis / 1000D)).append(seconds <= 1 ? " second" : " seconds"); + } + + return time.toString().trim(); + } + + public static String formatTime(int timer) { + int hours = timer / 3600; + int secondsLeft = timer - hours * 3600; + int minutes = secondsLeft / 60; + int seconds = secondsLeft - minutes * 60; + + String formattedTime = ""; + + if (hours > 0) { + if (hours < 10) + formattedTime += "0"; + formattedTime += hours + ":"; + } + + if (minutes < 10) + formattedTime += "0"; + formattedTime += minutes + ":"; + + if (seconds < 10) + formattedTime += "0"; + formattedTime += seconds; + + return formattedTime; + } + + 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; + continue; + } + case "m": { + totalTime += value * 60L; + found = true; + continue; + } + case "h": { + totalTime += value * 60L * 60L; + found = true; + continue; + } + case "d": { + totalTime += value * 60L * 60L * 24L; + found = true; + continue; + } + case "w": { + totalTime += value * 60L * 60L * 24L * 7L; + found = true; + continue; + } + case "mo": { + totalTime += value * 60L * 60L * 24L * 30L; + found = true; + continue; + } + case "y": { + totalTime += value * 60L * 60L * 24L * 365L; + found = true; + } + } + } + + return found ? (totalTime * 1000L) + 1000L : -1; + } +} \ No newline at end of file diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/time/TimeUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/time/TimeUtil.java new file mode 100644 index 0000000..98b6d04 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/time/TimeUtil.java @@ -0,0 +1,203 @@ +package me.devkevin.landcore.utils.time; + +import lombok.experimental.UtilityClass; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +@UtilityClass +public class TimeUtil { + 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 String dateToString(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + return calendar.getTime().toString(); + } + + 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 String getDetailedTime(long millis) { + long seconds = millis / 1000L; + + if (seconds <= 0) { + return "0 seconds"; + } + + long minutes = seconds / 60; + seconds = seconds % 60; + long hours = minutes / 60; + minutes = minutes % 60; + long day = hours / 24; + hours = hours % 24; + long years = day / 365; + day = day % 365; + + StringBuilder time = new StringBuilder(); + + if (years != 0) { + time.append(years).append(years == 1 ? "y" : "y").append(day == 0 ? "" : ","); + } + + if (day != 0) { + time.append(day).append(day == 1 ? "d" : "d").append(hours == 0 ? "" : ","); + } + + if (hours != 0) { + time.append(hours).append(hours == 1 ? "h" : "h").append(minutes == 0 ? "" : ","); + } + + if (minutes != 0) { + time.append(minutes).append(minutes == 1 ? "m" : "m").append(seconds == 0 ? "" : ","); + } + + if (seconds != 0) { + time.append(seconds).append(seconds == 1 ? "s" : "s"); + } + + return time.toString().trim(); + } + + public static String formatTimeMillis(long millis) { + long seconds = millis / 1000L; + + if (seconds <= 0) { + return "0 seconds"; + } + + long minutes = seconds / 60; + seconds = seconds % 60; + long hours = minutes / 60; + minutes = minutes % 60; + long day = hours / 24; + hours = hours % 24; + long years = day / 365; + day = day % 365; + + StringBuilder time = new StringBuilder(); + + if (years != 0) { + time.append(years).append(years == 1 ? " year " : " years "); + } + + if (day != 0) { + time.append(day).append(day == 1 ? " day " : " days "); + } + + if (hours != 0) { + time.append(hours).append(hours == 1 ? " hour " : " hours "); + } + + if (minutes != 0) { + time.append(minutes).append(minutes == 1 ? " minute " : " minutes "); + } + + if (seconds != 0) { + time.append(seconds).append(seconds == 1 ? " second " : " seconds "); + } + + return time.toString().trim(); + } + + public static String formatTimeSeconds(long seconds) { + return formatTimeMillis(seconds * 1000); + } + + public static String formatTimeMillisToClock(long millis) { + return millis / 1000L <= 0 ? "0:00" : String.format("%01d:%02d", + TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), + TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))); + } + + public static String formatTimeSecondsToClock(long seconds) { + return formatTimeMillisToClock(seconds * 1000); + } + + 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; + continue; + } + case "m": { + totalTime += value * 60L; + found = true; + continue; + } + case "h": { + totalTime += value * 60L * 60L; + found = true; + continue; + } + case "d": { + totalTime += value * 60L * 60L * 24L; + found = true; + continue; + } + case "w": { + totalTime += value * 60L * 60L * 24L * 7L; + found = true; + continue; + } + case "mo": { + totalTime += value * 60L * 60L * 24L * 30L; + found = true; + continue; + } + case "y": { + totalTime += value * 60L * 60L * 24L * 365L; + found = true; + } + } + } + + return found ? (totalTime * 1000L) + 1000L : -1; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/timer/AbstractTimer.java b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/AbstractTimer.java new file mode 100644 index 0000000..a1ce700 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/AbstractTimer.java @@ -0,0 +1,33 @@ +package me.devkevin.landcore.utils.timer; + +import java.util.concurrent.TimeUnit; + +public abstract class AbstractTimer implements Timer { + private final long ms; + protected long expiry; + + protected AbstractTimer(TimeUnit unit, int amount) { + this.ms = unit.toMillis(amount); + } + + @Override + public boolean isActive() { + return isActive(true); + } + + @Override + public boolean isActive(boolean autoReset) { + boolean active = System.currentTimeMillis() < expiry; + + if (autoReset && !active) { + reset(); + } + + return active; + } + + @Override + public void reset() { + this.expiry = System.currentTimeMillis() + ms; + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/timer/Timer.java b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/Timer.java new file mode 100644 index 0000000..89c2e2b --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/Timer.java @@ -0,0 +1,11 @@ +package me.devkevin.landcore.utils.timer; + +public interface Timer { + boolean isActive(boolean autoReset); + + boolean isActive(); + + String formattedExpiration(); + + void reset(); +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/timer/impl/DoubleTimer.java b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/impl/DoubleTimer.java new file mode 100644 index 0000000..c33e28c --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/impl/DoubleTimer.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.utils.timer.impl; + +import me.devkevin.landcore.utils.timer.AbstractTimer; + +import java.util.concurrent.TimeUnit; + +public class DoubleTimer extends AbstractTimer { + public DoubleTimer(int seconds) { + super(TimeUnit.SECONDS, seconds); + } + + @Override + public String formattedExpiration() { + double seconds = (expiry - System.currentTimeMillis()) / 1000.0; + return String.format("%.1f seconds", seconds); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/timer/impl/IntegerTimer.java b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/impl/IntegerTimer.java new file mode 100644 index 0000000..2fe4010 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/timer/impl/IntegerTimer.java @@ -0,0 +1,17 @@ +package me.devkevin.landcore.utils.timer.impl; + +import me.devkevin.landcore.utils.time.TimeUtil; +import me.devkevin.landcore.utils.timer.AbstractTimer; + +import java.util.concurrent.TimeUnit; + +public class IntegerTimer extends AbstractTimer { + public IntegerTimer(TimeUnit unit, int amount) { + super(unit, amount); + } + + @Override + public String formattedExpiration() { + return TimeUtil.formatTimeMillis(expiry - System.currentTimeMillis()); + } +} diff --git a/LandCore/src/main/java/me/devkevin/landcore/utils/web/WebUtil.java b/LandCore/src/main/java/me/devkevin/landcore/utils/web/WebUtil.java new file mode 100644 index 0000000..dab6785 --- /dev/null +++ b/LandCore/src/main/java/me/devkevin/landcore/utils/web/WebUtil.java @@ -0,0 +1,43 @@ +package me.devkevin.landcore.utils.web; + +import me.devkevin.landcore.callback.WebCallback; +import lombok.experimental.UtilityClass; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.util.ArrayList; +import java.util.List; + +@UtilityClass +public class WebUtil { + public static void getResponse(JavaPlugin plugin, String url, WebCallback callback) { + plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(url).openStream()))) { + callback.callback(reader.readLine()); + } catch (Exception ex) { + ex.printStackTrace(); + } + }); + } + + public static List getLines(String link) { + List lines = new ArrayList<>(); + try { + URL url = new URL(link); + URLConnection urlConnection = url.openConnection(); + InputStream inputStream = urlConnection.getInputStream(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + String line = null; + while ((line = bufferedReader.readLine()) != null) { + lines.add(line); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + return lines; + } +} diff --git a/LandCore/src/main/resources/config.yml b/LandCore/src/main/resources/config.yml new file mode 100644 index 0000000..64d1965 --- /dev/null +++ b/LandCore/src/main/resources/config.yml @@ -0,0 +1,11 @@ +server_name: "server-name" +network_name: "SERVER_NAME" + +mongodb: + uri: mongodb://127.0.0.1:27017/land_core + +redis: + host: 127.0.0.1 + port: 6379 + timeout: 2000 + password: "53$pdu432423f" diff --git a/LandCore/src/main/resources/plugin.yml b/LandCore/src/main/resources/plugin.yml new file mode 100644 index 0000000..b7c88b5 --- /dev/null +++ b/LandCore/src/main/resources/plugin.yml @@ -0,0 +1,4 @@ +name: LandCore +version: ${version} +author: DevKevin +main: me.devkevin.landcore.LandCore diff --git a/LandCore/target/LandCore-1.3-SNAPSHOT.jar b/LandCore/target/LandCore-1.3-SNAPSHOT.jar new file mode 100644 index 0000000..a035ee1 Binary files /dev/null and b/LandCore/target/LandCore-1.3-SNAPSHOT.jar differ diff --git a/LandCore/target/classes/config.yml b/LandCore/target/classes/config.yml new file mode 100644 index 0000000..64d1965 --- /dev/null +++ b/LandCore/target/classes/config.yml @@ -0,0 +1,11 @@ +server_name: "server-name" +network_name: "SERVER_NAME" + +mongodb: + uri: mongodb://127.0.0.1:27017/land_core + +redis: + host: 127.0.0.1 + port: 6379 + timeout: 2000 + password: "53$pdu432423f" diff --git a/LandCore/target/classes/me/devkevin/landcore/LandCore.class b/LandCore/target/classes/me/devkevin/landcore/LandCore.class new file mode 100644 index 0000000..99d0bea Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/LandCore.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI$LandCoreListener.class b/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI$LandCoreListener.class new file mode 100644 index 0000000..deb8751 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI$LandCoreListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI$Language.class b/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI$Language.class new file mode 100644 index 0000000..d0f408a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI$Language.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI.class b/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI.class new file mode 100644 index 0000000..72e5c3e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/LandCoreAPI.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/callback/DocumentCallback.class b/LandCore/target/classes/me/devkevin/landcore/callback/DocumentCallback.class new file mode 100644 index 0000000..46ff4be Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/callback/DocumentCallback.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/callback/WebCallback.class b/LandCore/target/classes/me/devkevin/landcore/callback/WebCallback.class new file mode 100644 index 0000000..b77c6ed Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/callback/WebCallback.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/BaseCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/BaseCommand.class new file mode 100644 index 0000000..ddb7195 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/BaseCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/PlayerCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/PlayerCommand.class new file mode 100644 index 0000000..2db7f41 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/PlayerCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/ClearChatCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ClearChatCommand.class new file mode 100644 index 0000000..bc82cca Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ClearChatCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/EnchantCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/EnchantCommand.class new file mode 100644 index 0000000..c4b9b11 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/EnchantCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/FeedCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/FeedCommand.class new file mode 100644 index 0000000..27ea100 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/FeedCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/HealCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/HealCommand.class new file mode 100644 index 0000000..ff378f2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/HealCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/HelpOpCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/HelpOpCommand.class new file mode 100644 index 0000000..494e2d3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/HelpOpCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/IgnoreCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/IgnoreCommand.class new file mode 100644 index 0000000..56d8b0f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/IgnoreCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/ListCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ListCommand.class new file mode 100644 index 0000000..66cb1a1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ListCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/MessageCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/MessageCommand.class new file mode 100644 index 0000000..de8b793 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/MessageCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/PCoinsCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/PCoinsCommand.class new file mode 100644 index 0000000..890e562 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/PCoinsCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/PingCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/PingCommand.class new file mode 100644 index 0000000..4286955 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/PingCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/PlayTimeCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/PlayTimeCommand.class new file mode 100644 index 0000000..a76274a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/PlayTimeCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/ReplyCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ReplyCommand.class new file mode 100644 index 0000000..68e8f26 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ReplyCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/ReportCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ReportCommand.class new file mode 100644 index 0000000..a12fb0b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/ReportCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/StoreCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/StoreCommand.class new file mode 100644 index 0000000..20b7650 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/StoreCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/TeleportPositionCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/TeleportPositionCommand.class new file mode 100644 index 0000000..108d368 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/TeleportPositionCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/AltsCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/AltsCommand.class new file mode 100644 index 0000000..ef15459 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/AltsCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/BroadcastCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/BroadcastCommand.class new file mode 100644 index 0000000..9e8416c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/BroadcastCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/BuildServerCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/BuildServerCommand.class new file mode 100644 index 0000000..f0212f0 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/BuildServerCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/FreezeCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/FreezeCommand.class new file mode 100644 index 0000000..d5b8980 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/FreezeCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/GameModeCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/GameModeCommand.class new file mode 100644 index 0000000..8c339ca Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/GameModeCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/MisplaceCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/MisplaceCommand.class new file mode 100644 index 0000000..17f8c80 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/MisplaceCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/MuteChatCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/MuteChatCommand.class new file mode 100644 index 0000000..ed8e24b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/MuteChatCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/ShutdownCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/ShutdownCommand.class new file mode 100644 index 0000000..5b4d868 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/ShutdownCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/SlowChatCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/SlowChatCommand.class new file mode 100644 index 0000000..925830d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/SlowChatCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/StaffChatCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/StaffChatCommand.class new file mode 100644 index 0000000..97dc9e7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/StaffChatCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/TeleportCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/TeleportCommand.class new file mode 100644 index 0000000..3eeb894 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/TeleportCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/VanishCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/VanishCommand.class new file mode 100644 index 0000000..8ab6893 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/VanishCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/WhitelistCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/WhitelistCommand.class new file mode 100644 index 0000000..ef96754 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/WhitelistCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/permissions/DeletePermissionCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/permissions/DeletePermissionCommand.class new file mode 100644 index 0000000..5bdef93 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/permissions/DeletePermissionCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/permissions/SetPermissionCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/permissions/SetPermissionCommand.class new file mode 100644 index 0000000..5af85d9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/permissions/SetPermissionCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/BanCommand$1.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/BanCommand$1.class new file mode 100644 index 0000000..ef3cd3a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/BanCommand$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/BanCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/BanCommand.class new file mode 100644 index 0000000..31a9e7e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/BanCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/CheckCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/CheckCommand.class new file mode 100644 index 0000000..4636577 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/CheckCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/KickCommand$1.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/KickCommand$1.class new file mode 100644 index 0000000..361f6d7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/KickCommand$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/KickCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/KickCommand.class new file mode 100644 index 0000000..b56cb0a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/KickCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/MuteCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/MuteCommand.class new file mode 100644 index 0000000..b2e1376 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/MuteCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/UnbanCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/UnbanCommand.class new file mode 100644 index 0000000..a0e7fe5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/UnbanCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/UnmuteCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/UnmuteCommand.class new file mode 100644 index 0000000..292cfe6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/UnmuteCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/WarnCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/WarnCommand.class new file mode 100644 index 0000000..e6dd5d2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/staff/punish/WarnCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleGlobalChat.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleGlobalChat.class new file mode 100644 index 0000000..ea53246 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleGlobalChat.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleMessagesCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleMessagesCommand.class new file mode 100644 index 0000000..4c76aed Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleMessagesCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleSoundsCommand.class b/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleSoundsCommand.class new file mode 100644 index 0000000..ae22029 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/commands/impl/toggle/ToggleSoundsCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/commands/DisguiseCommand.class b/LandCore/target/classes/me/devkevin/landcore/disguise/commands/DisguiseCommand.class new file mode 100644 index 0000000..6da1953 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/commands/DisguiseCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/commands/UndisguiseCommand.class b/LandCore/target/classes/me/devkevin/landcore/disguise/commands/UndisguiseCommand.class new file mode 100644 index 0000000..5157ea9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/commands/UndisguiseCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/manager/DisguiseManager$NicknamePattern.class b/LandCore/target/classes/me/devkevin/landcore/disguise/manager/DisguiseManager$NicknamePattern.class new file mode 100644 index 0000000..85bb901 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/manager/DisguiseManager$NicknamePattern.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/manager/DisguiseManager.class b/LandCore/target/classes/me/devkevin/landcore/disguise/manager/DisguiseManager.class new file mode 100644 index 0000000..edf4f9a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/manager/DisguiseManager.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$1.class new file mode 100644 index 0000000..b05642b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$2.class new file mode 100644 index 0000000..4c7529b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$3.class new file mode 100644 index 0000000..f161b02 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$4.class new file mode 100644 index 0000000..9461152 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$5.class new file mode 100644 index 0000000..96f9363 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$6.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$6.class new file mode 100644 index 0000000..af489d6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu$6.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu.class b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu.class new file mode 100644 index 0000000..44674d6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/disguise/menu/DisguiseMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/BanEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/BanEvent.class new file mode 100644 index 0000000..6d654b9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/BanEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/BaseEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/BaseEvent.class new file mode 100644 index 0000000..bf65295 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/BaseEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/CoreEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/CoreEvent.class new file mode 100644 index 0000000..cb63ce4 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/CoreEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/CoreProfileEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/CoreProfileEvent.class new file mode 100644 index 0000000..82e9606 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/CoreProfileEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/PlayerFakeEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/PlayerFakeEvent.class new file mode 100644 index 0000000..ad9ae16 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/PlayerFakeEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/disguise/PreDisguiseEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/disguise/PreDisguiseEvent.class new file mode 100644 index 0000000..472752b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/disguise/PreDisguiseEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/disguise/UnDisguiseEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/disguise/UnDisguiseEvent.class new file mode 100644 index 0000000..902be90 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/disguise/UnDisguiseEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerFreezeEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerFreezeEvent.class new file mode 100644 index 0000000..f78fd7e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerFreezeEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerMessageEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerMessageEvent.class new file mode 100644 index 0000000..f1f4772 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerMessageEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerRankChangeEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerRankChangeEvent.class new file mode 100644 index 0000000..532d8f0 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/player/PlayerRankChangeEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/server/ServerShutdownCancelEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/server/ServerShutdownCancelEvent.class new file mode 100644 index 0000000..53df214 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/server/ServerShutdownCancelEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/event/server/ServerShutdownScheduleEvent.class b/LandCore/target/classes/me/devkevin/landcore/event/server/ServerShutdownScheduleEvent.class new file mode 100644 index 0000000..e02ceb5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/event/server/ServerShutdownScheduleEvent.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/Faction.class b/LandCore/target/classes/me/devkevin/landcore/faction/Faction.class new file mode 100644 index 0000000..f5757d6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/Faction.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/FactionHelpCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/FactionHelpCommand.class new file mode 100644 index 0000000..3f9ab64 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/FactionHelpCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionDemoteCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionDemoteCommand.class new file mode 100644 index 0000000..19889a3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionDemoteCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionInviteCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionInviteCommand.class new file mode 100644 index 0000000..e32659e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionInviteCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionKickCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionKickCommand.class new file mode 100644 index 0000000..ea7900f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionKickCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionPasswordCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionPasswordCommand.class new file mode 100644 index 0000000..8991968 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionPasswordCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionPromoteCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionPromoteCommand.class new file mode 100644 index 0000000..660192a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/captain/FactionPromoteCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/leader/FactionDescriptionCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/leader/FactionDescriptionCommand.class new file mode 100644 index 0000000..f33c661 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/leader/FactionDescriptionCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/leader/FactionDisbandCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/leader/FactionDisbandCommand.class new file mode 100644 index 0000000..698248f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/leader/FactionDisbandCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionAcceptCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionAcceptCommand.class new file mode 100644 index 0000000..554fd6f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionAcceptCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionChatCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionChatCommand.class new file mode 100644 index 0000000..c763947 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionChatCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionCreateCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionCreateCommand.class new file mode 100644 index 0000000..328976b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionCreateCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionInfoCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionInfoCommand.class new file mode 100644 index 0000000..8b7669a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionInfoCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionLeaveCommand.class b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionLeaveCommand.class new file mode 100644 index 0000000..fe1b135 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/commands/player/FactionLeaveCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/invite/FactionInvite.class b/LandCore/target/classes/me/devkevin/landcore/faction/invite/FactionInvite.class new file mode 100644 index 0000000..a4543fe Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/invite/FactionInvite.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/listener/FactionListener.class b/LandCore/target/classes/me/devkevin/landcore/faction/listener/FactionListener.class new file mode 100644 index 0000000..e4c095f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/listener/FactionListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/manager/FactionManager.class b/LandCore/target/classes/me/devkevin/landcore/faction/manager/FactionManager.class new file mode 100644 index 0000000..39255df Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/manager/FactionManager.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/member/FactionMember.class b/LandCore/target/classes/me/devkevin/landcore/faction/member/FactionMember.class new file mode 100644 index 0000000..f6378d2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/member/FactionMember.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/member/FactionMemberType.class b/LandCore/target/classes/me/devkevin/landcore/faction/member/FactionMemberType.class new file mode 100644 index 0000000..61f0b77 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/member/FactionMemberType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/faction/profile/FactionProfile.class b/LandCore/target/classes/me/devkevin/landcore/faction/profile/FactionProfile.class new file mode 100644 index 0000000..6138b69 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/faction/profile/FactionProfile.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory$1.class b/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory$1.class new file mode 100644 index 0000000..a595a8a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory$LocationData.class b/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory$LocationData.class new file mode 100644 index 0000000..f283603 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory$LocationData.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory.class b/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory.class new file mode 100644 index 0000000..88e37dc Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/CustomLocationTypeAdapterFactory.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory$1.class b/LandCore/target/classes/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory$1.class new file mode 100644 index 0000000..341eb2b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory.class b/LandCore/target/classes/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory.class new file mode 100644 index 0000000..ab1318b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/ItemStackTypeAdapterFactory.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/item/EnchantType.class b/LandCore/target/classes/me/devkevin/landcore/gson/item/EnchantType.class new file mode 100644 index 0000000..a919164 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/item/EnchantType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/item/ItemMetaType.class b/LandCore/target/classes/me/devkevin/landcore/gson/item/ItemMetaType.class new file mode 100644 index 0000000..18055fe Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/item/ItemMetaType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/item/ItemType.class b/LandCore/target/classes/me/devkevin/landcore/gson/item/ItemType.class new file mode 100644 index 0000000..905b5e3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/item/ItemType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/gson/item/PotionEffectType.class b/LandCore/target/classes/me/devkevin/landcore/gson/item/PotionEffectType.class new file mode 100644 index 0000000..fa4411a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/gson/item/PotionEffectType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/handler/PacketListener.class b/LandCore/target/classes/me/devkevin/landcore/handler/PacketListener.class new file mode 100644 index 0000000..4b2a4b2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/handler/PacketListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/inventory/menu/Menu.class b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/Menu.class new file mode 100644 index 0000000..962d853 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/Menu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/inventory/menu/action/Action.class b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/action/Action.class new file mode 100644 index 0000000..de33a1e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/action/Action.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/inventory/menu/impl/PerPlayerMenu.class b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/impl/PerPlayerMenu.class new file mode 100644 index 0000000..6946b32 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/impl/PerPlayerMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/inventory/menu/impl/ReportMenu.class b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/impl/ReportMenu.class new file mode 100644 index 0000000..57a7196 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/inventory/menu/impl/ReportMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/HelpCommandListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/HelpCommandListener.class new file mode 100644 index 0000000..0188f4d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/HelpCommandListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/InventoryListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/InventoryListener.class new file mode 100644 index 0000000..cf26d6f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/InventoryListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/MenuListeners.class b/LandCore/target/classes/me/devkevin/landcore/listeners/MenuListeners.class new file mode 100644 index 0000000..aab75af Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/MenuListeners.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/MessageListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/MessageListener.class new file mode 100644 index 0000000..a4067fb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/MessageListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerInteractListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerInteractListener.class new file mode 100644 index 0000000..d3f5acc Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerInteractListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerListener.class new file mode 100644 index 0000000..3b7d684 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerPacketListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerPacketListener.class new file mode 100644 index 0000000..8a3af9f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/PlayerPacketListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/FreezeListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/FreezeListener.class new file mode 100644 index 0000000..40142de Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/FreezeListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/FrozenDisconnectListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/FrozenDisconnectListener.class new file mode 100644 index 0000000..6ad7da7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/FrozenDisconnectListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/HelpopListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/HelpopListener.class new file mode 100644 index 0000000..bc9eb52 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/HelpopListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/RedisFactionListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/RedisFactionListener.class new file mode 100644 index 0000000..78e15ee Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/RedisFactionListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/RedisServerMonitorListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/RedisServerMonitorListener.class new file mode 100644 index 0000000..df7c9eb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/RedisServerMonitorListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/ReportListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/ReportListener.class new file mode 100644 index 0000000..a143aed Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/ReportListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/StaffChatListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/StaffChatListener.class new file mode 100644 index 0000000..216c6ea Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/StaffChatListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/listeners/redis/StaffStreamListener.class b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/StaffStreamListener.class new file mode 100644 index 0000000..f3b5ca8 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/listeners/redis/StaffStreamListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/managers/MenuManager.class b/LandCore/target/classes/me/devkevin/landcore/managers/MenuManager.class new file mode 100644 index 0000000..7a330aa Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/managers/MenuManager.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/managers/PlayerManager.class b/LandCore/target/classes/me/devkevin/landcore/managers/PlayerManager.class new file mode 100644 index 0000000..1f30ce5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/managers/PlayerManager.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/managers/ProfileManager.class b/LandCore/target/classes/me/devkevin/landcore/managers/ProfileManager.class new file mode 100644 index 0000000..ebeda75 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/managers/ProfileManager.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/managers/StaffManager.class b/LandCore/target/classes/me/devkevin/landcore/managers/StaffManager.class new file mode 100644 index 0000000..305355d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/managers/StaffManager.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/NameTagAdapter.class b/LandCore/target/classes/me/devkevin/landcore/nametag/NameTagAdapter.class new file mode 100644 index 0000000..6506305 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/NameTagAdapter.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagInfo.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagInfo.class new file mode 100644 index 0000000..d69e687 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagInfo.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagMethod.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagMethod.class new file mode 100644 index 0000000..c02fa63 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagMethod.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagThread.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagThread.class new file mode 100644 index 0000000..d8a10eb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagThread.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagUpdate.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagUpdate.class new file mode 100644 index 0000000..a991fd7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag$NametagUpdate.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag.class new file mode 100644 index 0000000..bacff88 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/InternalNametag.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagListener.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagListener.class new file mode 100644 index 0000000..38e686e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagProvider$DefaultNametagProvider.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagProvider$DefaultNametagProvider.class new file mode 100644 index 0000000..80a19a0 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagProvider$DefaultNametagProvider.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagProvider.class b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagProvider.class new file mode 100644 index 0000000..3af5d41 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/nametag/impl/NametagProvider.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$1.class b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$1.class new file mode 100644 index 0000000..7c955a2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$2.class b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$2.class new file mode 100644 index 0000000..6289338 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$3.class b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$3.class new file mode 100644 index 0000000..d0f4c03 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile.class b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile.class new file mode 100644 index 0000000..12b1d76 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/CoreProfile.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/color/ColorCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/color/ColorCommand.class new file mode 100644 index 0000000..7b52f7d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/color/ColorCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/color/SetColorCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/color/SetColorCommand.class new file mode 100644 index 0000000..b17fab5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/color/SetColorCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$1.class new file mode 100644 index 0000000..25a9398 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$2.class new file mode 100644 index 0000000..9d9812f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$3.class new file mode 100644 index 0000000..d096b97 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu.class new file mode 100644 index 0000000..77c4d6a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/color/menu/ColorMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/Grant.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/Grant.class new file mode 100644 index 0000000..64c5ccb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/Grant.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$1.class new file mode 100644 index 0000000..48d6d0d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$2.class new file mode 100644 index 0000000..fb3bd96 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$3.class new file mode 100644 index 0000000..744bb47 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$4.class new file mode 100644 index 0000000..e8f30c3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$5.class new file mode 100644 index 0000000..725a778 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu.class new file mode 100644 index 0000000..71ce45a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantConfirmMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$1.class new file mode 100644 index 0000000..481a6b3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$2.class new file mode 100644 index 0000000..ec9f0cd Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$3.class new file mode 100644 index 0000000..b87ba96 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$4.class new file mode 100644 index 0000000..0f34b21 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$5.class new file mode 100644 index 0000000..2943f14 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$6.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$6.class new file mode 100644 index 0000000..8fbc493 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$6.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$7.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$7.class new file mode 100644 index 0000000..ae2a512 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$7.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$8.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$8.class new file mode 100644 index 0000000..51ba9e1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$8.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$9.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$9.class new file mode 100644 index 0000000..eca2262 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu$9.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu.class new file mode 100644 index 0000000..b6a5265 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantDurationMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$1.class new file mode 100644 index 0000000..b3f84db Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$2.class new file mode 100644 index 0000000..aaba4f6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$3.class new file mode 100644 index 0000000..7520e4f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$4.class new file mode 100644 index 0000000..ae5cfe3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$5.class new file mode 100644 index 0000000..8142d5f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$6.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$6.class new file mode 100644 index 0000000..88fa4f7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$6.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$7.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$7.class new file mode 100644 index 0000000..7e5f748 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$7.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$8.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$8.class new file mode 100644 index 0000000..7ce5c6d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$8.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$9.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$9.class new file mode 100644 index 0000000..ac17cbf Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu$9.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu.class new file mode 100644 index 0000000..a4e489b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantReasonMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$1.class new file mode 100644 index 0000000..4ffb6c3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$2.class new file mode 100644 index 0000000..7e221e2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$3.class new file mode 100644 index 0000000..3e60992 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu.class new file mode 100644 index 0000000..e6622c1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantSelectMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu$1.class new file mode 100644 index 0000000..832d3b6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu$2.class new file mode 100644 index 0000000..7789ba7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu.class new file mode 100644 index 0000000..911560f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/GrantViewMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu$1.class new file mode 100644 index 0000000..cf0d12b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu$2.class new file mode 100644 index 0000000..8784ede Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu.class new file mode 100644 index 0000000..700ba74 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/menus/QuickGrantMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedure.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedure.class new file mode 100644 index 0000000..c3aada2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedure.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedureListener.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedureListener.class new file mode 100644 index 0000000..0b9f9f6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedureListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedureStage.class b/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedureStage.class new file mode 100644 index 0000000..4c52ec1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/grant/procedure/GrantProcedureStage.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/UserCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/info/UserCommand.class new file mode 100644 index 0000000..bc0bdbe Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/UserCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$1.class new file mode 100644 index 0000000..af73db8 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$2.class new file mode 100644 index 0000000..d000d67 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$3.class new file mode 100644 index 0000000..888cab4 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$4.class new file mode 100644 index 0000000..91b68cb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$5.class new file mode 100644 index 0000000..df9017c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu.class new file mode 100644 index 0000000..d9d1d18 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/info/menu/UserViewMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/Note.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/Note.class new file mode 100644 index 0000000..1173bb3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/Note.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NoteAddCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NoteAddCommand.class new file mode 100644 index 0000000..3cdbb2f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NoteAddCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NoteRemoveCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NoteRemoveCommand.class new file mode 100644 index 0000000..f5158b6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NoteRemoveCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NotesCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NotesCommand.class new file mode 100644 index 0000000..bc398f1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/commands/NotesCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/json/NoteJsonDeSerializer.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/json/NoteJsonDeSerializer.class new file mode 100644 index 0000000..b9a006d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/json/NoteJsonDeSerializer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/json/NoteJsonSerializer.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/json/NoteJsonSerializer.class new file mode 100644 index 0000000..67d44e5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/json/NoteJsonSerializer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/menu/NotesMenu$NoteButton.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/menu/NotesMenu$NoteButton.class new file mode 100644 index 0000000..b62173b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/menu/NotesMenu$NoteButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/notes/menu/NotesMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/notes/menu/NotesMenu.class new file mode 100644 index 0000000..8b4385c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/notes/menu/NotesMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/Rank.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/Rank.class new file mode 100644 index 0000000..9e545f1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/Rank.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/GrantCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/GrantCommand.class new file mode 100644 index 0000000..d2476c9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/GrantCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/GrantsCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/GrantsCommand.class new file mode 100644 index 0000000..0d5ed13 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/GrantsCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/QuickGrantCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/QuickGrantCommand.class new file mode 100644 index 0000000..0a8af7c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/QuickGrantCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/RankCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/RankCommand.class new file mode 100644 index 0000000..db99e3b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/RankCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/RankListCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/RankListCommand.class new file mode 100644 index 0000000..28a6783 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/commands/RankListCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$1.class new file mode 100644 index 0000000..6977281 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$2.class new file mode 100644 index 0000000..1cb5079 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$3.class new file mode 100644 index 0000000..1d007bf Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu.class new file mode 100644 index 0000000..a33f87e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/rank/menu/RankListMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/PrefixCommand.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/PrefixCommand.class new file mode 100644 index 0000000..236b55a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/PrefixCommand.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/CountriesPrefix.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/CountriesPrefix.class new file mode 100644 index 0000000..868c1e2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/CountriesPrefix.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/SymbolPrefix.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/SymbolPrefix.class new file mode 100644 index 0000000..40e6009 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/SymbolPrefix.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/TextSymbolPrefix.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/TextSymbolPrefix.class new file mode 100644 index 0000000..48b1b03 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/enums/TextSymbolPrefix.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$1.class new file mode 100644 index 0000000..31b647b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$10.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$10.class new file mode 100644 index 0000000..1536a97 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$10.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$11.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$11.class new file mode 100644 index 0000000..4931ec7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$11.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$12.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$12.class new file mode 100644 index 0000000..6745670 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$12.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$2.class new file mode 100644 index 0000000..6ddb43b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$3.class new file mode 100644 index 0000000..f46a4a7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$4.class new file mode 100644 index 0000000..4de239b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$5.class new file mode 100644 index 0000000..7bbe8a3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$6.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$6.class new file mode 100644 index 0000000..fb0ce3a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$6.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$7.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$7.class new file mode 100644 index 0000000..2d96f9d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$7.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$8.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$8.class new file mode 100644 index 0000000..bca1028 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$8.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$9.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$9.class new file mode 100644 index 0000000..0a8cde9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu$9.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu.class b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu.class new file mode 100644 index 0000000..cdef72a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/player/tags/menu/PrefixMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/Punishment.class b/LandCore/target/classes/me/devkevin/landcore/punishment/Punishment.class new file mode 100644 index 0000000..99ab981 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/Punishment.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentJsonDeserializer.class b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentJsonDeserializer.class new file mode 100644 index 0000000..ada5a72 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentJsonDeserializer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentJsonSerializer.class b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentJsonSerializer.class new file mode 100644 index 0000000..101b5ce Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentJsonSerializer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentType$PunishmentTypeData.class b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentType$PunishmentTypeData.class new file mode 100644 index 0000000..787e29a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentType$PunishmentTypeData.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentType.class b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentType.class new file mode 100644 index 0000000..f6fcba7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/PunishmentType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/listener/PunishmentListener$1.class b/LandCore/target/classes/me/devkevin/landcore/punishment/listener/PunishmentListener$1.class new file mode 100644 index 0000000..a962aac Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/listener/PunishmentListener$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/listener/PunishmentListener.class b/LandCore/target/classes/me/devkevin/landcore/punishment/listener/PunishmentListener.class new file mode 100644 index 0000000..a911377 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/listener/PunishmentListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsListMenu$PunishmentInfoButton.class b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsListMenu$PunishmentInfoButton.class new file mode 100644 index 0000000..6943928 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsListMenu$PunishmentInfoButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsListMenu.class b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsListMenu.class new file mode 100644 index 0000000..b014370 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsListMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsMenu$SelectPunishmentTypeButton.class b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsMenu$SelectPunishmentTypeButton.class new file mode 100644 index 0000000..539fb07 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsMenu$SelectPunishmentTypeButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsMenu.class b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsMenu.class new file mode 100644 index 0000000..96dda81 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/menu/PunishmentsMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedure.class b/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedure.class new file mode 100644 index 0000000..7969811 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedure.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedureStage.class b/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedureStage.class new file mode 100644 index 0000000..82d8002 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedureStage.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedureType.class b/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedureType.class new file mode 100644 index 0000000..65f1ce4 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/punishment/procedure/PunishmentProcedureType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/redis/RedisMessenger$1.class b/LandCore/target/classes/me/devkevin/landcore/redis/RedisMessenger$1.class new file mode 100644 index 0000000..bc5a839 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/redis/RedisMessenger$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/redis/RedisMessenger.class b/LandCore/target/classes/me/devkevin/landcore/redis/RedisMessenger.class new file mode 100644 index 0000000..8cf0e24 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/redis/RedisMessenger.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/redis/annotation/RedisHandler.class b/LandCore/target/classes/me/devkevin/landcore/redis/annotation/RedisHandler.class new file mode 100644 index 0000000..1caad6b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/redis/annotation/RedisHandler.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/redis/message/RedisMessage$1.class b/LandCore/target/classes/me/devkevin/landcore/redis/message/RedisMessage$1.class new file mode 100644 index 0000000..91c3402 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/redis/message/RedisMessage$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/redis/message/RedisMessage.class b/LandCore/target/classes/me/devkevin/landcore/redis/message/RedisMessage.class new file mode 100644 index 0000000..11279c7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/redis/message/RedisMessage.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/ServerSettings.class b/LandCore/target/classes/me/devkevin/landcore/server/ServerSettings.class new file mode 100644 index 0000000..f109b07 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/ServerSettings.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$1.class b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$1.class new file mode 100644 index 0000000..e7f0290 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$2.class b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$2.class new file mode 100644 index 0000000..ecb2e84 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$3.class b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$3.class new file mode 100644 index 0000000..5ebdb14 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode.class b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode.class new file mode 100644 index 0000000..bf4539f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/WhitelistMode.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/filter/Filter.class b/LandCore/target/classes/me/devkevin/landcore/server/filter/Filter.class new file mode 100644 index 0000000..2748fb4 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/filter/Filter.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/server/filter/NegativeWordPair.class b/LandCore/target/classes/me/devkevin/landcore/server/filter/NegativeWordPair.class new file mode 100644 index 0000000..bf86337 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/server/filter/NegativeWordPair.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/storage/database/MongoRequest.class b/LandCore/target/classes/me/devkevin/landcore/storage/database/MongoRequest.class new file mode 100644 index 0000000..d794246 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/storage/database/MongoRequest.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/storage/database/MongoStorage.class b/LandCore/target/classes/me/devkevin/landcore/storage/database/MongoStorage.class new file mode 100644 index 0000000..28afd0d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/storage/database/MongoStorage.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/storage/flatfile/Config.class b/LandCore/target/classes/me/devkevin/landcore/storage/flatfile/Config.class new file mode 100644 index 0000000..1eb33f9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/storage/flatfile/Config.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$1.class new file mode 100644 index 0000000..02343d8 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$2.class new file mode 100644 index 0000000..d4da781 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$3.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$3.class new file mode 100644 index 0000000..045fb9f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$3.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$4.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$4.class new file mode 100644 index 0000000..72c867c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$4.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$5.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$5.class new file mode 100644 index 0000000..bc2291b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$5.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$6.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$6.class new file mode 100644 index 0000000..ea3750e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$6.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$7.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$7.class new file mode 100644 index 0000000..a40bba3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu$7.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu.class b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu.class new file mode 100644 index 0000000..99293e6 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/store/StorePCoinMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/task/BroadcastTask.class b/LandCore/target/classes/me/devkevin/landcore/task/BroadcastTask.class new file mode 100644 index 0000000..6920d30 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/task/BroadcastTask.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/task/GrantDisguiseCheckTask.class b/LandCore/target/classes/me/devkevin/landcore/task/GrantDisguiseCheckTask.class new file mode 100644 index 0000000..bfc9673 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/task/GrantDisguiseCheckTask.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/task/ShutdownTask.class b/LandCore/target/classes/me/devkevin/landcore/task/ShutdownTask.class new file mode 100644 index 0000000..ef81337 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/task/ShutdownTask.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/BukkitReflection.class b/LandCore/target/classes/me/devkevin/landcore/utils/BukkitReflection.class new file mode 100644 index 0000000..e03c674 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/BukkitReflection.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/Clickable.class b/LandCore/target/classes/me/devkevin/landcore/utils/Clickable.class new file mode 100644 index 0000000..dc5bb08 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/Clickable.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/Duration.class b/LandCore/target/classes/me/devkevin/landcore/utils/Duration.class new file mode 100644 index 0000000..bbdde47 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/Duration.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/FieldBoundReflections.class b/LandCore/target/classes/me/devkevin/landcore/utils/FieldBoundReflections.class new file mode 100644 index 0000000..b71e4d1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/FieldBoundReflections.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/Menu.class b/LandCore/target/classes/me/devkevin/landcore/utils/Menu.class new file mode 100644 index 0000000..19e9f28 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/Menu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/NumberUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/NumberUtil.class new file mode 100644 index 0000000..64ae41a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/NumberUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/NumberUtils.class b/LandCore/target/classes/me/devkevin/landcore/utils/NumberUtils.class new file mode 100644 index 0000000..b231d1e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/NumberUtils.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/PlayerList.class b/LandCore/target/classes/me/devkevin/landcore/utils/PlayerList.class new file mode 100644 index 0000000..f3683c1 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/PlayerList.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/PlayerVersion.class b/LandCore/target/classes/me/devkevin/landcore/utils/PlayerVersion.class new file mode 100644 index 0000000..be80f43 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/PlayerVersion.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil$1.class new file mode 100644 index 0000000..332a93a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil$MojangProfile.class b/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil$MojangProfile.class new file mode 100644 index 0000000..f654bac Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil$MojangProfile.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil.class new file mode 100644 index 0000000..2d42198 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/ProfileUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/Protocol.class b/LandCore/target/classes/me/devkevin/landcore/utils/Protocol.class new file mode 100644 index 0000000..51c4285 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/Protocol.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils$DataType.class b/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils$DataType.class new file mode 100644 index 0000000..86d995a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils$DataType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils$PackageType.class b/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils$PackageType.class new file mode 100644 index 0000000..f9894af Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils$PackageType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils.class b/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils.class new file mode 100644 index 0000000..be041d7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/ReflectionUtils.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/SkinUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/SkinUtil.class new file mode 100644 index 0000000..760a1dd Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/SkinUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/StringUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/StringUtil.class new file mode 100644 index 0000000..9a2f37d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/StringUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/TaskUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/TaskUtil.class new file mode 100644 index 0000000..c9a813f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/TaskUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/UUIDUtils.class b/LandCore/target/classes/me/devkevin/landcore/utils/UUIDUtils.class new file mode 100644 index 0000000..7ba6769 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/UUIDUtils.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/Utilities.class b/LandCore/target/classes/me/devkevin/landcore/utils/Utilities.class new file mode 100644 index 0000000..5eb5684 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/Utilities.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/WoolUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/WoolUtil.class new file mode 100644 index 0000000..ca11026 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/WoolUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/http/Skin.class b/LandCore/target/classes/me/devkevin/landcore/utils/http/Skin.class new file mode 100644 index 0000000..31f4606 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/http/Skin.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$1.class new file mode 100644 index 0000000..a34dd0d Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$2.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$2.class new file mode 100644 index 0000000..589f78f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$ClickableItem.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$ClickableItem.class new file mode 100644 index 0000000..b92309a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$ClickableItem.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$Inventory2D$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$Inventory2D$1.class new file mode 100644 index 0000000..9179b18 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$Inventory2D$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$Inventory2D.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$Inventory2D.class new file mode 100644 index 0000000..d426feb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$Inventory2D.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$InventoryMakerHolder.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$InventoryMakerHolder.class new file mode 100644 index 0000000..738cc12 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker$InventoryMakerHolder.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker.class new file mode 100644 index 0000000..cfce922 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryMaker.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$1.class new file mode 100644 index 0000000..542ab30 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$2.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$2.class new file mode 100644 index 0000000..37348de Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$AbstractClickableItem.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$AbstractClickableItem.class new file mode 100644 index 0000000..200c6e3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$AbstractClickableItem.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$ClickableItem.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$ClickableItem.class new file mode 100644 index 0000000..f58df5c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$ClickableItem.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$EmptyClickableItem.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$EmptyClickableItem.class new file mode 100644 index 0000000..be09ff2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$EmptyClickableItem.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$Inventory2D.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$Inventory2D.class new file mode 100644 index 0000000..4fc7415 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$Inventory2D.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$InventoryUIHolder.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$InventoryUIHolder.class new file mode 100644 index 0000000..d71ca51 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI$InventoryUIHolder.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI.class new file mode 100644 index 0000000..c034f4c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUI.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUIHolder.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUIHolder.class new file mode 100644 index 0000000..0588831 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/InventoryUIHolder.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/UIListener.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/UIListener.class new file mode 100644 index 0000000..ed0da5f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/UIListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/inventory/UtilItem.class b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/UtilItem.class new file mode 100644 index 0000000..1f46603 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/inventory/UtilItem.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemBuilder.class b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemBuilder.class new file mode 100644 index 0000000..18eba3f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemBuilder.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemMaker.class b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemMaker.class new file mode 100644 index 0000000..384d6d9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemMaker.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$1.class new file mode 100644 index 0000000..575cf46 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$ItemEnchant.class b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$ItemEnchant.class new file mode 100644 index 0000000..9948649 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$ItemEnchant.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$ReloreType.class b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$ReloreType.class new file mode 100644 index 0000000..a6c4fe5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil$ReloreType.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil.class new file mode 100644 index 0000000..9802d84 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/item/ItemUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonChain.class b/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonChain.class new file mode 100644 index 0000000..6fb5931 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonChain.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonDeserializer.class b/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonDeserializer.class new file mode 100644 index 0000000..61b0ddb Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonDeserializer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonSerializer.class b/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonSerializer.class new file mode 100644 index 0000000..88b93db Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/json/JsonSerializer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/location/CustomLocation.class b/LandCore/target/classes/me/devkevin/landcore/utils/location/CustomLocation.class new file mode 100644 index 0000000..3796933 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/location/CustomLocation.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/Button$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Button$1.class new file mode 100644 index 0000000..00bbc47 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Button$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/Button.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Button.class new file mode 100644 index 0000000..0c29c17 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Button.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/ButtonListener.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/ButtonListener.class new file mode 100644 index 0000000..9ef5c02 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/ButtonListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/ButtonSound.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/ButtonSound.class new file mode 100644 index 0000000..020ce97 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/ButtonSound.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu$1.class new file mode 100644 index 0000000..bb127ee Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu$2.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu$2.class new file mode 100644 index 0000000..e56ac27 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu.class new file mode 100644 index 0000000..a110b20 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/Menu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/MenuUpdateTask.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/MenuUpdateTask.class new file mode 100644 index 0000000..2d000ca Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/MenuUpdateTask.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/TypeCallback.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/TypeCallback.class new file mode 100644 index 0000000..00b5d2a Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/TypeCallback.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/BackButton.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/BackButton.class new file mode 100644 index 0000000..7ef112f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/BackButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/CloseButton.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/CloseButton.class new file mode 100644 index 0000000..3af9bf0 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/CloseButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/ConfirmationButton.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/ConfirmationButton.class new file mode 100644 index 0000000..0b63287 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/ConfirmationButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/DisplayButton.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/DisplayButton.class new file mode 100644 index 0000000..6808c24 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/DisplayButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/Glass.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/Glass.class new file mode 100644 index 0000000..8bb3bbd Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/buttons/Glass.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu$1.class new file mode 100644 index 0000000..5e49a04 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu$2.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu$2.class new file mode 100644 index 0000000..72ddd12 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu$2.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu.class new file mode 100644 index 0000000..c3d5fbe Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/menus/ConfirmMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/GlassFill.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/GlassFill.class new file mode 100644 index 0000000..d3c3fa3 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/GlassFill.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/JumpToPageButton.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/JumpToPageButton.class new file mode 100644 index 0000000..03a9d08 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/JumpToPageButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PageButton.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PageButton.class new file mode 100644 index 0000000..de6aee9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PageButton.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu$1.class new file mode 100644 index 0000000..1f8f1da Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu.class new file mode 100644 index 0000000..351d0be Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/PaginatedMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/ViewAllPagesMenu.class b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/ViewAllPagesMenu.class new file mode 100644 index 0000000..13cff4f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/menu/pagination/ViewAllPagesMenu.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/message/CC.class b/LandCore/target/classes/me/devkevin/landcore/utils/message/CC.class new file mode 100644 index 0000000..9d9ba43 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/message/CC.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/message/ClickableMessage$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/message/ClickableMessage$1.class new file mode 100644 index 0000000..4df044b Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/message/ClickableMessage$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/message/ClickableMessage.class b/LandCore/target/classes/me/devkevin/landcore/utils/message/ClickableMessage.class new file mode 100644 index 0000000..904886f Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/message/ClickableMessage.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/message/Messages$DefaultFontInfo.class b/LandCore/target/classes/me/devkevin/landcore/utils/message/Messages$DefaultFontInfo.class new file mode 100644 index 0000000..43e18a9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/message/Messages$DefaultFontInfo.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/message/Messages.class b/LandCore/target/classes/me/devkevin/landcore/utils/message/Messages.class new file mode 100644 index 0000000..9fcac6c Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/message/Messages.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/other/GameProfileUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/other/GameProfileUtil.class new file mode 100644 index 0000000..18039f9 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/other/GameProfileUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/other/UUIDFetcher.class b/LandCore/target/classes/me/devkevin/landcore/utils/other/UUIDFetcher.class new file mode 100644 index 0000000..5c91a81 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/other/UUIDFetcher.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketAdapter.class b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketAdapter.class new file mode 100644 index 0000000..e5ea81e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketAdapter.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketInterceptor.class b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketInterceptor.class new file mode 100644 index 0000000..58d3077 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketInterceptor.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketListener.class b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketListener.class new file mode 100644 index 0000000..53a9bfa Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PacketListener.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/packet/PlayerInfoPacketMod.class b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PlayerInfoPacketMod.class new file mode 100644 index 0000000..8de5dc5 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/packet/PlayerInfoPacketMod.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/packet/ScoreboardTeamPacketMod.class b/LandCore/target/classes/me/devkevin/landcore/utils/packet/ScoreboardTeamPacketMod.class new file mode 100644 index 0000000..05e1876 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/packet/ScoreboardTeamPacketMod.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$1.class b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$1.class new file mode 100644 index 0000000..1ed4cc2 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$1.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$CuboidDirection.class b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$CuboidDirection.class new file mode 100644 index 0000000..c9fca30 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$CuboidDirection.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$CuboidIterator.class b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$CuboidIterator.class new file mode 100644 index 0000000..67a4b80 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid$CuboidIterator.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid.class b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid.class new file mode 100644 index 0000000..c5c39a7 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/structure/Cuboid.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/time/TimeFormatUtils.class b/LandCore/target/classes/me/devkevin/landcore/utils/time/TimeFormatUtils.class new file mode 100644 index 0000000..1c30c66 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/time/TimeFormatUtils.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/time/TimeUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/time/TimeUtil.class new file mode 100644 index 0000000..363197e Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/time/TimeUtil.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/timer/AbstractTimer.class b/LandCore/target/classes/me/devkevin/landcore/utils/timer/AbstractTimer.class new file mode 100644 index 0000000..ccbe804 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/timer/AbstractTimer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/timer/Timer.class b/LandCore/target/classes/me/devkevin/landcore/utils/timer/Timer.class new file mode 100644 index 0000000..eb4a3f8 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/timer/Timer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/timer/impl/DoubleTimer.class b/LandCore/target/classes/me/devkevin/landcore/utils/timer/impl/DoubleTimer.class new file mode 100644 index 0000000..8b808bd Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/timer/impl/DoubleTimer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/timer/impl/IntegerTimer.class b/LandCore/target/classes/me/devkevin/landcore/utils/timer/impl/IntegerTimer.class new file mode 100644 index 0000000..40912b8 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/timer/impl/IntegerTimer.class differ diff --git a/LandCore/target/classes/me/devkevin/landcore/utils/web/WebUtil.class b/LandCore/target/classes/me/devkevin/landcore/utils/web/WebUtil.class new file mode 100644 index 0000000..0be6632 Binary files /dev/null and b/LandCore/target/classes/me/devkevin/landcore/utils/web/WebUtil.class differ diff --git a/LandCore/target/classes/plugin.yml b/LandCore/target/classes/plugin.yml new file mode 100644 index 0000000..2db7594 --- /dev/null +++ b/LandCore/target/classes/plugin.yml @@ -0,0 +1,4 @@ +name: LandCore +version: 1.3-SNAPSHOT +author: DevKevin +main: me.devkevin.landcore.LandCore diff --git a/LandCore/target/maven-archiver/pom.properties b/LandCore/target/maven-archiver/pom.properties new file mode 100644 index 0000000..a7c9f65 --- /dev/null +++ b/LandCore/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Thu May 04 14:03:38 BST 2023 +version=1.3-SNAPSHOT +groupId=me.devkevin.landcore +artifactId=LandCore diff --git a/LandCore/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/LandCore/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..a248381 --- /dev/null +++ b/LandCore/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,364 @@ +me\devkevin\landcore\player\CoreProfile.class +me\devkevin\landcore\player\grant\menus\GrantViewMenu.class +me\devkevin\landcore\server\filter\NegativeWordPair.class +me\devkevin\landcore\gson\CustomLocationTypeAdapterFactory.class +me\devkevin\landcore\nametag\impl\InternalNametag$NametagInfo.class +me\devkevin\landcore\disguise\menu\DisguiseMenu$1.class +me\devkevin\landcore\store\StorePCoinMenu$3.class +me\devkevin\landcore\disguise\commands\DisguiseCommand.class +me\devkevin\landcore\commands\impl\ClearChatCommand.class +me\devkevin\landcore\LandCore.class +me\devkevin\landcore\redis\annotation\RedisHandler.class +me\devkevin\landcore\commands\impl\HelpOpCommand.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$4.class +me\devkevin\landcore\player\tags\enums\TextSymbolPrefix.class +me\devkevin\landcore\utils\menu\buttons\ConfirmationButton.class +me\devkevin\landcore\utils\inventory\InventoryMaker$2.class +me\devkevin\landcore\faction\commands\captain\FactionKickCommand.class +me\devkevin\landcore\utils\PlayerVersion.class +me\devkevin\landcore\utils\NumberUtil.class +me\devkevin\landcore\player\grant\Grant.class +me\devkevin\landcore\commands\impl\PlayTimeCommand.class +me\devkevin\landcore\utils\menu\buttons\DisplayButton.class +me\devkevin\landcore\player\CoreProfile$1.class +me\devkevin\landcore\utils\BukkitReflection.class +me\devkevin\landcore\punishment\menu\PunishmentsListMenu.class +me\devkevin\landcore\utils\time\TimeUtil.class +me\devkevin\landcore\player\notes\commands\NoteRemoveCommand.class +me\devkevin\landcore\task\ShutdownTask.class +me\devkevin\landcore\utils\menu\Button.class +me\devkevin\landcore\player\info\UserCommand.class +me\devkevin\landcore\server\WhitelistMode$1.class +me\devkevin\landcore\commands\BaseCommand.class +me\devkevin\landcore\commands\impl\staff\StaffChatCommand.class +me\devkevin\landcore\commands\PlayerCommand.class +me\devkevin\landcore\disguise\menu\DisguiseMenu$6.class +me\devkevin\landcore\inventory\menu\impl\PerPlayerMenu.class +me\devkevin\landcore\redis\RedisMessenger$1.class +me\devkevin\landcore\storage\flatfile\Config.class +me\devkevin\landcore\listeners\redis\HelpopListener.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$9.class +me\devkevin\landcore\utils\message\ClickableMessage$1.class +me\devkevin\landcore\player\notes\commands\NoteAddCommand.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$3.class +me\devkevin\landcore\callback\DocumentCallback.class +me\devkevin\landcore\commands\impl\toggle\ToggleMessagesCommand.class +me\devkevin\landcore\faction\listener\FactionListener.class +me\devkevin\landcore\nametag\impl\NametagProvider$DefaultNametagProvider.class +me\devkevin\landcore\player\grant\menus\GrantSelectMenu$3.class +me\devkevin\landcore\utils\ReflectionUtils$PackageType.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$1.class +me\devkevin\landcore\player\grant\menus\QuickGrantMenu$2.class +me\devkevin\landcore\utils\item\ItemUtil.class +me\devkevin\landcore\utils\menu\buttons\Glass.class +me\devkevin\landcore\inventory\menu\Menu.class +me\devkevin\landcore\utils\inventory\InventoryMaker$ClickableItem.class +me\devkevin\landcore\faction\commands\leader\FactionDescriptionCommand.class +me\devkevin\landcore\player\color\menu\ColorMenu$1.class +me\devkevin\landcore\utils\inventory\InventoryUI$1.class +me\devkevin\landcore\utils\FieldBoundReflections.class +me\devkevin\landcore\commands\impl\staff\SlowChatCommand.class +me\devkevin\landcore\utils\inventory\InventoryUI$EmptyClickableItem.class +me\devkevin\landcore\utils\menu\ButtonSound.class +me\devkevin\landcore\utils\menu\buttons\CloseButton.class +me\devkevin\landcore\utils\menu\pagination\PageButton.class +me\devkevin\landcore\commands\impl\staff\punish\BanCommand.class +me\devkevin\landcore\utils\menu\pagination\PaginatedMenu.class +me\devkevin\landcore\commands\impl\toggle\ToggleGlobalChat.class +me\devkevin\landcore\punishment\procedure\PunishmentProcedureType.class +me\devkevin\landcore\store\StorePCoinMenu.class +me\devkevin\landcore\utils\timer\impl\DoubleTimer.class +me\devkevin\landcore\callback\WebCallback.class +me\devkevin\landcore\event\disguise\UnDisguiseEvent.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$4.class +me\devkevin\landcore\punishment\menu\PunishmentsListMenu$PunishmentInfoButton.class +me\devkevin\landcore\disguise\menu\DisguiseMenu$2.class +me\devkevin\landcore\player\rank\menu\RankListMenu$3.class +me\devkevin\landcore\commands\impl\staff\WhitelistCommand.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$9.class +me\devkevin\landcore\commands\impl\staff\punish\WarnCommand.class +me\devkevin\landcore\commands\impl\staff\ShutdownCommand.class +me\devkevin\landcore\listeners\PlayerListener.class +me\devkevin\landcore\punishment\PunishmentJsonDeserializer.class +me\devkevin\landcore\utils\inventory\InventoryMaker$1.class +me\devkevin\landcore\disguise\menu\DisguiseMenu.class +me\devkevin\landcore\server\ServerSettings.class +me\devkevin\landcore\commands\impl\staff\MuteChatCommand.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$3.class +me\devkevin\landcore\utils\StringUtil.class +me\devkevin\landcore\event\server\ServerShutdownScheduleEvent.class +me\devkevin\landcore\utils\packet\ScoreboardTeamPacketMod.class +me\devkevin\landcore\commands\impl\staff\GameModeCommand.class +me\devkevin\landcore\player\rank\menu\RankListMenu.class +me\devkevin\landcore\nametag\impl\InternalNametag$NametagUpdate.class +me\devkevin\landcore\utils\inventory\InventoryUI$ClickableItem.class +me\devkevin\landcore\utils\inventory\InventoryMaker$Inventory2D.class +me\devkevin\landcore\inventory\menu\impl\ReportMenu.class +me\devkevin\landcore\server\WhitelistMode$2.class +me\devkevin\landcore\player\notes\json\NoteJsonSerializer.class +me\devkevin\landcore\gson\item\PotionEffectType.class +me\devkevin\landcore\faction\Faction.class +me\devkevin\landcore\utils\inventory\InventoryMaker$InventoryMakerHolder.class +me\devkevin\landcore\player\rank\menu\RankListMenu$2.class +me\devkevin\landcore\utils\Menu.class +me\devkevin\landcore\utils\time\TimeFormatUtils.class +me\devkevin\landcore\commands\impl\toggle\ToggleSoundsCommand.class +me\devkevin\landcore\commands\impl\staff\punish\MuteCommand.class +me\devkevin\landcore\utils\ReflectionUtils.class +me\devkevin\landcore\player\grant\menus\GrantSelectMenu$2.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$5.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$7.class +me\devkevin\landcore\commands\impl\HealCommand.class +me\devkevin\landcore\listeners\HelpCommandListener.class +me\devkevin\landcore\listeners\redis\FrozenDisconnectListener.class +me\devkevin\landcore\redis\RedisMessenger.class +me\devkevin\landcore\player\grant\menus\QuickGrantMenu$1.class +me\devkevin\landcore\nametag\impl\InternalNametag$NametagThread.class +me\devkevin\landcore\utils\inventory\InventoryUI$InventoryUIHolder.class +me\devkevin\landcore\disguise\commands\UndisguiseCommand.class +me\devkevin\landcore\punishment\menu\PunishmentsMenu.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$8.class +me\devkevin\landcore\listeners\redis\RedisServerMonitorListener.class +me\devkevin\landcore\utils\inventory\UIListener.class +me\devkevin\landcore\utils\inventory\InventoryUI$2.class +me\devkevin\landcore\managers\StaffManager.class +me\devkevin\landcore\commands\impl\staff\FreezeCommand.class +me\devkevin\landcore\event\disguise\PreDisguiseEvent.class +me\devkevin\landcore\utils\menu\Menu$1.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu.class +me\devkevin\landcore\store\StorePCoinMenu$7.class +me\devkevin\landcore\nametag\impl\NametagListener.class +me\devkevin\landcore\commands\impl\ListCommand.class +me\devkevin\landcore\listeners\PlayerInteractListener.class +me\devkevin\landcore\utils\item\ItemMaker.class +me\devkevin\landcore\utils\TaskUtil.class +me\devkevin\landcore\utils\web\WebUtil.class +me\devkevin\landcore\player\grant\menus\QuickGrantMenu.class +me\devkevin\landcore\player\notes\Note.class +me\devkevin\landcore\faction\member\FactionMemberType.class +me\devkevin\landcore\task\GrantDisguiseCheckTask.class +me\devkevin\landcore\punishment\PunishmentType.class +me\devkevin\landcore\commands\impl\MessageCommand.class +me\devkevin\landcore\utils\packet\PacketInterceptor.class +me\devkevin\landcore\utils\packet\PlayerInfoPacketMod.class +me\devkevin\landcore\utils\location\CustomLocation.class +me\devkevin\landcore\utils\timer\Timer.class +me\devkevin\landcore\event\BanEvent.class +me\devkevin\landcore\event\player\PlayerFreezeEvent.class +me\devkevin\landcore\event\player\PlayerMessageEvent.class +me\devkevin\landcore\utils\UUIDUtils.class +me\devkevin\landcore\utils\timer\AbstractTimer.class +me\devkevin\landcore\faction\member\FactionMember.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$7.class +me\devkevin\landcore\punishment\listener\PunishmentListener.class +me\devkevin\landcore\punishment\procedure\PunishmentProcedure.class +me\devkevin\landcore\utils\inventory\InventoryUI.class +me\devkevin\landcore\utils\menu\Menu$2.class +me\devkevin\landcore\player\tags\enums\CountriesPrefix.class +me\devkevin\landcore\player\rank\Rank.class +me\devkevin\landcore\commands\impl\ReportCommand.class +me\devkevin\landcore\player\notes\commands\NotesCommand.class +me\devkevin\landcore\commands\impl\staff\punish\UnmuteCommand.class +me\devkevin\landcore\gson\ItemStackTypeAdapterFactory$1.class +me\devkevin\landcore\punishment\menu\PunishmentsMenu$SelectPunishmentTypeButton.class +me\devkevin\landcore\server\WhitelistMode$3.class +me\devkevin\landcore\utils\menu\pagination\ViewAllPagesMenu.class +me\devkevin\landcore\utils\packet\PacketAdapter.class +me\devkevin\landcore\handler\PacketListener.class +me\devkevin\landcore\player\notes\menu\NotesMenu.class +me\devkevin\landcore\utils\menu\TypeCallback.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$8.class +me\devkevin\landcore\storage\database\MongoRequest.class +me\devkevin\landcore\disguise\manager\DisguiseManager.class +me\devkevin\landcore\player\grant\menus\GrantSelectMenu.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$6.class +me\devkevin\landcore\disguise\menu\DisguiseMenu$5.class +me\devkevin\landcore\event\CoreProfileEvent.class +me\devkevin\landcore\faction\invite\FactionInvite.class +me\devkevin\landcore\faction\commands\player\FactionCreateCommand.class +me\devkevin\landcore\faction\commands\player\FactionInfoCommand.class +me\devkevin\landcore\punishment\listener\PunishmentListener$1.class +me\devkevin\landcore\event\player\PlayerRankChangeEvent.class +me\devkevin\landcore\utils\Clickable.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$1.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$9.class +me\devkevin\landcore\redis\message\RedisMessage.class +me\devkevin\landcore\utils\item\ItemBuilder.class +me\devkevin\landcore\LandCoreAPI$Language.class +me\devkevin\landcore\utils\menu\MenuUpdateTask.class +me\devkevin\landcore\faction\commands\player\FactionLeaveCommand.class +me\devkevin\landcore\punishment\PunishmentType$PunishmentTypeData.class +me\devkevin\landcore\commands\impl\staff\TeleportCommand.class +me\devkevin\landcore\listeners\MessageListener.class +me\devkevin\landcore\utils\inventory\UtilItem.class +me\devkevin\landcore\commands\impl\staff\punish\KickCommand.class +me\devkevin\landcore\commands\impl\staff\punish\CheckCommand.class +me\devkevin\landcore\LandCoreAPI.class +me\devkevin\landcore\player\color\menu\ColorMenu$3.class +me\devkevin\landcore\store\StorePCoinMenu$6.class +me\devkevin\landcore\utils\menu\buttons\BackButton.class +me\devkevin\landcore\disguise\menu\DisguiseMenu$4.class +me\devkevin\landcore\listeners\redis\FreezeListener.class +me\devkevin\landcore\player\color\menu\ColorMenu.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$7.class +me\devkevin\landcore\gson\item\EnchantType.class +me\devkevin\landcore\player\rank\menu\RankListMenu$1.class +me\devkevin\landcore\server\filter\Filter.class +me\devkevin\landcore\player\rank\commands\QuickGrantCommand.class +me\devkevin\landcore\utils\other\UUIDFetcher.class +me\devkevin\landcore\utils\json\JsonDeserializer.class +me\devkevin\landcore\utils\menu\pagination\PaginatedMenu$1.class +me\devkevin\landcore\faction\commands\player\FactionChatCommand.class +me\devkevin\landcore\utils\WoolUtil.class +me\devkevin\landcore\listeners\PlayerPacketListener.class +me\devkevin\landcore\utils\inventory\InventoryUI$Inventory2D.class +me\devkevin\landcore\managers\MenuManager.class +me\devkevin\landcore\player\grant\menus\GrantViewMenu$1.class +me\devkevin\landcore\utils\menu\menus\ConfirmMenu.class +me\devkevin\landcore\utils\packet\PacketListener.class +me\devkevin\landcore\player\rank\commands\GrantCommand.class +me\devkevin\landcore\utils\item\ItemUtil$1.class +me\devkevin\landcore\utils\item\ItemUtil$ItemEnchant.class +me\devkevin\landcore\commands\impl\ReplyCommand.class +me\devkevin\landcore\utils\NumberUtils.class +me\devkevin\landcore\nametag\NameTagAdapter.class +me\devkevin\landcore\utils\menu\menus\ConfirmMenu$2.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$6.class +me\devkevin\landcore\utils\menu\pagination\JumpToPageButton.class +me\devkevin\landcore\disguise\menu\DisguiseMenu$3.class +me\devkevin\landcore\nametag\impl\NametagProvider.class +me\devkevin\landcore\player\grant\menus\GrantConfirmMenu$1.class +me\devkevin\landcore\store\StorePCoinMenu$5.class +me\devkevin\landcore\utils\ProfileUtil$MojangProfile.class +me\devkevin\landcore\commands\impl\staff\permissions\DeletePermissionCommand.class +me\devkevin\landcore\commands\impl\staff\permissions\SetPermissionCommand.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$5.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$4.class +me\devkevin\landcore\player\info\menu\UserViewMenu.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu.class +me\devkevin\landcore\player\grant\menus\GrantConfirmMenu.class +me\devkevin\landcore\punishment\procedure\PunishmentProcedureStage.class +me\devkevin\landcore\player\grant\menus\GrantSelectMenu$1.class +me\devkevin\landcore\nametag\impl\InternalNametag$NametagMethod.class +me\devkevin\landcore\commands\impl\EnchantCommand.class +me\devkevin\landcore\event\PlayerFakeEvent.class +me\devkevin\landcore\utils\inventory\InventoryUI$AbstractClickableItem.class +me\devkevin\landcore\faction\profile\FactionProfile.class +me\devkevin\landcore\punishment\PunishmentJsonSerializer.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$2.class +me\devkevin\landcore\commands\impl\staff\BroadcastCommand.class +me\devkevin\landcore\faction\commands\captain\FactionDemoteCommand.class +me\devkevin\landcore\utils\inventory\InventoryMaker$Inventory2D$1.class +me\devkevin\landcore\listeners\redis\ReportListener.class +me\devkevin\landcore\commands\impl\staff\AltsCommand.class +me\devkevin\landcore\gson\CustomLocationTypeAdapterFactory$1.class +me\devkevin\landcore\player\notes\menu\NotesMenu$NoteButton.class +me\devkevin\landcore\faction\commands\captain\FactionPasswordCommand.class +me\devkevin\landcore\listeners\InventoryListener.class +me\devkevin\landcore\commands\impl\PCoinsCommand.class +me\devkevin\landcore\utils\menu\Button$1.class +me\devkevin\landcore\player\tags\PrefixCommand.class +me\devkevin\landcore\gson\item\ItemType.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$3.class +me\devkevin\landcore\utils\timer\impl\IntegerTimer.class +me\devkevin\landcore\player\info\menu\UserViewMenu$1.class +me\devkevin\landcore\managers\PlayerManager.class +me\devkevin\landcore\disguise\manager\DisguiseManager$NicknamePattern.class +me\devkevin\landcore\faction\commands\captain\FactionPromoteCommand.class +me\devkevin\landcore\utils\ProfileUtil.class +me\devkevin\landcore\redis\message\RedisMessage$1.class +me\devkevin\landcore\player\tags\menu\PrefixMenu.class +me\devkevin\landcore\utils\inventory\InventoryMaker.class +me\devkevin\landcore\player\color\menu\ColorMenu$2.class +me\devkevin\landcore\utils\message\ClickableMessage.class +me\devkevin\landcore\listeners\redis\StaffStreamListener.class +me\devkevin\landcore\utils\menu\Menu.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$8.class +me\devkevin\landcore\inventory\menu\action\Action.class +me\devkevin\landcore\player\grant\menus\GrantViewMenu$2.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$10.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$2.class +me\devkevin\landcore\utils\SkinUtil.class +me\devkevin\landcore\utils\Duration.class +me\devkevin\landcore\nametag\impl\InternalNametag.class +me\devkevin\landcore\player\rank\commands\RankListCommand.class +me\devkevin\landcore\gson\CustomLocationTypeAdapterFactory$LocationData.class +me\devkevin\landcore\commands\impl\FeedCommand.class +me\devkevin\landcore\utils\inventory\InventoryUIHolder.class +me\devkevin\landcore\listeners\redis\RedisFactionListener.class +me\devkevin\landcore\utils\Protocol.class +me\devkevin\landcore\utils\json\JsonSerializer.class +me\devkevin\landcore\player\info\menu\UserViewMenu$5.class +me\devkevin\landcore\server\WhitelistMode.class +me\devkevin\landcore\utils\other\GameProfileUtil.class +me\devkevin\landcore\faction\commands\FactionHelpCommand.class +me\devkevin\landcore\commands\impl\staff\MisplaceCommand.class +me\devkevin\landcore\player\grant\menus\GrantConfirmMenu$2.class +me\devkevin\landcore\store\StorePCoinMenu$4.class +me\devkevin\landcore\commands\impl\staff\punish\BanCommand$1.class +me\devkevin\landcore\utils\message\Messages$DefaultFontInfo.class +me\devkevin\landcore\utils\http\Skin.class +me\devkevin\landcore\player\grant\procedure\GrantProcedure.class +me\devkevin\landcore\player\info\menu\UserViewMenu$2.class +me\devkevin\landcore\utils\message\CC.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$5.class +me\devkevin\landcore\listeners\MenuListeners.class +me\devkevin\landcore\utils\ReflectionUtils$DataType.class +me\devkevin\landcore\faction\commands\leader\FactionDisbandCommand.class +me\devkevin\landcore\player\color\SetColorCommand.class +me\devkevin\landcore\utils\menu\pagination\GlassFill.class +me\devkevin\landcore\utils\Utilities.class +me\devkevin\landcore\gson\item\ItemMetaType.class +me\devkevin\landcore\player\grant\menus\GrantConfirmMenu$5.class +me\devkevin\landcore\utils\item\ItemUtil$ReloreType.class +me\devkevin\landcore\commands\impl\staff\VanishCommand.class +me\devkevin\landcore\faction\manager\FactionManager.class +me\devkevin\landcore\player\rank\commands\RankCommand.class +me\devkevin\landcore\utils\structure\Cuboid.class +me\devkevin\landcore\utils\structure\Cuboid$1.class +me\devkevin\landcore\player\grant\menus\GrantReasonMenu$6.class +me\devkevin\landcore\utils\message\Messages.class +me\devkevin\landcore\commands\impl\staff\BuildServerCommand.class +me\devkevin\landcore\commands\impl\staff\punish\KickCommand$1.class +me\devkevin\landcore\player\info\menu\UserViewMenu$3.class +me\devkevin\landcore\gson\ItemStackTypeAdapterFactory.class +me\devkevin\landcore\utils\json\JsonChain.class +me\devkevin\landcore\player\tags\enums\SymbolPrefix.class +me\devkevin\landcore\storage\database\MongoStorage.class +me\devkevin\landcore\store\StorePCoinMenu$1.class +me\devkevin\landcore\task\BroadcastTask.class +me\devkevin\landcore\player\notes\json\NoteJsonDeSerializer.class +me\devkevin\landcore\event\BaseEvent.class +me\devkevin\landcore\utils\PlayerList.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$12.class +me\devkevin\landcore\utils\menu\menus\ConfirmMenu$1.class +me\devkevin\landcore\player\grant\menus\GrantConfirmMenu$4.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$2.class +me\devkevin\landcore\punishment\Punishment.class +me\devkevin\landcore\player\CoreProfile$2.class +me\devkevin\landcore\player\info\menu\UserViewMenu$4.class +me\devkevin\landcore\commands\impl\StoreCommand.class +me\devkevin\landcore\player\grant\procedure\GrantProcedureStage.class +me\devkevin\landcore\commands\impl\IgnoreCommand.class +me\devkevin\landcore\commands\impl\TeleportPositionCommand.class +me\devkevin\landcore\faction\commands\player\FactionAcceptCommand.class +me\devkevin\landcore\event\CoreEvent.class +me\devkevin\landcore\player\rank\commands\GrantsCommand.class +me\devkevin\landcore\managers\ProfileManager.class +me\devkevin\landcore\faction\commands\captain\FactionInviteCommand.class +me\devkevin\landcore\LandCoreAPI$LandCoreListener.class +me\devkevin\landcore\player\color\ColorCommand.class +me\devkevin\landcore\utils\ProfileUtil$1.class +me\devkevin\landcore\event\server\ServerShutdownCancelEvent.class +me\devkevin\landcore\utils\structure\Cuboid$CuboidIterator.class +me\devkevin\landcore\utils\menu\ButtonListener.class +me\devkevin\landcore\store\StorePCoinMenu$2.class +me\devkevin\landcore\utils\structure\Cuboid$CuboidDirection.class +me\devkevin\landcore\player\CoreProfile$3.class +me\devkevin\landcore\player\grant\menus\GrantDurationMenu$1.class +me\devkevin\landcore\player\grant\procedure\GrantProcedureListener.class +me\devkevin\landcore\player\grant\menus\GrantConfirmMenu$3.class +me\devkevin\landcore\commands\impl\staff\punish\UnbanCommand.class +me\devkevin\landcore\listeners\redis\StaffChatListener.class +me\devkevin\landcore\commands\impl\PingCommand.class +me\devkevin\landcore\player\tags\menu\PrefixMenu$11.class diff --git a/LandCore/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/LandCore/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..98bf270 --- /dev/null +++ b/LandCore/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,241 @@ +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\StoreCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\PlayTimeCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\pagination\PaginatedMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\callback\DocumentCallback.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\ReportListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\procedure\PunishmentProcedureStage.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\inventory\InventoryMaker.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\EnchantCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\ButtonListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\managers\PlayerManager.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\packet\PlayerInfoPacketMod.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\managers\StaffManager.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\menus\QuickGrantMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\commands\RankCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\MisplaceCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\redis\RedisMessenger.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\time\TimeFormatUtils.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\inventory\UtilItem.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\ClearChatCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\storage\database\MongoStorage.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\TypeCallback.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\menu\PunishmentsListMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\HealCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\packet\PacketInterceptor.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\Protocol.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\toggle\ToggleGlobalChat.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\RedisFactionListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\storage\flatfile\Config.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\color\menu\ColorMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\PlayerFakeEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\task\ShutdownTask.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\Menu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\leader\FactionDescriptionCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\gson\CustomLocationTypeAdapterFactory.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\buttons\DisplayButton.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\VanishCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\CoreEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\menu\PunishmentsMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\MenuListeners.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\storage\database\MongoRequest.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\procedure\GrantProcedureStage.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\Menu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\tags\enums\SymbolPrefix.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\UnmuteCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\AltsCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\location\CustomLocation.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\inventory\menu\Menu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\member\FactionMember.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\MessageCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\FieldBoundReflections.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\inventory\menu\action\Action.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\other\UUIDFetcher.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\WarnCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\IgnoreCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\StringUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\task\GrantDisguiseCheckTask.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\MuteChatCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\tags\enums\CountriesPrefix.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\buttons\BackButton.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\ReflectionUtils.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\inventory\UIListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\buttons\Glass.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\web\WebUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\StaffChatCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\Rank.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\player\FactionCreateCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\PingCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\captain\FactionPromoteCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\UnbanCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\HelpOpCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\CoreProfileEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\timer\impl\DoubleTimer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\listener\PunishmentListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\menus\GrantDurationMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\PunishmentJsonSerializer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\ListCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\disguise\menu\DisguiseMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\commands\GrantsCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\menu\RankListMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\NumberUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\tags\enums\TextSymbolPrefix.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\Button.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\TaskUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\MessageListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\info\UserCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\FeedCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\store\StorePCoinMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\timer\Timer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\menus\ConfirmMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\ProfileUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\MuteCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\player\FactionInfoCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\tags\PrefixCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\CoreProfile.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\Punishment.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\menus\GrantReasonMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\packet\ScoreboardTeamPacketMod.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\permissions\SetPermissionCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\pagination\ViewAllPagesMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\FreezeCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\json\JsonDeserializer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\BuildServerCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\HelpCommandListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\nametag\impl\InternalNametag.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\invite\FactionInvite.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\LandCore.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\structure\Cuboid.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\TeleportPositionCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\HelpopListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\color\ColorCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\pagination\JumpToPageButton.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\PunishmentType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\task\BroadcastTask.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\item\ItemUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\nametag\impl\NametagListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\redis\message\RedisMessage.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\player\FactionAcceptCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\menu\NotesMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\handler\PacketListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\gson\ItemStackTypeAdapterFactory.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\inventory\InventoryUIHolder.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\message\ClickableMessage.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\message\Messages.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\tags\menu\PrefixMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\json\JsonChain.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\listener\FactionListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\nametag\NameTagAdapter.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\commands\RankListCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\toggle\ToggleMessagesCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\BukkitReflection.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\server\ServerShutdownCancelEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\FactionHelpCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\timer\impl\IntegerTimer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\ShutdownCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\server\ServerSettings.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\BaseEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\toggle\ToggleSoundsCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\permissions\DeletePermissionCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\server\filter\Filter.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\Utilities.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\message\CC.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\FrozenDisconnectListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\server\WhitelistMode.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\commands\NoteRemoveCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\MenuUpdateTask.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\buttons\ConfirmationButton.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\player\PlayerRankChangeEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\PlayerListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\Clickable.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\procedure\GrantProcedure.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\leader\FactionDisbandCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\StaffStreamListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\member\FactionMemberType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\json\NoteJsonSerializer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\managers\ProfileManager.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\menus\GrantSelectMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\ReplyCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\gson\item\ItemMetaType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\player\FactionLeaveCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\nametag\impl\NametagProvider.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\managers\MenuManager.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\disguise\PreDisguiseEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\PlayerPacketListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\gson\item\EnchantType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\commands\GrantCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\timer\AbstractTimer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\menus\GrantConfirmMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\BanEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\redis\annotation\RedisHandler.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\PlayerVersion.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\FreezeListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\pagination\PageButton.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\Note.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\disguise\manager\DisguiseManager.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\captain\FactionDemoteCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\InventoryListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\color\SetColorCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\inventory\InventoryUI.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\packet\PacketListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\ReportCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\BanCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\procedure\PunishmentProcedureType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\inventory\menu\impl\PerPlayerMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\UUIDUtils.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\info\menu\UserViewMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\buttons\CloseButton.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\player\PlayerFreezeEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\server\ServerShutdownScheduleEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\procedure\GrantProcedureListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\SkinUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\player\FactionChatCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\StaffChatListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\gson\item\ItemType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\commands\NotesCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\commands\NoteAddCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\Duration.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\captain\FactionPasswordCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\captain\FactionKickCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\ButtonSound.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\http\Skin.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\json\JsonSerializer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\menus\GrantViewMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\BaseCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\WoolUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\manager\FactionManager.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\CheckCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\other\GameProfileUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\grant\Grant.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\Faction.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\item\ItemBuilder.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\BroadcastCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\PlayerCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\LandCoreAPI.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\SlowChatCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\punish\KickCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\inventory\menu\impl\ReportMenu.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\time\TimeUtil.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\PlayerInteractListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\server\filter\NegativeWordPair.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\PCoinsCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\listeners\redis\RedisServerMonitorListener.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\menu\pagination\GlassFill.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\GameModeCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\profile\FactionProfile.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\PlayerList.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\disguise\commands\DisguiseCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\TeleportCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\item\ItemMaker.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\procedure\PunishmentProcedure.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\faction\commands\captain\FactionInviteCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\callback\WebCallback.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\gson\item\PotionEffectType.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\commands\impl\staff\WhitelistCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\disguise\commands\UndisguiseCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\packet\PacketAdapter.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\notes\json\NoteJsonDeSerializer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\disguise\UnDisguiseEvent.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\punishment\PunishmentJsonDeserializer.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\player\rank\commands\QuickGrantCommand.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\utils\NumberUtils.java +C:\Users\kevin\Desktop\Java Projects\LandCore\src\main\java\me\devkevin\landcore\event\player\PlayerMessageEvent.java diff --git a/LandCore/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst b/LandCore/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/createdFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/LandCore/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/LandCore/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/LandCore/target/original-LandCore-1.3-SNAPSHOT.jar b/LandCore/target/original-LandCore-1.3-SNAPSHOT.jar new file mode 100644 index 0000000..25255d2 Binary files /dev/null and b/LandCore/target/original-LandCore-1.3-SNAPSHOT.jar differ diff --git a/Practice/.idea/.gitignore b/Practice/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/Practice/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/Practice/.idea/artifacts/Practice_jar.xml b/Practice/.idea/artifacts/Practice_jar.xml new file mode 100644 index 0000000..8a1ac60 --- /dev/null +++ b/Practice/.idea/artifacts/Practice_jar.xml @@ -0,0 +1,13 @@ + + + $PROJECT_DIR$/../../jars de los plugins que usare + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/compiler-DESKTOP-G1HQ77A.xml b/Practice/.idea/compiler-DESKTOP-G1HQ77A.xml new file mode 100644 index 0000000..38a2568 --- /dev/null +++ b/Practice/.idea/compiler-DESKTOP-G1HQ77A.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/compiler.xml b/Practice/.idea/compiler.xml new file mode 100644 index 0000000..38a2568 --- /dev/null +++ b/Practice/.idea/compiler.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/discord.xml b/Practice/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/Practice/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/Practice/.idea/encodings.xml b/Practice/.idea/encodings.xml new file mode 100644 index 0000000..af673e7 --- /dev/null +++ b/Practice/.idea/encodings.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/fileTemplates/internal/AnnotationType.java b/Practice/.idea/fileTemplates/internal/AnnotationType.java new file mode 100644 index 0000000..afcedb5 --- /dev/null +++ b/Practice/.idea/fileTemplates/internal/AnnotationType.java @@ -0,0 +1,10 @@ +#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end +#parse("File Header.java") + +/** + * @author DevKevin (devkevinggg@gmail.com) + * ${DATE} @ ${TIME} + * ${NAME} / ${PACKAGE_NAME} / ${PROJECT_NAME} + */ +public @interface ${NAME} { +} diff --git a/Practice/.idea/fileTemplates/internal/Class.java b/Practice/.idea/fileTemplates/internal/Class.java new file mode 100644 index 0000000..5342a36 --- /dev/null +++ b/Practice/.idea/fileTemplates/internal/Class.java @@ -0,0 +1,10 @@ +#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end +#parse("File Header.java") + +/** + * @author DevKevin (devkevinggg@gmail.com) + * ${DATE} @ ${TIME} + * ${NAME} / ${PACKAGE_NAME} / ${PROJECT_NAME} + */ +public class ${NAME} { +} diff --git a/Practice/.idea/fileTemplates/internal/Enum.java b/Practice/.idea/fileTemplates/internal/Enum.java new file mode 100644 index 0000000..8b82712 --- /dev/null +++ b/Practice/.idea/fileTemplates/internal/Enum.java @@ -0,0 +1,10 @@ +#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end +#parse("File Header.java") + +/** + * @author DevKevin (devkevinggg@gmail.com) + * ${DATE} @ ${TIME} + * ${NAME} / ${PACKAGE_NAME} / ${PROJECT_NAME} + */ +public enum ${NAME} { +} diff --git a/Practice/.idea/fileTemplates/internal/Interface.java b/Practice/.idea/fileTemplates/internal/Interface.java new file mode 100644 index 0000000..9154f3e --- /dev/null +++ b/Practice/.idea/fileTemplates/internal/Interface.java @@ -0,0 +1,10 @@ +#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end +#parse("File Header.java") + +/** + * @author DevKevin (devkevinggg@gmail.com) + * ${DATE} @ ${TIME} + * ${NAME} / ${PACKAGE_NAME} / ${PROJECT_NAME} + */ +public interface ${NAME} { +} diff --git a/Practice/.idea/fileTemplates/internal/Record.java b/Practice/.idea/fileTemplates/internal/Record.java new file mode 100644 index 0000000..e224e45 --- /dev/null +++ b/Practice/.idea/fileTemplates/internal/Record.java @@ -0,0 +1,10 @@ +#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end +#parse("File Header.java") + +/** + * @author DevKevin (devkevinggg@gmail.com) + * ${DATE} @ ${TIME} + * ${NAME} / ${PACKAGE_NAME} / ${PROJECT_NAME} + */ +public record ${NAME}() { +} diff --git a/Practice/.idea/inspectionProfiles/Project_Default.xml b/Practice/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6461f49 --- /dev/null +++ b/Practice/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,14 @@ + + + + \ No newline at end of file diff --git a/Practice/.idea/jarRepositories.xml b/Practice/.idea/jarRepositories.xml new file mode 100644 index 0000000..6faed73 --- /dev/null +++ b/Practice/.idea/jarRepositories.xml @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/jpa-buddy.xml b/Practice/.idea/jpa-buddy.xml new file mode 100644 index 0000000..966d5f5 --- /dev/null +++ b/Practice/.idea/jpa-buddy.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/Practice/.idea/misc-DESKTOP-G1HQ77A.xml b/Practice/.idea/misc-DESKTOP-G1HQ77A.xml new file mode 100644 index 0000000..c2eb269 --- /dev/null +++ b/Practice/.idea/misc-DESKTOP-G1HQ77A.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/misc.xml b/Practice/.idea/misc.xml new file mode 100644 index 0000000..deb37fb --- /dev/null +++ b/Practice/.idea/misc.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/uiDesigner.xml b/Practice/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/Practice/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Practice/.idea/workspace-DESKTOP-G1HQ77A.xml b/Practice/.idea/workspace-DESKTOP-G1HQ77A.xml new file mode 100644 index 0000000..cecf794 --- /dev/null +++ b/Practice/.idea/workspace-DESKTOP-G1HQ77A.xml @@ -0,0 +1,215 @@ + + + + + + + + + + + Countdown + getCountdown + join unranked + PAPER + emerald + giving you + Match ended + succesfully + you have + starting + starting duel match. + searching + MATCH SUMMary + winner + select a + ELO range + RED + ELO + yellow + Settings + StatsCommand + click here + strafe + Save + you are editing + aqua + allowing + cooldown + club.egirls.practice + /inv + + + vip.strafe.practice + + +

C:\Users\filoù\Desktop\mcp\eclipse\Practice\src\main\java\club\egirls\practice + C:\Users\filoù\Desktop\mcp\eclipse\Practice + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1552408540221 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + file://$PROJECT_DIR$/src/main/java/vip/strafe/practice/commands/management/TournamentCommand.java + 56 + + + file://$PROJECT_DIR$/src/main/java/vip/strafe/practice/managers/InventoryManager.java + 665 + + + + + + + \ No newline at end of file diff --git a/Practice/README.MD b/Practice/README.MD new file mode 100644 index 0000000..c66015e --- /dev/null +++ b/Practice/README.MD @@ -0,0 +1,11 @@ +### TO-DO +- [ ] Possibly recode queues and implement some new features to it +- [ ] Add SkyWars Event +- [ ] Add BedWars kit type +- [ ] Add StickFight kit type +- [x] Add HCF TeamFights for Parties +- [x] Fix weird and random invis bug on some matches +- [ ] Allow the Bridges bridge to be broke by players +- [x] Completely recoded arena regeneration +- [ ] Make the Bridges max build height based on the arena so it cannot be glitched +- [ ] Allow the Bridges armor to NOT be explicitly full (helmet, chestplate, leggings, boots) (That means, being able to make the armor not have the helmet for example) diff --git a/Practice/TODO b/Practice/TODO new file mode 100644 index 0000000..2c7233d --- /dev/null +++ b/Practice/TODO @@ -0,0 +1,18 @@ +Practice permissions + +// Donors permissions + +practice.donors.* +practice.donors.{rank_name} + +practice.staff + +practice.developer +practice.platformadmin + +practice.user.spawn-visibility + +practice.host.tournament + + +// TODO: add whitelist arenas for BuildUHC and Sumo 28/11/2022 \ No newline at end of file diff --git a/Practice/dependency-reduced-pom.xml b/Practice/dependency-reduced-pom.xml new file mode 100644 index 0000000..65aa9f7 --- /dev/null +++ b/Practice/dependency-reduced-pom.xml @@ -0,0 +1,118 @@ + + + 4.0.0 + me.devkevin.practice + Practice + Practice + dev-SNAPSHOT + Practice plugin exclusive created for uDrop Network + + + + maven-compiler-plugin + + 1.8 + 1.8 + + + + maven-shade-plugin + 2.1 + + + package + + shade + + + + + + + + + club.inverted + inverted-spigot + 1.8.8-R0.1-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar + + + com.lunarclient + bukkitapi + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/bukkitapi.jar + + + me.devkevin.landcore + LandCore + 1.3-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/LandCore-1.3-SNAPSHOT.jar + + + club.udrop.npc + NPC + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/NPC-1.0-SNAPSHOT.jar + + + com.comphenix.protocol + ProtocolLib + yes + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/ProtocolLib.jar + + + WorldEdit + WorldEdit + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/WorldEdit.jar + + + ViaVersion-3.2.1 + ViaVersion-3.2.1 + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/ViaVersion-3.2.1.jar + + + ViaRewind-1.4.5 + ViaRewind-1.4.5 + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/ViaRewind-1.4.5.jar + + + FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0 + FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0 + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0.jar + + + PlaceholderAPI-2.10.9 + PlaceholderAPI-2.10.9 + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/PlaceholderAPI-2.10.9.jar + + + me.filoghost.holographicdisplays + HolographicDisplays + 1.0-SNAPSHOT + system + C:\Users\kevin\Desktop\Java Projects\Practice/lib/HolographicDisplays.jar + + + org.projectlombok + lombok + 1.16.20 + provided + + + + diff --git a/Practice/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar b/Practice/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar new file mode 100644 index 0000000..b8e579f Binary files /dev/null and b/Practice/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar differ diff --git a/Practice/lib/FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0.jar b/Practice/lib/FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0.jar new file mode 100644 index 0000000..aa92422 Binary files /dev/null and b/Practice/lib/FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0.jar differ diff --git a/Practice/lib/HolographicDisplays.jar b/Practice/lib/HolographicDisplays.jar new file mode 100644 index 0000000..f2202b2 Binary files /dev/null and b/Practice/lib/HolographicDisplays.jar differ diff --git a/Practice/lib/LandCore-1.3-SNAPSHOT.jar b/Practice/lib/LandCore-1.3-SNAPSHOT.jar new file mode 100644 index 0000000..af4ee14 Binary files /dev/null and b/Practice/lib/LandCore-1.3-SNAPSHOT.jar differ diff --git a/Practice/lib/NPC-1.0-SNAPSHOT.jar b/Practice/lib/NPC-1.0-SNAPSHOT.jar new file mode 100644 index 0000000..9e1e0d1 Binary files /dev/null and b/Practice/lib/NPC-1.0-SNAPSHOT.jar differ diff --git a/Practice/lib/PlaceholderAPI-2.10.9.jar b/Practice/lib/PlaceholderAPI-2.10.9.jar new file mode 100644 index 0000000..ac94604 Binary files /dev/null and b/Practice/lib/PlaceholderAPI-2.10.9.jar differ diff --git a/Practice/lib/ProtocolLib.jar b/Practice/lib/ProtocolLib.jar new file mode 100644 index 0000000..74682ff Binary files /dev/null and b/Practice/lib/ProtocolLib.jar differ diff --git a/Practice/lib/ViaRewind-1.4.5.jar b/Practice/lib/ViaRewind-1.4.5.jar new file mode 100644 index 0000000..ca56bf2 Binary files /dev/null and b/Practice/lib/ViaRewind-1.4.5.jar differ diff --git a/Practice/lib/ViaVersion-3.2.1.jar b/Practice/lib/ViaVersion-3.2.1.jar new file mode 100644 index 0000000..c68ea80 Binary files /dev/null and b/Practice/lib/ViaVersion-3.2.1.jar differ diff --git a/Practice/lib/WorldEdit.jar b/Practice/lib/WorldEdit.jar new file mode 100644 index 0000000..9411332 Binary files /dev/null and b/Practice/lib/WorldEdit.jar differ diff --git a/Practice/lib/bukkitapi.jar b/Practice/lib/bukkitapi.jar new file mode 100644 index 0000000..d4a7bcf Binary files /dev/null and b/Practice/lib/bukkitapi.jar differ diff --git a/Practice/pom.xml b/Practice/pom.xml new file mode 100644 index 0000000..7f59279 --- /dev/null +++ b/Practice/pom.xml @@ -0,0 +1,177 @@ + + + 4.0.0 + + me.devkevin.practice + Practice + Practice + dev-SNAPSHOT + + Practice plugin exclusive created for uDrop Network + + + + + + club.inverted + inverted-spigot + 1.8.8-R0.1-SNAPSHOT + system + ${project.basedir}/lib/Carbon-Server-1.8.8-R0.1-SNAPSHOT.jar + + + + + com.lunarclient + bukkitapi + 1.0-SNAPSHOT + system + ${project.basedir}/lib/bukkitapi.jar + + + + + me.devkevin.landcore + LandCore + 1.3-SNAPSHOT + system + ${project.basedir}/lib/LandCore-1.3-SNAPSHOT.jar + + + + + club.udrop.npc + NPC + 1.0-SNAPSHOT + system + ${project.basedir}/lib/NPC-1.0-SNAPSHOT.jar + + + + + com.comphenix.protocol + ProtocolLib + yes + system + ${project.basedir}/lib/ProtocolLib.jar + + + + + WorldEdit + WorldEdit + 1.0-SNAPSHOT + system + ${project.basedir}/lib/WorldEdit.jar + + + + + ViaVersion-3.2.1 + ViaVersion-3.2.1 + 1.0-SNAPSHOT + system + ${project.basedir}/lib/ViaVersion-3.2.1.jar + + + + + ViaRewind-1.4.5 + ViaRewind-1.4.5 + 1.0-SNAPSHOT + system + ${project.basedir}/lib/ViaRewind-1.4.5.jar + + + + + FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0 + FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0 + 1.0-SNAPSHOT + system + ${project.basedir}/lib/FastAsyncWorldEdit-bukkit-19.07.12-5cc5ce5-1277-22.3.0.jar + + + + + PlaceholderAPI-2.10.9 + PlaceholderAPI-2.10.9 + 1.0-SNAPSHOT + system + ${project.basedir}/lib/PlaceholderAPI-2.10.9.jar + + + + + me.filoghost.holographicdisplays + HolographicDisplays + 1.0-SNAPSHOT + system + ${project.basedir}/lib/HolographicDisplays.jar + + + + + com.google.code.gson + gson + 2.10.1 + + + + org.projectlombok + lombok + 1.16.20 + provided + + + + + org.mongodb + mongo-java-driver + 3.12.11 + compile + + + net.dv8tion + JDA + 1.2.2_139 + + + + + net.dv8tion + JDA + 5.0.0-beta.5 + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.1 + + + package + + shade + + + + + + + + \ No newline at end of file diff --git a/Practice/src/main/java/club/inverted/chatcolor/CC.java b/Practice/src/main/java/club/inverted/chatcolor/CC.java new file mode 100644 index 0000000..88446b2 --- /dev/null +++ b/Practice/src/main/java/club/inverted/chatcolor/CC.java @@ -0,0 +1,186 @@ +package club.inverted.chatcolor; + +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.ConsoleCommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; +import java.util.stream.StreamSupport; + +/** + * Copyright 05/08/2019 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public final class CC { + + public static final String BLUE = ChatColor.BLUE.toString(); + public static final String AQUA = ChatColor.AQUA.toString(); + public static final String YELLOW = ChatColor.YELLOW.toString(); + public static final String RED = ChatColor.RED.toString(); + public static final String GRAY = ChatColor.GRAY.toString(); + public static final String GOLD = ChatColor.GOLD.toString(); + public static final String GREEN = ChatColor.GREEN.toString(); + public static final String WHITE = ChatColor.WHITE.toString(); + public static final String BLACK = ChatColor.BLACK.toString(); + public static final String BOLD = ChatColor.BOLD.toString(); + public static final String ITALIC = ChatColor.ITALIC.toString(); + public static final String UNDERLINE = ChatColor.UNDERLINE.toString(); + public static final String STRIKETHROUGH = ChatColor.STRIKETHROUGH.toString(); + public static final String RESET = ChatColor.RESET.toString(); + public static final String MAGIC = ChatColor.MAGIC.toString(); + public static final String OBFUSCATED = MAGIC; + public static final String B = BOLD; + public static final String M = MAGIC; + public static final String O = MAGIC; + public static final String I = ITALIC; + public static final String S = STRIKETHROUGH; + public static final String R = RESET; + public static final String DARK_BLUE = ChatColor.DARK_BLUE.toString(); + public static final String DARK_AQUA = ChatColor.DARK_AQUA.toString(); + public static final String DARK_GRAY = ChatColor.DARK_GRAY.toString(); + public static final String DARK_GREEN = ChatColor.DARK_GREEN.toString(); + public static final String DARK_PURPLE = ChatColor.DARK_PURPLE.toString(); + public static final String DARK_RED = ChatColor.DARK_RED.toString(); + public static final String D_BLUE = DARK_BLUE; + public static final String D_AQUA = DARK_AQUA; + public static final String D_GRAY = DARK_GRAY; + public static final String D_GREEN = DARK_GREEN; + public static final String D_PURPLE = DARK_PURPLE; + public static final String D_RED = DARK_RED; + public static final String LIGHT_PURPLE = ChatColor.LIGHT_PURPLE.toString(); + public static final String L_PURPLE = LIGHT_PURPLE; + public static final String PINK = L_PURPLE; + public static final String SCOREBAORD_SEPARATOR = CC.GRAY + CC.S + "----------------------"; + public static final String MENU_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "------------------------"; + public static final String CHAT_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "------------------------------------------------"; + public static final String SB_BAR = ChatColor.GRAY.toString() + ChatColor.STRIKETHROUGH.toString() + "----------------------"; + + public static short translateToWool(ChatColor color) { + switch (color) { + case WHITE: + return 0; + case GOLD: + return 1; + case AQUA: + return 3; + case YELLOW: + return 4; + case GREEN: + return 5; + case LIGHT_PURPLE: + return 6; + case DARK_GRAY: + return 7; + case GRAY: + return 8; + case DARK_AQUA: + return 9; + case DARK_PURPLE: + return 10; + case DARK_BLUE: + case BLUE: + return 11; + case DARK_GREEN: + return 13; + case DARK_RED: + case RED: + return 14; + default: + return 0; + } + } + + /** + * Returns a coloured version of a string. + * + * @param string the string to be coloured. + * @return coloured string. + */ + public static String translate(String string) { + return ChatColor.translateAlternateColorCodes('&', string); + } + + /** + * Returns a coloured version of a list. + * + * @param iterable the list to be coloured. + * @return coloured list. + */ + public static List translate(Iterable iterable) { + return StreamSupport.stream(iterable.spliterator(), false).filter(Objects::nonNull).map(CC::translate).collect(Collectors.toList()); + } + + /** + * Returns a coloured version of a list. + * + * @param list the list to be coloured. + * @return coloured list. + * */ + public static List translate(List list) { + List buffered = new ArrayList(); + for (String string : list) buffered.add(translate(string)); + return buffered; + } + + /** + * Returns a coloured version of string list. + * + * @param strings the strings list to be coloured. + * @return coloured strings list. + * */ + public static String[] translate(String... strings) { + return translate(Arrays.asList(strings)).stream().toArray(String[]::new); + } + + /** + * Convert strings to colors that are sent to the {@link Player}. + * + * @param receiver who is receiving the message. + * @return strings what you're sending. + * */ + public static void sendMessage(Player receiver, String... strings) { + receiver.sendMessage(translate(strings)); + } + + /** + * Convert strings to colors that are sent to the {@link CommandSender}. + * + * @param commandSender who is receiving the message. + * @return strings what you're sending. + * */ + public static void sendMessage(CommandSender commandSender, String... strings) { + commandSender.sendMessage(translate(strings)); + } + + /** + * Convert strings to colors that are sent to the {@link CommandSender}. + * + * @param commandSender who is receiving the message. + * @return component text what you're sending. + * */ + public static void sendMessage(CommandSender commandSender, BaseComponent[] value) { + if(commandSender instanceof Player) { + ((Player) commandSender).spigot().sendMessage(value); + } else { + commandSender.sendMessage(TextComponent.toLegacyText(value)); + } + } + + /** + * Convert strings to colors that are sent to the {@link ConsoleCommandSender}. + * + * @return strings what you're sending to the console. + * */ + public static void logger(String... strings) { + Bukkit.getConsoleSender().sendMessage(translate(strings)); + } +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/Aether.java b/Practice/src/main/java/com/bizarrealex/aether/Aether.java new file mode 100644 index 0000000..9f75b92 --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/Aether.java @@ -0,0 +1,157 @@ +package com.bizarrealex.aether; + +import com.bizarrealex.aether.event.BoardCreateEvent; +import com.bizarrealex.aether.scoreboard.Board; +import com.bizarrealex.aether.scoreboard.BoardAdapter; +import com.bizarrealex.aether.scoreboard.BoardEntry; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Score; +import org.bukkit.scoreboard.Scoreboard; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static com.bizarrealex.aether.AetherOptions.defaultOptions; + +public class Aether { + + @Getter BoardAdapter adapter; + @Getter private final JavaPlugin plugin; + @Getter private final AetherOptions options; + + public Aether(JavaPlugin plugin, BoardAdapter adapter, AetherOptions options) { + this.options = options; + this.plugin = plugin; + + setAdapter(adapter); + run(); + } + + public Aether(JavaPlugin plugin, BoardAdapter adapter) { + this(plugin, adapter, defaultOptions()); + } + + public Aether(JavaPlugin plugin) { + this(plugin, null, defaultOptions()); + } + + private void run() { + new BukkitRunnable() { + @Override + public void run() { + if (adapter == null) return; + for (Player player : Bukkit.getOnlinePlayers()) { + Board board = Board.getByPlayer(player); + if (board != null) { + List scores = adapter.getScoreboard(player, board, board.getCooldowns()); + List translatedScores = new ArrayList<>(); + if (scores == null) { + if (!board.getEntries().isEmpty()) { + for (BoardEntry boardEntry : board.getEntries()) { + boardEntry.remove(); + } + board.getEntries().clear(); + } + continue; + } + + for (String line : scores) { + translatedScores.add(ChatColor.translateAlternateColorCodes('&', line)); + } + + if (!options.scoreDirectionDown()) { + Collections.reverse(scores); + } + + Scoreboard scoreboard = board.getScoreboard(); + Objective objective = board.getObjective(); + + if (!(objective.getDisplayName().equals(adapter.getTitle(player)))) { + objective.setDisplayName(ChatColor.translateAlternateColorCodes('&', adapter.getTitle(player))); + } + + outer: + for (int i = 0; i < scores.size(); i++) { + String text = scores.get(i); + int position; + if (options.scoreDirectionDown()) { + position = 15 - i; + } else { + position = i + 1; + } + + Iterator iterator = new ArrayList<>(board.getEntries()).iterator(); + while (iterator.hasNext()) { + BoardEntry boardEntry = iterator.next(); + Score score = objective.getScore(boardEntry.getKey()); + + if (score != null && boardEntry.getText().equals(ChatColor.translateAlternateColorCodes('&', text))) { + if (score.getScore() == position) { + continue outer; + } + } + } + + int positionToSearch = options.scoreDirectionDown() ? 15 - position : position - 1; + + iterator = board.getEntries().iterator(); + while (iterator.hasNext()) { + BoardEntry boardEntry = iterator.next(); + int entryPosition = scoreboard.getObjective(DisplaySlot.SIDEBAR).getScore(boardEntry.getKey()).getScore(); + + if (!options.scoreDirectionDown()) { + if (entryPosition > scores.size()) { + iterator.remove(); + boardEntry.remove(); + } + } + + } + + BoardEntry entry = board.getByPosition(positionToSearch); + + if (entry == null) { + new BoardEntry(board, text).send(position); + } else { + entry.setText(text).setup().send(position); + } + + if (board.getEntries().size() > scores.size()) { + iterator = board.getEntries().iterator(); + while (iterator.hasNext()) { + BoardEntry boardEntry = iterator.next(); + if ((!translatedScores.contains(boardEntry.getText())) || Collections.frequency(board.getBoardEntriesFormatted(), boardEntry.getText()) > 1) { + iterator.remove(); + boardEntry.remove(); + } + } + } + } + adapter.onScoreboardCreate(player, scoreboard); + player.setScoreboard(scoreboard); + } + } + } + }.runTaskTimerAsynchronously(plugin, 20L, 2L); + } + + public void setAdapter(BoardAdapter adapter) { + this.adapter = adapter; + for (Player player : Bukkit.getOnlinePlayers()) { + Board board = Board.getByPlayer(player); + if (board != null) { + Board.getBoards().remove(board); + } + Bukkit.getPluginManager().callEvent(new BoardCreateEvent(new Board(player, this, options), player)); + } + } +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/AetherOptions.java b/Practice/src/main/java/com/bizarrealex/aether/AetherOptions.java new file mode 100644 index 0000000..ad0b588 --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/AetherOptions.java @@ -0,0 +1,18 @@ +package com.bizarrealex.aether; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(chain = true, fluent = true) +public class AetherOptions { + + private boolean hook; + private boolean scoreDirectionDown; + + static AetherOptions defaultOptions() { + return new AetherOptions().hook(false).scoreDirectionDown(false); + } +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/event/BoardCreateEvent.java b/Practice/src/main/java/com/bizarrealex/aether/event/BoardCreateEvent.java new file mode 100644 index 0000000..0425b8e --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/event/BoardCreateEvent.java @@ -0,0 +1,27 @@ +package com.bizarrealex.aether.event; + +import com.bizarrealex.aether.scoreboard.Board; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BoardCreateEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + @Getter private final Board board; + @Getter private final Player player; + + public BoardCreateEvent(Board board, Player player) { + this.board = board; + this.player = player; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/scoreboard/Board.java b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/Board.java new file mode 100644 index 0000000..6ae127d --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/Board.java @@ -0,0 +1,129 @@ +package com.bizarrealex.aether.scoreboard; + +import com.bizarrealex.aether.Aether; +import com.bizarrealex.aether.AetherOptions; +import com.bizarrealex.aether.scoreboard.cooldown.BoardCooldown; +import io.netty.util.internal.ConcurrentSet; +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; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public class Board { + + @Getter private static final Set boards = new ConcurrentSet<>(); + + private final Aether aether; + private final AetherOptions options; + + @Getter private Scoreboard scoreboard; + @Getter private final Player player; + @Getter private Objective objective; + @Getter private final Set keys; + @Getter private final List entries; + + private final Set cooldowns; + + public Board(Player player, Aether aether, AetherOptions options) { + this.player = player; + this.aether = aether; + this.options = options; + + this.keys = new ConcurrentSet<>(); + this.entries = new ArrayList<>(); + + this.cooldowns = new ConcurrentSet<>(); + + setup(); + } + + public static Board getByPlayer(Player player) { + for (Board board : boards) { + if (board.getPlayer().getName().equals(player.getName())) { + return board; + } + } + + return null; + } + + private void setup() { + if (options.hook() && !player.getScoreboard().equals(Bukkit.getScoreboardManager().getMainScoreboard())) { + scoreboard = player.getScoreboard(); + } else { + scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + } + + objective = scoreboard.registerNewObjective("glaedr_is_shit", "dummy"); + objective.setDisplaySlot(DisplaySlot.SIDEBAR); + + if (aether.getAdapter() != null) { + objective.setDisplayName(ChatColor.translateAlternateColorCodes('&', aether.getAdapter().getTitle(player))); + } else { + objective.setDisplayName("Default Title"); + } + + boards.add(this); + } + + public String getNewKey(BoardEntry entry) { + for (ChatColor color : ChatColor.values()) { + String colorText = color + "" + ChatColor.WHITE; + if (entry.getText().length() > 16) { + String sub = entry.getText().substring(0, 16); + colorText = colorText + ChatColor.getLastColors(sub); + } + + if (!keys.contains(colorText)) { + keys.add(colorText); + return colorText; + } + } + + throw new IndexOutOfBoundsException("No more keys available!"); + } + + public List getBoardEntriesFormatted() { + List toReturn = new ArrayList<>(); + for (BoardEntry entry : new ArrayList<>(entries)) { + toReturn.add(entry.getText()); + } + + return toReturn; + } + + public BoardEntry getByPosition(int position) { + int i = 0; + + for (BoardEntry board : entries) { + if (i == position) { + return board; + } + i++; + } + + return null; + } + + public BoardCooldown getCooldown(String id) { + for (BoardCooldown cooldown : getCooldowns()) { + if (cooldown.getId().equals(id)) { + return cooldown; + } + } + + return null; + } + + public Set getCooldowns() { + cooldowns.removeIf(cooldown -> System.currentTimeMillis() >= cooldown.getEnd()); + return cooldowns; + } +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/scoreboard/BoardAdapter.java b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/BoardAdapter.java new file mode 100644 index 0000000..b8bf4c1 --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/BoardAdapter.java @@ -0,0 +1,17 @@ +package com.bizarrealex.aether.scoreboard; + +import com.bizarrealex.aether.scoreboard.cooldown.BoardCooldown; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Scoreboard; + +import java.util.List; +import java.util.Set; + +public interface BoardAdapter { + + String getTitle(Player player); + + List getScoreboard(Player player, Board board, Set cooldowns); + + void onScoreboardCreate(Player player, Scoreboard board); +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/scoreboard/BoardEntry.java b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/BoardEntry.java new file mode 100644 index 0000000..ecd1321 --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/BoardEntry.java @@ -0,0 +1,89 @@ +package com.bizarrealex.aether.scoreboard; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.bukkit.ChatColor; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Score; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +@Accessors(chain = true) +public class BoardEntry { + + @Getter private final Board board; + @Getter @Setter private String text; + @Getter private final String originalText; + @Getter private final String key; + @Getter private Team team; + + public BoardEntry(Board board, String text) { + this.board = board; + this.text = text; + this.originalText = text; + this.key = board.getNewKey(this); + + setup(); + } + + public BoardEntry setup() { + Scoreboard scoreboard = board.getScoreboard(); + + text = ChatColor.translateAlternateColorCodes('&', text); + + String teamName = key; + + if (teamName.length() > 16) { + teamName = teamName.substring(0, 16); + } + + if (scoreboard.getTeam(teamName) != null) { + team = scoreboard.getTeam(teamName); + } else { + team = scoreboard.registerNewTeam(teamName); + } + + if (!(team.getEntries().contains(key))) { + team.addEntry(key); + } + + if (!(board.getEntries().contains(this))) { + board.getEntries().add(this); + } + + return this; + } + + public void send(int position) { + Objective objective = board.getObjective(); + + if (text.length() > 16) { + boolean fix = text.toCharArray()[15] == ChatColor.COLOR_CHAR; + + String prefix = fix ? text.substring(0, 15) : text.substring(0, 16); + String suffix = fix ? text.substring(15) : ChatColor.getLastColors(prefix) + text.substring(16); + + team.setPrefix(prefix); + + if (suffix.length() > 16) { + team.setSuffix(suffix.substring(0, 16)); + } else { + team.setSuffix(suffix); + } + } else { + team.setPrefix(text); + team.setSuffix(""); + } + + Score score = objective.getScore(key); + score.setScore(position); + + } + + public void remove() { + board.getKeys().remove(key); + board.getScoreboard().resetScores(key); + } + +} diff --git a/Practice/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.java b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.java new file mode 100644 index 0000000..be1c215 --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.java @@ -0,0 +1,42 @@ +package com.bizarrealex.aether.scoreboard.cooldown; + +import com.bizarrealex.aether.scoreboard.Board; +import lombok.Getter; +import org.apache.commons.lang.time.DurationFormatUtils; + +import java.text.DecimalFormat; + +public class BoardCooldown { + + private static final DecimalFormat SECONDS_FORMATTER = new DecimalFormat("#0.0"); + + @Getter private final Board board; + @Getter private final String id; + @Getter private final double duration; + @Getter private final long end; + + public BoardCooldown(Board board, String id, double duration) { + this.board = board; + this.id = id; + this.duration = duration; + this.end = (long) (System.currentTimeMillis() + (duration * 1000)); + + board.getCooldowns().add(this); + } + + public String getFormattedString(BoardFormat format) { + if (format == null) { + throw new NullPointerException(); + } + if (format == BoardFormat.SECONDS) { + return SECONDS_FORMATTER.format(((end - System.currentTimeMillis()) / 1000.0f)); + } else { + return DurationFormatUtils.formatDuration(end - System.currentTimeMillis(), "mm:ss"); + } + } + + public void cancel() { + board.getCooldowns().remove(this); + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.java b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.java new file mode 100644 index 0000000..b90c1c4 --- /dev/null +++ b/Practice/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.java @@ -0,0 +1,7 @@ +package com.bizarrealex.aether.scoreboard.cooldown; + +public enum BoardFormat { + SECONDS, + MINUTES, + HOURS +} diff --git a/Practice/src/main/java/me/devkevin/practice/Practice.java b/Practice/src/main/java/me/devkevin/practice/Practice.java new file mode 100644 index 0000000..129ffb7 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/Practice.java @@ -0,0 +1,426 @@ +package me.devkevin.practice; + +import club.inverted.chatcolor.CC; +import com.bizarrealex.aether.Aether; +import com.google.gson.Gson; +import com.google.gson.JsonParser; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.arena.chunk.listener.ArenaPlayerChunkLimiter; +import me.devkevin.practice.arena.chunk.manager.ChunkManager; +import me.devkevin.practice.arena.chunk.manager.ChunkRestorationManager; +import me.devkevin.practice.arena.command.ArenaChunkCommands; +import me.devkevin.practice.arena.command.ArenaCommand; +import me.devkevin.practice.arena.manager.ArenaManager; +import me.devkevin.practice.board.PracticeBoard; +import me.devkevin.practice.command.general.*; +import me.devkevin.practice.command.requeue.PlayAgainCommand; +import me.devkevin.practice.command.staff.CancelMatchCommand; +import me.devkevin.practice.command.staff.FollowCommand; +import me.devkevin.practice.command.staff.OngoingMatchesCommand; +import me.devkevin.practice.command.staff.StaffModeCommand; +import me.devkevin.practice.command.stats.ResetStatsCommand; +import me.devkevin.practice.command.stats.SetStatsCommand; +import me.devkevin.practice.command.time.DayCommand; +import me.devkevin.practice.command.time.NightCommand; +import me.devkevin.practice.command.time.SunsetCommand; +import me.devkevin.practice.data.PracticeDatabase; +import me.devkevin.practice.events.commands.*; +import me.devkevin.practice.events.manager.EventManager; +import me.devkevin.practice.events.menu.HostMenu; +import me.devkevin.practice.file.Config; +import me.devkevin.practice.general.GeneralSettingMenu; +import me.devkevin.practice.hcf.classes.Archer; +import me.devkevin.practice.hcf.classes.Bard; +import me.devkevin.practice.hcf.effects.EffectRestorer; +import me.devkevin.practice.hcf.listener.HCFClassListener; +import me.devkevin.practice.hcf.listener.HCFMatchListener; +import me.devkevin.practice.hcf.manager.HCFManager; +import me.devkevin.practice.kit.command.KitManageCommand; +import me.devkevin.practice.kit.command.KitsCommand; +import me.devkevin.practice.kit.listener.KitEditorError32Listener; +import me.devkevin.practice.kit.manager.EditorManager; +import me.devkevin.practice.kit.manager.KitManager; +import me.devkevin.practice.kit.menu.KitEditorMenu; +import me.devkevin.practice.leaderboard.LeaderboardManager; +import me.devkevin.practice.leaderboard.hologram.HologramManager; +import me.devkevin.practice.leaderboard.npc.NPCRunnable; +import me.devkevin.practice.location.manager.CustomLocationManager; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.duel.command.AcceptCommand; +import me.devkevin.practice.match.duel.command.DuelCommand; +import me.devkevin.practice.match.duel.menu.DuelMenu; +import me.devkevin.practice.match.history.MatchLocatedData; +import me.devkevin.practice.match.history.command.MatchHistoryCommand; +import me.devkevin.practice.match.listener.entity.*; +import me.devkevin.practice.match.listener.game.MatchEndListener; +import me.devkevin.practice.match.listener.game.MatchStartListener; +import me.devkevin.practice.match.listener.time.MatchDurationLimitListener; +import me.devkevin.practice.match.manager.MatchManager; +import me.devkevin.practice.match.menu.MatchDetailSnapshot; +import me.devkevin.practice.match.menu.command.InvCommand; +import me.devkevin.practice.match.spec.SpectateCommand; +import me.devkevin.practice.match.timer.TimerManager; +import me.devkevin.practice.match.timer.impl.EnderpearlTimer; +import me.devkevin.practice.match.vote.VoteManager; +import me.devkevin.practice.match.vote.commands.ArenaStatsCommand; +import me.devkevin.practice.match.vote.commands.RateCommand; +import me.devkevin.practice.options.command.OptionsCommand; +import me.devkevin.practice.options.listener.ProfileOptionsListeners; +import me.devkevin.practice.panel.commands.impl.*; +import me.devkevin.practice.party.command.*; +import me.devkevin.practice.party.manager.PartyManager; +import me.devkevin.practice.party.menu.PartyMenu; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.hotbar.HotbarItem; +import me.devkevin.practice.profile.listener.*; +import me.devkevin.practice.profile.manager.ProfileManager; +import me.devkevin.practice.profile.menu.StatsMenu; +import me.devkevin.practice.profile.task.DataLoaderWorkerRunnable; +import me.devkevin.practice.profile.task.ExpBarTask; +import me.devkevin.practice.profile.task.ProfileSaveDataTask; +import me.devkevin.practice.queue.Queue; +import me.devkevin.practice.queue.menu.party.PartyQueueJoinMenu; +import me.devkevin.practice.queue.menu.party.PlayJoinMenu; +import me.devkevin.practice.queue.menu.play.QueueMenu; +import me.devkevin.practice.staff.StaffMode; +import me.devkevin.practice.tournament.command.TournamentCommand; +import me.devkevin.practice.tournament.host.TournamentHostMenu; +import me.devkevin.practice.tournament.manager.TournamentManager; +import me.devkevin.practice.util.GsonFactory; +import me.devkevin.practice.util.command.CommandFramework; +import me.devkevin.practice.util.inventory.UIListener; +import me.devkevin.practice.util.menu.ButtonListener; +import me.devkevin.practice.util.menu.MenuUpdateTask; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.event.Listener; +import org.bukkit.inventory.Recipe; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.*; +import java.util.concurrent.ForkJoinPool; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static org.bukkit.Bukkit.getPluginManager; + +/** + * Copyright (c) Kevin Acaymo (DevKevin) 2020. + * You may not copy, re-sell, distribute, modify, + * or use any code contained in this document or file, + * collection of documents or files, or project. Thank you. + */ +@Getter +public class Practice extends JavaPlugin { + + @Getter private static Practice instance; + + public static final int RECORDING_VERSION = 1; + public static final int ENTITY_ID_OFFSET = 1000; + + public static Random RANDOM = new Random(); + private final JsonParser jsonParser = new JsonParser(); + public static Gson GSON; + + private PracticeDatabase practiceDatabase; + + private Config mainConfig; + private CommandFramework framework; + + private ProfileManager profileManager; + private KitManager kitManager; + private ArenaManager arenaManager; + private CustomLocationManager customLocationManager; + private ChunkManager chunkManager; + private HotbarItem hotbarItem; + private Queue queue; + private MatchManager matchManager; + private MatchDetailSnapshot matchDetailSnapshot; + private DuelMenu duelMenu; + private TimerManager timerManager; + private PartyMenu partyMenu; + private PartyManager partyManager; + private PartyQueueJoinMenu partyQueueJoinMenu; + private EventManager eventManager; + private HostMenu hostMenu; + private StaffMode staffMode; + private ChunkRestorationManager chunkRestorationManager; + private MatchLocatedData matchLocatedData; + private DataLoaderWorkerRunnable dataLoaderWorkerRunnable; + private TournamentManager tournamentManager; + private TournamentHostMenu tournamentHostMenu; + private PlayJoinMenu playJoinMenu; + private LeaderboardManager leaderboardManager; + private GeneralSettingMenu generalSettingMenu; + private QueueMenu queueMenu; + private KitEditorMenu kitEditorMenu; + private EditorManager editorManager; + private VoteManager voteManager; + private StatsMenu statsMenu; + private HCFManager hcfManager; + private EffectRestorer effectRestorer; + private HologramManager hologramManager; + + @Setter private boolean restarting = false; + + private Aether board; + + private String serverName, networkWebsite; + + private long leaderboardUpdateTime; + + @Override + public void onEnable() { + instance = this; + + if (!Practice.getInstance().getDescription().getAuthors().contains("DevKevin") || !Practice.getInstance().getDescription().getName().equals("Practice")) { + getPluginManager().disablePlugin(this); + } + + Bukkit.getConsoleSender().sendMessage(CC.STRIKETHROUGH); + Bukkit.getConsoleSender().sendMessage(CC.translate("&4Practice &8- &fv" + getDescription().getVersion())); + Bukkit.getConsoleSender().sendMessage(CC.translate("&7Made by &6DevKevin")); + Bukkit.getConsoleSender().sendMessage(CC.STRIKETHROUGH); + + leaderboardUpdateTime = (15 * 60L) * 20L; // The time is calculated in minutes + + mainConfig = new Config("config", this); + practiceDatabase = new PracticeDatabase(this); + framework = new CommandFramework(this); + GSON = GsonFactory.getPrettyGson(); + + serverName = "Prac"; + networkWebsite = "prac.lol"; + + this.matchLocatedData = new MatchLocatedData(); + + // setup board, nametag, + this.board = new Aether(this, new PracticeBoard()); + + disableLoggers(); + + // register managers + customLocationManager = new CustomLocationManager(); + chunkRestorationManager = new ChunkRestorationManager(); + arenaManager = new ArenaManager(); + chunkManager = new ChunkManager(); + kitManager = new KitManager(); + matchManager = new MatchManager(); + hotbarItem = new HotbarItem(); + matchDetailSnapshot = new MatchDetailSnapshot(); + duelMenu = new DuelMenu(); + timerManager = new TimerManager(this); + partyMenu = new PartyMenu(); + partyManager = new PartyManager(); + partyQueueJoinMenu = new PartyQueueJoinMenu(); + profileManager = new ProfileManager(); + queue = new Queue(); + eventManager = new EventManager(); + hostMenu = new HostMenu(); + staffMode = new StaffMode(); + tournamentManager = new TournamentManager(); + tournamentHostMenu = new TournamentHostMenu(); + leaderboardManager = new LeaderboardManager(this); + queueMenu = new QueueMenu(); + generalSettingMenu = new GeneralSettingMenu(); + kitEditorMenu = new KitEditorMenu(); + editorManager = new EditorManager(); + voteManager = new VoteManager(this); + statsMenu = new StatsMenu(); + effectRestorer = new EffectRestorer(); + hcfManager = new HCFManager(); + hologramManager = new HologramManager(this); + + if (this.timerManager.getTimer(EnderpearlTimer.class) == null) this.timerManager.registerTimer(new EnderpearlTimer()); + + List listeners = Arrays.asList( + new EntityListener(), + new ProfileListener(), + new WorldListener(), + new UIListener(), + new ButtonListener(), + new MatchStartListener(), + new MatchEndListener(), + new PotionMatchListener(), + new MatchDurationLimitListener(), + new MatchRodListener(), + new TabCompleteListener(), + new ProfileOptionsListeners(), + new InventoryListener(), + //new FreezeListener(), + new PlayerTabCompleteFix(), + new KitEditorError32Listener(), + new SwordBlockDetector(), + new ArenaPlayerChunkLimiter(this), + new MovementListener(this), + new BowBoostingListener(), + new HCFMatchListener(), + new HCFClassListener(hcfManager), + new Bard(), new Archer() + ); + + for (Listener listener : listeners) { + getServer().getPluginManager().registerEvents(listener, this); + } + + // register commands + new SetSpawnCommand(); + new SetEditorSpawnCommand(); + + // kit related + new KitManageCommand(); + new KitsCommand(); + + // arena related + new ArenaCommand(); + new ArenaChunkCommands(); + + new InvCommand(); + new FlyCommand(); + + new DuelCommand(); + new AcceptCommand(); + new SpectateCommand(); + + // party related + new PartyInviteCommand(); + new PartyAcceptCommand(); + new PartyHelpCommand(); + new PartyCreateCommand(); + new PartyLeaveCommand(); + new PartyOpenCommand(); + new PartyInfoCommand(); + new PartyListCommand(); + new PartyJoinCommand(); + new PartyKickCommand(); + new PartyLimitCommand(); + + new EventManagerCommand(); + new HostCommand(); + new HostEventCommand(); + new JoinEventCommand(); + new SetEventSpawnCommand(); + new LeaveEventCommand(); + + new OptionsCommand(); + + new DayCommand(); + new NightCommand(); + new SunsetCommand(); + + new ResetLeaderboardsCommand(); + new ResetStatsCommand(); + new SetStatsCommand(); + + // Staff Mode + new StaffModeCommand(); + new FollowCommand(); + new CancelMatchCommand(); + new OngoingMatchesCommand(); + + // Match history + new MatchHistoryCommand(); + + // Practice Panel stuff + new DebugBlockedCommands(); + new ForceChunkSaveCommand(); + new ForceGlobalEloUpdateCommand(); + new ForceQueueCommand(); + new GlobalEloDebugCommand(); + new GlobalQueueDebugCommand(); + new GotoEventCommand(); + new GotoEventCommand(); + new PartyDebugCommand(); + new PlayerStateDebugCommand(); + new SafeStopCommand(); + new SetMatchesPlayedCommand(); + + new TournamentCommand(); + + new PlayAgainCommand(); + + new RateCommand(); + new ArenaStatsCommand(); + + new StatsCommand(); + + // register schedulers + dataLoaderWorkerRunnable = new DataLoaderWorkerRunnable(); + Thread thread = new Thread(dataLoaderWorkerRunnable); + thread.setName("[Practice] Data Loader Worker"); + thread.start(); + + getServer().getScheduler().runTaskTimerAsynchronously(this, new ProfileSaveDataTask(), 20L * 60L * 5L, 20L * 60L * 5L); + getServer().getScheduler().runTaskTimerAsynchronously(this, new MenuUpdateTask(), 5L, 5L); + getServer().getScheduler().runTaskTimerAsynchronously(this, new ExpBarTask(), 2L, 2L); + getServer().getScheduler().runTaskTimerAsynchronously(this, () -> { + getLeaderboardManager().updateLeaderboards(); + }, 20L, getLeaderboardUpdateTime()); + + + getServer().getScheduler().runTaskTimerAsynchronously(this, new NPCRunnable(this), 300L, 300L); + + new PracticeCache().start(); + } + + @Override + public void onDisable() { + for (Profile profile : profileManager.getAllData()) { + profileManager.saveData(profile); + } + + for (Map.Entry entry : matchManager.getMatches().entrySet()) { + Match match = entry.getValue(); + if (match.getKit().isBuild() || match.getKit().isSpleef()) { + ChunkRestorationManager.getIChunkRestoration().reset(match.getStandaloneArena()); + } + } + + for (Entity entity : this.getServer().getWorld("world").getEntities()) { + if (entity.getType() == EntityType.DROPPED_ITEM) { + entity.remove(); + } + } + + for (Chunk chunk : this.getServer().getWorld("world").getLoadedChunks()) { + chunk.unload(true); + } + + getServer().getConsoleSender().sendMessage(CC.translate("&8[&6Practice&8] &cUnloading chunks...")); + + this.arenaManager.saveArenas(); + this.kitManager.saveKits(); + this.customLocationManager.saveConfig(); + this.practiceDatabase.getClient().close(); + } + + private void removeCrafting(Material material) { + Iterator iterator = getServer().recipeIterator(); + while (iterator.hasNext()) { + Recipe recipe = iterator.next(); + if (recipe != null && recipe.getResult().getType() == material) { + iterator.remove(); + } + } + } + + private void disableLoggers() { + Logger.getLogger("org.mongodb.driver.connection").setLevel(Level.OFF); + Logger.getLogger("org.mongodb.driver.cluster").setLevel(Level.OFF); + } + + /** + * Runs the given runnable asynchronously + * This method is usually used in mongo and + * other non-bukkit related tasks + * + * @param runnable {@link Runnable} the runnable + */ + public void submitToThread(Runnable runnable) { + ForkJoinPool.commonPool().execute(runnable); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/PracticeCache.java b/Practice/src/main/java/me/devkevin/practice/PracticeCache.java new file mode 100644 index 0000000..5787183 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/PracticeCache.java @@ -0,0 +1,77 @@ +package me.devkevin.practice; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import me.devkevin.practice.profile.Profile; +import org.bukkit.Bukkit; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PracticeCache extends Thread { + + @Getter private static PracticeCache instance; + + private int onlinePlayers; + private int queueingPlayers; + private int playingPlayers; + private int onlineStaffModePlayers; + + private int unrankedSoloPlayers; + private int rankedSoloPlayers; + + public PracticeCache() { + instance = this; + } + + @Override + public void run() { + while (true) { + onlinePlayers = Bukkit.getOnlinePlayers().size(); + int queueingPlayers = 0; + int playingPlayers = 0; + int onlineStaffModePlayers = 0; + int unrankedSoloPlayers = 0; + int rankedSoloPlayers = 0; + + for (Profile profile : Practice.getInstance().getProfileManager().getAllData()) { + if (profile.isInQueue()) { + queueingPlayers++; + } + + if (profile.isFighting()) { + playingPlayers++; + } + + if (profile.isInStaffMode()) { + onlineStaffModePlayers++; + } + + if (profile.isInSoloUnranked()) { + unrankedSoloPlayers++; + } + + if (profile.isInSoloRanked()) { + rankedSoloPlayers++; + } + } + + this.queueingPlayers = queueingPlayers; + this.playingPlayers = playingPlayers; + this.onlineStaffModePlayers = onlineStaffModePlayers; + this.unrankedSoloPlayers = unrankedSoloPlayers; + this.rankedSoloPlayers = rankedSoloPlayers; + + try { + Thread.sleep(500L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/PracticeLang.java b/Practice/src/main/java/me/devkevin/practice/PracticeLang.java new file mode 100644 index 0000000..f17e01e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/PracticeLang.java @@ -0,0 +1,69 @@ +package me.devkevin.practice; + +import club.inverted.chatcolor.CC; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.bukkit.ChatColor; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PracticeLang { + + public static final String line = CC.GRAY + CC.STRIKETHROUGH + StringUtils.repeat("-", 30); + + // kit related + public static final String NO_KIT_EXIST = CC.RED + "That kit doesn't exist."; + public static final String NO_ARENA_EXIST = CC.RED + "An arena with that name does not exist."; + public static final String ALREADY_KIT_EXIST = CC.RED + "That kit is already exist."; + public static final String KIT_CREATED = CC.YELLOW + " kit has been created."; + public static final String KIT_DELETED = CC.RED + " kit has been deleted."; + public static final String KIT_ENABLE = CC.GREEN + " kit has been enabled."; + public static final String KIT_DISABLE = CC.RED + " kit has been disabled."; + public static final String SUMO_KIT_ENABLE = CC.GREEN + " sumo kit has been enabled."; + public static final String SUMO_KIT_DISABLE = CC.RED + " sumo kit has been disabled."; + public static final String BUILD_KIT_ENABLE = CC.GREEN + " build mode has been enabled."; + public static final String BUILD_KIT_DISABLE = CC.RED + " build mode has been disabled."; + public static final String RANKED_KIT_ENABLE = CC.GREEN + "Ranked mode has been enabled for "; + public static final String RANKED_KIT_DISABLE = CC.RED + "Ranked mode has been disabled for "; + public static final String ICON_KIT = CC.YELLOW + "You has been set the icon of "; + public static final String NO_ICON_KIT = CC.YELLOW + "You must be holding an item to set the kit icon"; + public static final String KIT_SETINV = CC.YELLOW + "You has been update the inv of "; + public static final String KIT_GETINV = CC.YELLOW + "You has been retrieved kit contents of "; + public static final String NO_DROP_SLOT_1 = CC.RED + "You can't drop that while you're holding it in slot 1."; + public static final String INV_NOT_FOUND = CC.RED + "Cannot find the request inventory. Maybe it expired?"; + public static final String NO_PERMISSION = CC.RED + "You don't have permission to execute that command."; + public static final String PLAYER_NOT_FOUND = ChatColor.RED + "%s not found."; + public static final String ERROR_STATE = ChatColor.RED + "You can't execute that command in your current state."; + public static final String VERTICAL_BAR = StringEscapeUtils.unescapeJava("\u2503"); + public static final String HEART = StringEscapeUtils.unescapeJava("\u2764"); + + /** + * `&7&l» ` - Arrow used on the left side of item display names + * Named left arrow due to its usage on the left side of items, despite the fact + * the arrow is actually pointing to the right. + * @see me.devkevin.practice.profile.hotbar.HotbarItem usage + */ + public static final String LEFT_ARROW = ChatColor.BLUE.toString() + "» "; + + /** + * ` &7&l«` - Arrow used on the right side of item display names + * Named right arrow due to its usage on the right side of items, despite the fact + * the arrow is actually pointing to the left. + * @see me.devkevin.practice.profile.hotbar.HotbarItem usage + */ + public static final String RIGHT_ARROW = ChatColor.BLUE.toString() + " «"; + + + public static final String[] blockedCommands = new String[] { + "/gamemode creative", + "/gamemode c", + "/gamemode 1", + "/gmc", + "/kill", + "/disguise", + "/undisguise" + }; +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/Arena.java b/Practice/src/main/java/me/devkevin/practice/arena/Arena.java new file mode 100644 index 0000000..8f25b8b --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/Arena.java @@ -0,0 +1,57 @@ +package me.devkevin.practice.arena; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.location.CustomLocation; + +import java.util.List; + +@Getter +@Setter +@AllArgsConstructor +@RequiredArgsConstructor +public class Arena { + + @Getter private final String name; + + private List standaloneArenas; + private List availableArenas; + + private String icon; + private int iconData; + + private CustomLocation a; + private CustomLocation b; + + private CustomLocation min; + private CustomLocation max; + + private int buildMax; + private int deadZone; + private int portalProt; + + private boolean enabled; + + @Setter private boolean arenaSelected; + @Setter private Arena selectedArena; + + //private String author = "Inverted Build Team."; + + public StandaloneArena getAvailableArena() { + StandaloneArena arena = this.availableArenas.get(0); + this.availableArenas.remove(0); + + return arena; + } + + public void addStandaloneArena(StandaloneArena arena) { + this.standaloneArenas.add(arena); + } + + public void addAvailableArena(StandaloneArena arena) { + this.availableArenas.add(arena); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/data/NekoChunk.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/data/NekoChunk.java new file mode 100644 index 0000000..975ff11 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/data/NekoChunk.java @@ -0,0 +1,15 @@ +package me.devkevin.practice.arena.chunk.data; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter @Setter @AllArgsConstructor +public class NekoChunk { + private int x,z; +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/data/NekoChunkData.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/data/NekoChunkData.java new file mode 100644 index 0000000..7a31fc9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/data/NekoChunkData.java @@ -0,0 +1,27 @@ +package me.devkevin.practice.arena.chunk.data; + +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_8_R3.ChunkSection; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter @Setter +public class NekoChunkData { + public Map chunks = new ConcurrentHashMap<>(); + + public ChunkSection[] getNyaChunk(int x, int z) { + for (Map.Entry chunksFromMap : chunks.entrySet()) { + if (chunksFromMap.getKey().getX() == x && chunksFromMap.getKey().getZ() == z) { + return chunksFromMap.getValue(); + } + } + return null; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/listener/ArenaPlayerChunkLimiter.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/listener/ArenaPlayerChunkLimiter.java new file mode 100644 index 0000000..b2bea54 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/listener/ArenaPlayerChunkLimiter.java @@ -0,0 +1,89 @@ +package me.devkevin.practice.arena.chunk.listener; + +import me.devkevin.practice.Practice; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.event.Cancellable; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntitySpawnEvent; +import org.bukkit.event.hanging.HangingPlaceEvent; + +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright 18/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ArenaPlayerChunkLimiter implements Listener { + + // The amount of entities that can be in a chunk at once. + // Entity Types: https://hub.spigotmc.org/javadocs/spigot/org/bukkit/entity/EntityType.html + + private final Map limits = new HashMap<>(); + + public ArenaPlayerChunkLimiter(Practice plugin) { + for (EntityType type : EntityType.values()) { + // If the entity cannot be spawned in the world, continue + if (!type.isSpawnable()) { + continue; + } + int limit = Integer.getInteger(type.getName(), -1); + + // If there is no limit for the Entity type, continue + if (limit == -1) { + continue; + } + + // Settings the limit for the Entity type + limits.put(type, limit); + plugin.getLogger().info(type.name() + " Limit: " + limit); + } + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onEntitySpawn(EntitySpawnEvent event) { + this.handleEntitySpawn(event, event.getEntityType(), event.getLocation().getChunk()); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onHangingSpawn(HangingPlaceEvent event) { + this.handleEntitySpawn(event, event.getEntity().getType(), event.getBlock().getChunk()); + } + + /** + * Handle entity spawning for the given {@link Cancellable} event with the given + * {@link EntityType} at the given {@link Chunk}. + * + * @param event the spawn entity event + * @param entityType the type of the entity spawned + * @param chunk the chunk the entity was spawned + */ + private void handleEntitySpawn(Cancellable event, EntityType entityType, Chunk chunk) { + if (event.isCancelled()) { // If another plugin cancels this event, return + return; + } + Integer limit = limits.get(entityType); + if (limit == null) { // If the spawned entity type has no limit, return + return; + } + // Loop through all the entities in the given chunk and count the amount + // of entities with the same entity type as the one provided + int entities = 0; + for (Entity chunkEntity : chunk.getEntities()) { + if (chunkEntity.getType() == entityType) { + entities++; + } + } + // If the limit has been reached for this chunk, cancel the event + if (entities > limit) { + event.setCancelled(true); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/manager/ChunkManager.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/manager/ChunkManager.java new file mode 100644 index 0000000..23b4cef --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/manager/ChunkManager.java @@ -0,0 +1,133 @@ +package me.devkevin.practice.arena.chunk.manager; + +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.location.CustomLocation; +import org.bukkit.Chunk; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ChunkManager { + private final Practice plugin = Practice.getInstance(); + + @Getter private boolean chunksLoaded; + + public ChunkManager() { + new BukkitRunnable() { + @Override + public void run() { + loadChunks(); + } + }.runTaskLater(this.plugin, 5L); + } + + private void loadChunks() { + plugin.getLogger().info("Starting chunk loading task!"); + + CustomLocation spawnMin = plugin.getCustomLocationManager().getSpawnMin(); + CustomLocation spawnMax = plugin.getCustomLocationManager().getSpawnMax(); + + if (spawnMin != null && spawnMax != null) { + int spawnMinX = spawnMin.toBukkitLocation().getBlockX() >> 4; + int spawnMinZ = spawnMin.toBukkitLocation().getBlockZ() >> 4; + int spawnMaxX = spawnMax.toBukkitLocation().getBlockX() >> 4; + int spawnMaxZ = spawnMax.toBukkitLocation().getBlockZ() >> 4; + + if (spawnMinX > spawnMaxX) { + int lastSpawnMinX = spawnMinX; + spawnMinX = spawnMaxX; + spawnMaxX = lastSpawnMinX; + } + + if (spawnMinZ > spawnMaxZ) { + int lastSpawnMinZ = spawnMinZ; + spawnMinZ = spawnMaxZ; + spawnMaxZ = lastSpawnMinZ; + } + + for (int x = spawnMinX; x <= spawnMaxX; x++) { + for (int z = spawnMinZ; z <= spawnMaxZ; z++) { + Chunk chunk = spawnMin.toBukkitWorld().getChunkAt(x, z); + if (!chunk.isLoaded()) { + chunk.load(); + } + } + } + } else { + plugin.getLogger().info(" "); + plugin.getLogger().info(" ERROR ERROR ERROR "); + plugin.getLogger().info("Please make sure you set the Spawn Min & Max Locations!"); + plugin.getLogger().info("If you did not, remove 'spawnLocation' from settings.yml"); + plugin.getLogger().info(" ERROR ERROR ERROR "); + plugin.getLogger().info(" "); + } + + for (Arena arena : plugin.getArenaManager().getArenas().values()) { + if (!arena.isEnabled()) { + continue; + } + int arenaMinX = arena.getMin().toBukkitLocation().getBlockX() >> 4; + int arenaMinZ = arena.getMin().toBukkitLocation().getBlockZ() >> 4; + int arenaMaxX = arena.getMax().toBukkitLocation().getBlockX() >> 4; + int arenaMaxZ = arena.getMax().toBukkitLocation().getBlockZ() >> 4; + + if (arenaMinX > arenaMaxX) { + int lastArenaMinX = arenaMinX; + arenaMinX = arenaMaxX; + arenaMaxX = lastArenaMinX; + } + + if (arenaMinZ > arenaMaxZ) { + int lastArenaMinZ = arenaMinZ; + arenaMinZ = arenaMaxZ; + arenaMaxZ = lastArenaMinZ; + } + + for (int x = arenaMinX; x <= arenaMaxX; x++) { + for (int z = arenaMinZ; z <= arenaMaxZ; z++) { + Chunk chunk = arena.getMin().toBukkitWorld().getChunkAt(x, z); + if (!chunk.isLoaded()) { + chunk.load(); + } + } + } + + for (StandaloneArena saArena : arena.getStandaloneArenas()) { + arenaMinX = saArena.getMin().toBukkitLocation().getBlockX() >> 4; + arenaMinZ = saArena.getMin().toBukkitLocation().getBlockZ() >> 4; + arenaMaxX = saArena.getMax().toBukkitLocation().getBlockX() >> 4; + arenaMaxZ = saArena.getMax().toBukkitLocation().getBlockZ() >> 4; + + if (arenaMinX > arenaMaxX) { + int lastArenaMinX = arenaMinX; + arenaMinX = arenaMaxX; + arenaMaxX = lastArenaMinX; + } + + if (arenaMinZ > arenaMaxZ) { + int lastArenaMinZ = arenaMinZ; + arenaMinZ = arenaMaxZ; + arenaMaxZ = lastArenaMinZ; + } + + for (int x = arenaMinX; x <= arenaMaxX; x++) { + for (int z = arenaMinZ; z <= arenaMaxZ; z++) { + Chunk chunk = saArena.getMin().toBukkitWorld().getChunkAt(x, z); + if (!chunk.isLoaded()) { + chunk.load(); + } + } + } + } + } + + plugin.getLogger().info("Finished loading all the chunks!"); + this.chunksLoaded = true; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/manager/ChunkRestorationManager.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/manager/ChunkRestorationManager.java new file mode 100644 index 0000000..15743a5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/manager/ChunkRestorationManager.java @@ -0,0 +1,37 @@ +package me.devkevin.practice.arena.chunk.manager; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.arena.chunk.data.NekoChunkData; +import me.devkevin.practice.arena.chunk.reset.INekoChunkReset; +import me.devkevin.practice.arena.chunk.reset.impl.VanillaNekoChunkReset; +import me.devkevin.practice.arena.chunk.restoration.IChunkRestoration; +import me.devkevin.practice.arena.chunk.restoration.impl.PracticeChunkRestoration; +import me.devkevin.practice.arena.cuboid.Cuboid; +import me.devkevin.practice.arena.standalone.StandaloneArena; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class ChunkRestorationManager { + @Getter @Setter private static INekoChunkReset iNekoChunkReset; + @Getter @Setter private static IChunkRestoration iChunkRestoration; + + private final Map chunks = new ConcurrentHashMap<>(); + private final Map eventMapChunks = new ConcurrentHashMap<>(); + + public ChunkRestorationManager() { + if (iNekoChunkReset == null) { // Let the other plugins create an INekoReset before we load ours. + iNekoChunkReset = new VanillaNekoChunkReset(); + } + if (iChunkRestoration == null) { // Let the other plugins create an IChunkRestoration before we load ours. + iChunkRestoration = new PracticeChunkRestoration(iNekoChunkReset, this); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/reset/INekoChunkReset.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/reset/INekoChunkReset.java new file mode 100644 index 0000000..1c91140 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/reset/INekoChunkReset.java @@ -0,0 +1,18 @@ +package me.devkevin.practice.arena.chunk.reset; + +import net.minecraft.server.v1_8_R3.*; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public interface INekoChunkReset { + void setSections(Chunk nmsChunk, ChunkSection[] sections); + ChunkSection[] cloneSections(ChunkSection[] sections); + ChunkSection cloneSection(ChunkSection section); + + default NibbleArray cloneNibbleArray(NibbleArray nibbleArray) { + return new NibbleArray(nibbleArray.a().clone()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/reset/impl/VanillaNekoChunkReset.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/reset/impl/VanillaNekoChunkReset.java new file mode 100644 index 0000000..26646e8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/reset/impl/VanillaNekoChunkReset.java @@ -0,0 +1,77 @@ +package me.devkevin.practice.arena.chunk.reset.impl; + +import lombok.SneakyThrows; +import me.devkevin.practice.arena.chunk.reset.INekoChunkReset; +import net.minecraft.server.v1_8_R3.Chunk; +import net.minecraft.server.v1_8_R3.ChunkSection; +import net.minecraft.server.v1_8_R3.NibbleArray; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class VanillaNekoChunkReset implements INekoChunkReset { + @SneakyThrows + public void setSections(Chunk nmsChunk, ChunkSection[] sections) { + setField("sections", nmsChunk, sections); + + nmsChunk.getWorld().getWorld().refreshChunk(nmsChunk.locX, nmsChunk.locZ); + } + + public ChunkSection[] cloneSections(ChunkSection[] sections) { + ChunkSection[] newSections = new ChunkSection[sections.length]; + + for (int i = 0; i < sections.length; ++i) { + if (sections[i] != null) { + newSections[i] = cloneSection(sections[i]); + } + } + + return newSections; + } + + @SneakyThrows + public ChunkSection cloneSection(ChunkSection chunkSection) { + ChunkSection section = new ChunkSection(chunkSection.getYPosition(), chunkSection.getSkyLightArray() != null); + + setField("nonEmptyBlockCount", section, getFromField("nonEmptyBlockCount", chunkSection)); + setField("tickingBlockCount", section, getFromField("tickingBlockCount", chunkSection)); + setField("blockIds", section, chunkSection.getIdArray().clone()); + if (chunkSection.getEmittedLightArray() != null) { + section.a(cloneNibbleArray(chunkSection.getEmittedLightArray())); + } + + if (chunkSection.getSkyLightArray() != null) { + section.b(cloneNibbleArray(chunkSection.getSkyLightArray())); + } + + return section; + } + + public NibbleArray cloneNibbleArray(NibbleArray nibbleArray) { + return new NibbleArray(nibbleArray.a().clone()); + } + + @SneakyThrows + public void setField(String fieldName, Object clazz, Object value) { + Field field = clazz.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + + Field modifiers = Field.class.getDeclaredField("modifiers"); + modifiers.setAccessible(true); + modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); + + field.set(clazz, value); + } + + public Object getFromField(String fieldName, Object clazz) throws IllegalAccessException, NoSuchFieldException { + Field field = clazz.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + + return field.get(clazz); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/restoration/IChunkRestoration.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/restoration/IChunkRestoration.java new file mode 100644 index 0000000..2d43b03 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/restoration/IChunkRestoration.java @@ -0,0 +1,16 @@ +package me.devkevin.practice.arena.chunk.restoration; + +import me.devkevin.practice.arena.cuboid.Cuboid; +import me.devkevin.practice.arena.standalone.StandaloneArena; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public interface IChunkRestoration { + void copy(StandaloneArena arena); + void reset(StandaloneArena arena); + void copy(Cuboid cuboid); + void reset(Cuboid cuboid); +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/chunk/restoration/impl/PracticeChunkRestoration.java b/Practice/src/main/java/me/devkevin/practice/arena/chunk/restoration/impl/PracticeChunkRestoration.java new file mode 100644 index 0000000..ab42c44 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/chunk/restoration/impl/PracticeChunkRestoration.java @@ -0,0 +1,85 @@ +package me.devkevin.practice.arena.chunk.restoration.impl; + +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.arena.chunk.data.NekoChunk; +import me.devkevin.practice.arena.chunk.data.NekoChunkData; +import me.devkevin.practice.arena.chunk.manager.ChunkRestorationManager; +import me.devkevin.practice.arena.chunk.reset.INekoChunkReset; +import me.devkevin.practice.arena.chunk.restoration.IChunkRestoration; +import me.devkevin.practice.arena.cuboid.Cuboid; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import net.minecraft.server.v1_8_R3.ChunkSection; +import org.bukkit.craftbukkit.v1_8_R3.CraftChunk; + +/** + * Copyright 19/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@RequiredArgsConstructor +public class PracticeChunkRestoration implements IChunkRestoration { + private final INekoChunkReset iNekoChunkReset; + private final ChunkRestorationManager chunkRestorationManager; + + @Override + public void copy(StandaloneArena arena) { + Cuboid cuboid = new Cuboid(arena.getMin().toBukkitLocation(), arena.getMax().toBukkitLocation()); + + long startTime = System.currentTimeMillis(); + + NekoChunkData nekoChunkData = new NekoChunkData(); + cuboid.getChunks().forEach(chunk -> { + chunk.load(); + net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + ChunkSection[] nmsSections = iNekoChunkReset.cloneSections(nmsChunk.getSections()); + nekoChunkData.chunks.put(new NekoChunk(chunk.getX(), chunk.getZ()), iNekoChunkReset.cloneSections(nmsSections)); + }); + chunkRestorationManager.getChunks().put(arena, nekoChunkData); + } + + @Override + public void reset(StandaloneArena arena) { + long startTime = System.currentTimeMillis(); + + Cuboid cuboid = new Cuboid(arena.getMin().toBukkitLocation(), arena.getMax().toBukkitLocation()); + resetCuboid(cuboid, chunkRestorationManager.getChunks().get(arena)); + + System.out.println("Chunks have been reset! (took " + (System.currentTimeMillis() - startTime) + "ms)"); + } + + @Override + public void copy(Cuboid cuboid) { + long startTime = System.currentTimeMillis(); + + NekoChunkData nekoChunkData = new NekoChunkData(); + cuboid.getChunks().forEach(chunk -> { + chunk.load(); + net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + ChunkSection[] nmsSections = iNekoChunkReset.cloneSections(nmsChunk.getSections()); + nekoChunkData.chunks.put(new NekoChunk(chunk.getX(), chunk.getZ()), iNekoChunkReset.cloneSections(nmsSections)); + }); + chunkRestorationManager.getEventMapChunks().put(cuboid, nekoChunkData); + + System.out.println("Chunks copied for SkyWars Event! (" + (System.currentTimeMillis() - startTime) + "ms)"); + } + + @Override + public void reset(Cuboid cuboid) { + long startTime = System.currentTimeMillis(); + resetCuboid(cuboid, chunkRestorationManager.getEventMapChunks().get(cuboid)); + + System.out.println("Chunks have been reset for SkyWars Event! (took " + (System.currentTimeMillis() - startTime) + "ms)"); + } + + private void resetCuboid(Cuboid cuboid, NekoChunkData chunkData) { + cuboid.getChunks().forEach(chunk -> { + try { + chunk.load(); + iNekoChunkReset.setSections(((CraftChunk) chunk).getHandle(), iNekoChunkReset.cloneSections(chunkData.getNyaChunk(chunk.getX(), chunk.getZ()))); + chunk.getWorld().refreshChunk(chunk.getX(), chunk.getZ()); // let the mf server know that you've updated the chunk. + } catch (Exception e) { + e.printStackTrace(); + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/command/ArenaChunkCommands.java b/Practice/src/main/java/me/devkevin/practice/arena/command/ArenaChunkCommands.java new file mode 100644 index 0000000..f20ac8a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/command/ArenaChunkCommands.java @@ -0,0 +1,74 @@ +package me.devkevin.practice.arena.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.chunk.manager.ChunkRestorationManager; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 22/10/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ArenaChunkCommands extends PracticeCommand { + + private final String NO_ARENA = CC.RED + "That arena doesn't exist!"; + + private void getHelpCommand(Player player) { + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate(" &8- &fChunks - Command Help")); + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&7 • &b/chunk save ")); + player.sendMessage(CC.translate("&7 • &b/chunk reset ")); + player.sendMessage(CC.CHAT_BAR); + } + + @Override @Command(name = "chunk", permission = Rank.MANAGER) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + getHelpCommand(player); + return; + } + + Arena arena = getPlugin().getArenaManager().getArena(args[1]); + int copyNumber = Integer.parseInt(args[2]); + + switch (args[0].toLowerCase()) { + case "save": + if (arena != null) { + if (arena.getStandaloneArenas().get(copyNumber) == null) { + player.sendMessage(CC.RED + "That copy doesn't exist!"); + return; + } + + ChunkRestorationManager.getIChunkRestoration().copy(arena.getStandaloneArenas().get(copyNumber)); + player.sendMessage(CC.GREEN + "Successfully saved standalone arena chunks for " + CC.YELLOW + arena.getName() + CC.GREEN + "#" + copyNumber + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "reset": + if (arena != null) { + if (arena.getStandaloneArenas().get(copyNumber) == null) { + player.sendMessage(CC.RED + "That copy doesn't exist!"); + return; + } + + ChunkRestorationManager.getIChunkRestoration().reset(arena.getStandaloneArenas().get(copyNumber)); + player.sendMessage(CC.GREEN + "Successfully reset standalone arena chunks for " + CC.YELLOW + arena.getName() + CC.GREEN + "#" + copyNumber + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + default: + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/command/ArenaCommand.java b/Practice/src/main/java/me/devkevin/practice/arena/command/ArenaCommand.java new file mode 100644 index 0000000..7dbd958 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/command/ArenaCommand.java @@ -0,0 +1,266 @@ +package me.devkevin.practice.arena.command; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.generate.ArenaCommandRunnable; +import me.devkevin.practice.arena.generate.ArenaCopyRemovalRunnable; +import me.devkevin.practice.arena.menu.ArenaManagerMenu; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.apache.commons.lang.StringUtils; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ArenaCommand extends PracticeCommand { + + private final String NO_ARENA = ChatColor.RED + "That arena doesn't exist!"; + private final Practice plugin = Practice.getInstance(); + + @Override @Command(name = "arena", permission = Rank.MANAGER, inGameOnly = true, description = "Arenas command.", usage = "&cUsage: /arena [args]") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + + List arenamsg = Lists.newArrayList(); + + arenamsg.add(CC.CHAT_BAR); + arenamsg.add("&4&oArena Setup Help"); + arenamsg.add(CC.CHAT_BAR); + arenamsg.add("&c/arena create &7- &fCreates arena"); + arenamsg.add("&c/arena delete &7- &fDeletes arena"); + arenamsg.add("&c/arena enable &7- &fEnables arena"); + arenamsg.add("&c/arena disable &7- &fDisables arena"); + arenamsg.add("&c/arena info &7- &fShows arena information"); + arenamsg.add("&c/arena icon &7- &fSet the arena icon"); + arenamsg.add("&c/arena a &7- &f1st Player Spawn (Team Blue) (Team ID: 1)"); + arenamsg.add("&c/arena b &7- &f2nd Player Spawn (Team Red) (Team ID: 0)"); + arenamsg.add("&c/arena min &7- &fLowest corner pos of arena"); + arenamsg.add("&c/arena max &7- &fHighest corner pos of arena"); + arenamsg.add("&c/arena buildMax &7- &fHighest build height of arena"); + arenamsg.add("&c/arena deadZone &7- &fLowest player alive pos of arena"); + arenamsg.add("&c/arena portalprot &7- &fPortal protection radius of arena"); + arenamsg.add(" "); + arenamsg.add("&c/arena list &7- &fShows all arenas"); + arenamsg.add("&c/arena save &7- &fSaves all arenas"); + arenamsg.add("&c/arena manage &7- &fOpens arena management menu"); + arenamsg.add("&c/arena generate &7- &fCreates copies"); + arenamsg.add(CC.CHAT_BAR); + + for (String message : arenamsg) { + player.sendMessage(CC.translate(message)); + } + return; + } + + if (args[0].equalsIgnoreCase("save")) { + this.plugin.getArenaManager().reloadArenas(); + player.sendMessage(ChatColor.GREEN + "Successfully saved and reloaded all arenas."); + return; + } + + if (args[0].equalsIgnoreCase("manage")) { + if (this.plugin.getArenaManager().getArenas().size() == 0) { + player.sendMessage(CC.translate("&cThere are no arenas.")); + return; + } + + new ArenaManagerMenu().openMenu(player); + return; + } + + if (args[0].equalsIgnoreCase("list")) { + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&4&lArenas List &7(&f" + plugin.getArenaManager().getArenas().size() + "&c in total&7)")); + player.sendMessage(CC.CHAT_BAR); + for (Arena arena : plugin.getArenaManager().getArenas().values()) { + player.sendMessage(CC.translate(" &9&l▸ &c" + arena.getName() + " &8[" + (arena.isEnabled() ? "&aEnabled" : "&cDisabled") + "&8]")); + } + player.sendMessage(CC.CHAT_BAR); + + return; + } + + if (args.length < 2) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Arena arena = this.plugin.getArenaManager().getArena(args[1]); + switch (args[0].toLowerCase()) { + case "create": + if (arena == null) { + this.plugin.getArenaManager().createArena(args[1]); + player.sendMessage(ChatColor.GREEN + "Successfully created arena " + args[1] + "."); + } else { + player.sendMessage(ChatColor.RED + "That arena already exists!"); + } + break; + case "delete": + if (arena != null) { + if (this.plugin.getArenaManager().getArena(args[1]).getStandaloneArenas().size() >= 1) { + int i = 0; + for (StandaloneArena copy : this.plugin.getArenaManager().getArena(args[1]).getStandaloneArenas()) { + new ArenaCopyRemovalRunnable(i, arena, copy).runTask(this.plugin); + i++; + } + } + + this.plugin.getArenaManager().deleteArena(args[1]); + player.sendMessage(ChatColor.GREEN + "Successfully deleted arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "icon": + if (arena != null) { + if (player.getItemInHand().getType() != Material.AIR) { + String icon = player.getItemInHand().getType().name(); + int iconData = player.getItemInHand().getDurability(); + arena.setIcon(icon); + arena.setIconData(iconData); + player.sendMessage(ChatColor.GREEN + "Successfully set icon for arena " + args[1] + "."); + } else { + player.sendMessage(ChatColor.RED + "You must be holding an item to set the arena icon!"); + } + } else { + player.sendMessage(NO_ARENA); + } + break; + case "a": + if (arena != null) { + Location location = player.getLocation(); + arena.setA(CustomLocation.fromBukkitLocation(location)); + player.sendMessage(ChatColor.GREEN + "Successfully set position A for arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "b": + if (arena != null) { + Location location = player.getLocation(); + arena.setB(CustomLocation.fromBukkitLocation(location)); + player.sendMessage(ChatColor.GREEN + "Successfully set position B for arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "min": + if (arena != null) { + arena.setMin(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(ChatColor.GREEN + "Successfully set minimum position for arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "max": + if (arena != null) { + arena.setMax(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(ChatColor.GREEN + "Successfully set maximum position for arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "buildmax": + if (arena != null) { + arena.setBuildMax(player.getLocation().getBlockY()); + player.sendMessage(ChatColor.GREEN + "Successfully set maximum buildable height position for arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "deadzone": + if (arena != null) { + arena.setDeadZone(player.getLocation().getBlockY()); + player.sendMessage(CC.translate("&aSuccessfully set deadzone location for arena '&l" + arena.getName() + "&a'!")); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "portalprot": + if (arena != null) { + arena.setPortalProt(Integer.parseInt(args[2])); + player.sendMessage(ChatColor.GREEN + "Successfully set portal protection radius for arena " + args[1] + " to " + Integer.parseInt(args[2]) + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "disable": + case "enable": + if (arena != null) { + arena.setEnabled(!arena.isEnabled()); + player.sendMessage(arena.isEnabled() ? ChatColor.GREEN + "Successfully enabled arena " + args[1] + "." : + ChatColor.RED + "Successfully disabled arena " + args[1] + "."); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "info": + if (arena != null) { + List kitsWhitelisted = new ArrayList<>(); + + for (Kit kit : plugin.getKitManager().getKits()) { + if (kit.getArenaWhiteList().contains(arena.getName())) { + kitsWhitelisted.add(kit.getName()); + } + } + + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&b&lArena Information")); + player.sendMessage(" "); + player.sendMessage(CC.translate(" &9&l▸ &fName: &c" + arena.getName())); + player.sendMessage(CC.translate(" &9&l▸ &fState: " + (arena.isEnabled() ? "&aEnabled" : "&cDisabled"))); + player.sendMessage(CC.translate(" &9&l▸ &fBuildMax: &c" + arena.getBuildMax())); + player.sendMessage(CC.translate(" &9&l▸ &fDeadZone: &c" + arena.getDeadZone())); + player.sendMessage(CC.translate(" &9&l▸ &fPortalProt Radius: &c" + arena.getPortalProt())); + player.sendMessage(CC.translate(" &9&l▸ &f1st Spawn: &c" + Math.round(arena.getA().getX()) + "&7, &c" + Math.round(arena.getA().getY()) + "&7, &c" + Math.round(arena.getA().getZ()))); + player.sendMessage(CC.translate(" &9&l▸ &f2nd Spawn: &c" + Math.round(arena.getB().getX()) + "&7, &c" + Math.round(arena.getB().getY()) + "&7, &c" + Math.round(arena.getB().getZ()))); + player.sendMessage(CC.translate(" &9&l▸ &fMin Location: &c" + Math.round(arena.getMin().getX()) + "&7, &c" + Math.round(arena.getMin().getY()) + "&7, &c" + Math.round(arena.getMin().getZ()))); + player.sendMessage(CC.translate(" &9&l▸ &fMax Location: &c" + Math.round(arena.getMax().getX()) + "&7, &c" + Math.round(arena.getMax().getY()) + "&7, &c" + Math.round(arena.getMax().getZ()))); + player.sendMessage(CC.translate(" &9&l▸ &fStandalone Arenas: &c" + arena.getStandaloneArenas().size())); + player.sendMessage(CC.translate(" &9&l▸ &fAvailable Arenas: &c" + (arena.getAvailableArenas().size() == 0 ? +1 : arena.getAvailableArenas().size()))); + player.sendMessage(" "); + player.sendMessage(CC.translate(" &9&l▸ &fKits with this Arena: &c" + kitsWhitelisted.size())); + player.sendMessage(CC.translate(" &4 » &c" + StringUtils.join(kitsWhitelisted, "&f, &c"))); + player.sendMessage(" "); + player.sendMessage(CC.CHAT_BAR); + } else { + player.sendMessage(NO_ARENA); + } + break; + case "generate": + if (args.length == 3) { + int arenas = Integer.parseInt(args[2]); + + this.plugin.getServer().getScheduler().runTask(this.plugin, new ArenaCommandRunnable(this.plugin, arena, arenas)); + this.plugin.getArenaManager().setGeneratingArenaRunnable(this.plugin.getArenaManager().getGeneratingArenaRunnable() + 1); + } else { + player.sendMessage(ChatColor.RED + "Usage: /arena generate "); + } + break; + default: + player.sendMessage(CC.translate(command.getCommand().getUsage())); + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/cuboid/Cuboid.java b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/Cuboid.java new file mode 100644 index 0000000..61e15eb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/Cuboid.java @@ -0,0 +1,507 @@ +package me.devkevin.practice.arena.cuboid; + +import com.google.common.base.Preconditions; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class Cuboid implements Iterable, Cloneable, ConfigurationSerializable { + + private String worldName; + private int x1; + private int y1; + private int z1; + private int x2; + private int y2; + private int z2; + + public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this(((World) Preconditions.checkNotNull((Object) world)).getName(), x1, y1, z1, x2, y2, z2); + } + + private Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = worldName; + this.x1 = Math.min(x1, x2); + this.y1 = Math.min(y1, y2); + this.z1 = Math.min(z1, z2); + this.x2 = Math.max(x1, x2); + this.y2 = Math.max(y1, y2); + this.z2 = Math.max(z1, z2); + } + + public Cuboid(Location first, Location second) { + this.worldName = first.getWorld().getName(); + this.x1 = Math.min(first.getBlockX(), second.getBlockX()); + this.y1 = Math.min(first.getBlockY(), second.getBlockY()); + this.z1 = Math.min(first.getBlockZ(), second.getBlockZ()); + this.x2 = Math.max(first.getBlockX(), second.getBlockX()); + this.y2 = Math.max(first.getBlockY(), second.getBlockY()); + this.z2 = Math.max(first.getBlockZ(), second.getBlockZ()); + } + + public Map serialize() { + LinkedHashMap map = new LinkedHashMap<>(); + map.put("worldName", this.worldName); + map.put("x1", this.x1); + map.put("y1", this.y1); + map.put("z1", this.z1); + map.put("x2", this.x2); + map.put("y2", this.y2); + map.put("z2", this.z2); + + return map; + } + + public boolean hasBothPositionsSet() { + return this.getMinimumPoint() != null && this.getMaximumPoint() != null; + } + + public int getMinimumX() { + return Math.min(this.x1, this.x2); + } + + public int getMinimumZ() { + return Math.min(this.z1, this.z2); + } + + public int getMaximumX() { + return Math.max(this.x1, this.x2); + } + + public int getMaximumZ() { + return Math.max(this.z1, this.z2); + } + + public List edges() { + return this.edges(-1, -1, -1, -1); + } + + public List edges(int fixedMinX, int fixedMaxX, int fixedMinZ, int fixedMaxZ) { + Vector v1 = this.getMinimumPoint().toVector(); + Vector v2 = this.getMaximumPoint().toVector(); + int minX = v1.getBlockX(); + int maxX = v2.getBlockX(); + int minZ = v1.getBlockZ(); + int maxZ = v2.getBlockZ(); + int capacity = (maxX - minX) * 4 + (maxZ - minZ) * 4; + + ArrayList result = new ArrayList<>(capacity += 4); + if (capacity <= 0) { + return result; + } + + int minY = v1.getBlockY(); + int maxY = v1.getBlockY(); + for (int x = minX; x <= maxX; ++x) { + result.add(new Vector(x, minY, minZ)); + result.add(new Vector(x, minY, maxZ)); + result.add(new Vector(x, maxY, minZ)); + result.add(new Vector(x, maxY, maxZ)); + } + for (int z = minZ; z <= maxZ; ++z) { + result.add(new Vector(minX, minY, z)); + result.add(new Vector(minX, maxY, z)); + result.add(new Vector(maxX, minY, z)); + result.add(new Vector(maxX, maxY, z)); + } + + return result; + } + + public Set getPlayers() { + HashSet players = new HashSet<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + if (!this.contains(player)) continue; + players.add(player); + } + + return players; + } + + public Location getLowerNE() { + return new Location(this.getWorld(), this.x1, this.y1, this.z1); + } + + public Location getUpperSW() { + return new Location(this.getWorld(), this.x2, this.y2, this.z2); + } + + public Location getCenter() { + int x1 = this.x2 + 1; + int y1 = this.y2 + 1; + int z1 = this.z2 + 1; + + return new Location(this.getWorld(), (double) this.x1 + (double) (x1 - this.x1) / 2.0, (double) this.y1 + (double) (y1 - this.y1) / 2.0, (double) this.z1 + (double) (z1 - this.z1) / 2.0); + } + + public World getWorld() { + return Bukkit.getWorld(this.worldName); + } + + public int getSizeX() { + return this.x2 - this.x1 + 1; + } + + public int getSizeY() { + return this.y2 - this.y1 + 1; + } + + public int getSizeZ() { + return this.z2 - this.z1 + 1; + } + + public Location[] getCornerLocations() { + Location[] result = new Location[8]; + Block[] cornerBlocks = this.getCornerBlocks(); + for (int i = 0; i < cornerBlocks.length; ++i) { + result[i] = cornerBlocks[i].getLocation(); + } + + return result; + } + + public Block[] getCornerBlocks() { + Block[] result = new Block[8]; + World world = this.getWorld(); + result[0] = world.getBlockAt(this.x1, this.y1, this.z1); + result[1] = world.getBlockAt(this.x1, this.y1, this.z2); + result[2] = world.getBlockAt(this.x1, this.y2, this.z1); + result[3] = world.getBlockAt(this.x1, this.y2, this.z2); + result[4] = world.getBlockAt(this.x2, this.y1, this.z1); + result[5] = world.getBlockAt(this.x2, this.y1, this.z2); + result[6] = world.getBlockAt(this.x2, this.y2, this.z1); + result[7] = world.getBlockAt(this.x2, this.y2, this.z2); + + return result; + } + + public Cuboid shift(CuboidDirection direction, int amount) throws IllegalArgumentException { + return this.expand(direction, amount).expand(direction.opposite(), -amount); + } + + public Cuboid inset(CuboidDirection direction, int amount) throws IllegalArgumentException { + return this.outset(direction, -amount); + } + + public Cuboid expand(CuboidDirection direction, int amount) throws IllegalArgumentException { + switch (direction) { + case NORTH: { + return new Cuboid(this.worldName, this.x1 - amount, this.y1, this.z1, this.x2, this.y2, this.z2); + } + case SOUTH: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2 + amount, this.y2, this.z2); + } + case EAST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1 - amount, this.x2, this.y2, this.z2); + } + case WEST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z2 + amount); + } + case DOWN: { + return new Cuboid(this.worldName, this.x1, this.y1 - amount, this.z1, this.x2, this.y2, this.z2); + } + case UP: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2 + amount, this.z2); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public Cuboid outset(CuboidDirection direction, int amount) throws IllegalArgumentException { + switch (direction) { + case HORIZONTAL: { + return this.expand(CuboidDirection.NORTH, amount).expand(CuboidDirection.SOUTH, amount).expand(CuboidDirection.EAST, amount).expand(CuboidDirection.WEST, amount); + } + case VERTICAL: { + return this.expand(CuboidDirection.DOWN, amount).expand(CuboidDirection.UP, amount); + } + case BOTH: { + return this.outset(CuboidDirection.HORIZONTAL, amount).outset(CuboidDirection.VERTICAL, amount); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public boolean contains(Cuboid cuboid) { + return this.contains(cuboid.getMinimumPoint()) || this.contains(cuboid.getMaximumPoint()); + } + + public boolean contains(Player player) { + return this.contains(player.getLocation()); + } + + public boolean contains(World world, int x, int z) { + return (world == null || this.getWorld().equals(world)) && x >= this.x1 && x <= this.x2 && z >= this.z1 && z <= this.z2; + } + + public boolean contains(int x, int y, int z) { + return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2 && z >= this.z1 && z <= this.z2; + } + + public boolean contains(Block block) { + return this.contains(block.getLocation()); + } + + public boolean contains(Location location) { + if (location == null || this.worldName == null) { + return false; + } + World world = location.getWorld(); + + return world != null && this.worldName.equals(location.getWorld().getName()) && this.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ()); + } + + public int getVolume() { + return this.getSizeX() * this.getSizeY() * this.getSizeZ(); + } + + public int getArea() { + Location min = this.getMinimumPoint(); + Location max = this.getMaximumPoint(); + + return (max.getBlockX() - min.getBlockX() + 1) * (max.getBlockZ() - min.getBlockZ() + 1); + } + + public byte getAverageLightLevel() { + long total = 0L; + int count = 0; + for (Block block : this) { + if (!block.isEmpty()) continue; + total += block.getLightLevel(); + ++count; + } + + return count > 0 ? (byte) (total / (long) count) : (byte) 0; + } + + public Location getMinimumPoint() { + return new Location(this.getWorld(), Math.min(this.x1, this.x2), Math.min(this.y1, this.y2), Math.min(this.z1, this.z2)); + } + + public Location getMaximumPoint() { + return new Location(this.getWorld(), Math.max(this.x1, this.x2), Math.max(this.y1, this.y2), Math.max(this.z1, this.z2)); + } + + public int getWidth() { + return this.getMaximumPoint().getBlockX() - this.getMinimumPoint().getBlockX(); + } + + public int getHeight() { + return this.getMaximumPoint().getBlockY() - this.getMinimumPoint().getBlockY(); + } + + public int getLength() { + return this.getMaximumPoint().getBlockZ() - this.getMinimumPoint().getBlockZ(); + } + + public Cuboid contract() { + return this.contract(CuboidDirection.DOWN).contract(CuboidDirection.SOUTH).contract(CuboidDirection.EAST).contract(CuboidDirection.UP).contract(CuboidDirection.NORTH).contract(CuboidDirection.WEST); + } + + public Cuboid contract(CuboidDirection direction) { + Cuboid face = this.getFace(direction.opposite()); + switch (direction) { + case DOWN: { + while (face.containsOnly(Material.AIR) && face.y1 > this.y1) { + face = face.shift(CuboidDirection.DOWN, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, face.y2, this.z2); + } + case UP: { + while (face.containsOnly(Material.AIR) && face.y2 < this.y2) { + face = face.shift(CuboidDirection.UP, 1); + } + return new Cuboid(this.worldName, this.x1, face.y1, this.z1, this.x2, this.y2, this.z2); + } + case NORTH: { + while (face.containsOnly(Material.AIR) && face.x1 > this.x1) { + face = face.shift(CuboidDirection.NORTH, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, face.x2, this.y2, this.z2); + } + case SOUTH: { + while (face.containsOnly(Material.AIR) && face.x2 < this.x2) { + face = face.shift(CuboidDirection.SOUTH, 1); + } + return new Cuboid(this.worldName, face.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + case EAST: { + while (face.containsOnly(Material.AIR) && face.z1 > this.z1) { + face = face.shift(CuboidDirection.EAST, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, face.z2); + } + case WEST: { + while (face.containsOnly(Material.AIR) && face.z2 < this.z2) { + face = face.shift(CuboidDirection.WEST, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, face.z1, this.x2, this.y2, this.z2); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public Cuboid getFace(CuboidDirection direction) { + switch (direction) { + case DOWN: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y1, this.z2); + } + case UP: { + return new Cuboid(this.worldName, this.x1, this.y2, this.z1, this.x2, this.y2, this.z2); + } + case NORTH: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x1, this.y2, this.z2); + } + case SOUTH: { + return new Cuboid(this.worldName, this.x2, this.y1, this.z1, this.x2, this.y2, this.z2); + } + case EAST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z1); + } + case WEST: { + return new Cuboid(this.worldName, this.x1, this.y1, this.z2, this.x2, this.y2, this.z2); + } + } + throw new IllegalArgumentException("Invalid direction " + direction); + } + + public boolean containsOnly(Material material) { + for (Block block : this) { + if (block.getType() == material) continue; + return false; + } + + return true; + } + + public Cuboid getBoundingCuboid(Cuboid other) { + if (other == null) { + return this; + } + int xMin = Math.min(this.x1, other.x1); + int yMin = Math.min(this.y1, other.y1); + int zMin = Math.min(this.z1, other.z1); + int xMax = Math.max(this.x2, other.x2); + int yMax = Math.max(this.y2, other.y2); + int zMax = Math.max(this.z2, other.z2); + + return new Cuboid(this.worldName, xMin, yMin, zMin, xMax, yMax, zMax); + } + + public Block getRelativeBlock(int x, int y, int z) { + return this.getWorld().getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + public Block getRelativeBlock(World world, int x, int y, int z) { + return world.getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + public List getChunks() { + World world = this.getWorld(); + int x1 = this.x1 & -16; + int x2 = this.x2 & -16; + int z1 = this.z1 & -16; + int z2 = this.z2 & -16; + + ArrayList result = new ArrayList<>(x2 - x1 + 16 + (z2 - z1) * 16); + for (int x3 = x1; x3 <= x2; x3 += 16) { + for (int z3 = z1; z3 <= z2; z3 += 16) { + result.add(world.getChunkAt(x3 >> 4, z3 >> 4)); + } + } + + return result; + } + + @Override + public Iterator iterator() { + return new CuboidBlockIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + public Iterator locationIterator() { + return new CuboidLocationIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + public Cuboid clone() { + try { + return (Cuboid) super.clone(); + } catch (CloneNotSupportedException ex) { + throw new RuntimeException("This could never happen", ex); + } + } + + public String toString() { + return "Cuboid: " + this.worldName + ',' + this.x1 + ',' + this.y1 + ',' + this.z1 + "=>" + this.x2 + ',' + this.y2 + ',' + this.z2; + } + + public String getWorldName() { + return this.worldName; + } + + public int getX1() { + return this.x1; + } + + public int getY1() { + return this.y1; + } + + public int getZ1() { + return this.z1; + } + + public int getX2() { + return this.x2; + } + + public int getY2() { + return this.y2; + } + + public int getZ2() { + return this.z2; + } + + public void setWorldName(String worldName) { + this.worldName = worldName; + } + + public void setX1(int x1) { + this.x1 = x1; + } + + public void setY1(int y1) { + this.y1 = y1; + } + + public void setZ1(int z1) { + this.z1 = z1; + } + + public void setX2(int x2) { + this.x2 = x2; + } + + public void setY2(int y2) { + this.y2 = y2; + } + + public void setZ2(int z2) { + this.z2 = z2; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidBlockIterator.java b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidBlockIterator.java new file mode 100644 index 0000000..acac3c3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidBlockIterator.java @@ -0,0 +1,97 @@ +package me.devkevin.practice.arena.cuboid; + +import org.bukkit.World; +import org.bukkit.block.Block; + +import java.util.Iterator; + +public class CuboidBlockIterator implements Iterator { + + private World world; + private int baseX; + private int baseY; + private int baseZ; + private int sizeX; + private int sizeY; + private int sizeZ; + private int x; + private int y; + private int z; + + CuboidBlockIterator(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.world = world; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.z = 0; + this.y = 0; + this.x = 0; + } + + @Override + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + @Override + public Block next() { + Block block = this.world.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + if (++this.x >= this.sizeX) { + this.x = 0; + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + return block; + } + + @Override + public void remove() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public World getWorld() { + return this.world; + } + + public int getBaseX() { + return this.baseX; + } + + public int getBaseY() { + return this.baseY; + } + + public int getBaseZ() { + return this.baseZ; + } + + public int getSizeX() { + return this.sizeX; + } + + public int getSizeY() { + return this.sizeY; + } + + public int getSizeZ() { + return this.sizeZ; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public int getZ() { + return this.z; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidDirection.java b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidDirection.java new file mode 100644 index 0000000..fd07f5c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidDirection.java @@ -0,0 +1,46 @@ +package me.devkevin.practice.arena.cuboid; + +public enum CuboidDirection { + + NORTH, EAST, SOUTH, WEST, + UP, DOWN, HORIZONTAL, VERTICAL, BOTH, + UNKNOWN; + + private CuboidDirection() { + + } + + public CuboidDirection opposite() { + switch (this) { + case NORTH: { + return SOUTH; + } + case EAST: { + return WEST; + } + case SOUTH: { + return NORTH; + } + case WEST: { + return EAST; + } + case HORIZONTAL: { + return VERTICAL; + } + case VERTICAL: { + return HORIZONTAL; + } + case UP: { + return DOWN; + } + case DOWN: { + return UP; + } + case BOTH: { + return BOTH; + } + } + return UNKNOWN; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidLocationIterator.java b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidLocationIterator.java new file mode 100644 index 0000000..0f4c846 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/cuboid/CuboidLocationIterator.java @@ -0,0 +1,97 @@ +package me.devkevin.practice.arena.cuboid; + +import org.bukkit.Location; +import org.bukkit.World; + +import java.util.Iterator; + +public class CuboidLocationIterator implements Iterator { + + private World world; + private int baseX; + private int baseY; + private int baseZ; + private int sizeX; + private int sizeY; + private int sizeZ; + private int x; + private int y; + private int z; + + CuboidLocationIterator(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.world = world; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.z = 0; + this.y = 0; + this.x = 0; + } + + @Override + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + @Override + public Location next() { + Location location = new Location(this.world, this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + if (++this.x >= this.sizeX) { + this.x = 0; + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + return location; + } + + @Override + public void remove() throws UnsupportedOperationException { + throw new UnsupportedOperationException(); + } + + public World getWorld() { + return this.world; + } + + public int getBaseX() { + return this.baseX; + } + + public int getBaseY() { + return this.baseY; + } + + public int getBaseZ() { + return this.baseZ; + } + + public int getSizeX() { + return this.sizeX; + } + + public int getSizeY() { + return this.sizeY; + } + + public int getSizeZ() { + return this.sizeZ; + } + + public int getX() { + return this.x; + } + + public int getY() { + return this.y; + } + + public int getZ() { + return this.z; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/generate/ArenaCommandRunnable.java b/Practice/src/main/java/me/devkevin/practice/arena/generate/ArenaCommandRunnable.java new file mode 100644 index 0000000..9d557da --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/generate/ArenaCommandRunnable.java @@ -0,0 +1,74 @@ +package me.devkevin.practice.arena.generate; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.location.CustomLocation; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +@Getter +@AllArgsConstructor +public class ArenaCommandRunnable implements Runnable { + + private final Practice plugin; + private final Arena copiedArena; + + private int times; + + @Override + public void run() { + this.duplicateArena(this.copiedArena, 10000, 10000); + } + + private void duplicateArena(Arena arena, int offsetX, int offsetZ) { + new DuplicateArenaRunnable(this.plugin, arena, offsetX, offsetZ, 500, 500) { + @Override + public void onComplete() { + double minX = arena.getMin().getX() + this.getOffsetX(); + double minZ = arena.getMin().getZ() + this.getOffsetZ(); + double maxX = arena.getMax().getX() + this.getOffsetX(); + double maxZ = arena.getMax().getZ() + this.getOffsetZ(); + + double aX = arena.getA().getX() + this.getOffsetX(); + double aZ = arena.getA().getZ() + this.getOffsetZ(); + double bX = arena.getB().getX() + this.getOffsetX(); + double bZ = arena.getB().getZ() + this.getOffsetZ(); + + CustomLocation min = new CustomLocation(minX, arena.getMin().getY(), minZ, arena.getMin().getYaw(), arena.getMin().getPitch()); + CustomLocation max = new CustomLocation(maxX, arena.getMax().getY(), maxZ, arena.getMax().getYaw(), arena.getMax().getPitch()); + CustomLocation a = new CustomLocation(aX, arena.getA().getY(), aZ, arena.getA().getYaw(), arena.getA().getPitch()); + CustomLocation b = new CustomLocation(bX, arena.getB().getY(), bZ, arena.getB().getYaw(), arena.getB().getPitch()); + + StandaloneArena standaloneArena = new StandaloneArena(a, b, min, max); + + arena.addStandaloneArena(standaloneArena); + arena.addAvailableArena(standaloneArena); + + String arenaPasteMessage = "[Standalone Arena] - " + arena.getName() + " placed at " + (int) minX + ", " + (int) minZ + ". " + ArenaCommandRunnable.this.times + " copies remaining."; + + if (--ArenaCommandRunnable.this.times > 0) { + ArenaCommandRunnable.this.plugin.getServer().getLogger().info(arenaPasteMessage); + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.isOp()) { + player.sendMessage(ChatColor.GREEN + arenaPasteMessage); + } + } + ArenaCommandRunnable.this.duplicateArena(arena, (int) Math.round(maxX), (int) Math.round(maxZ)); + } else { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.isOp()) { + player.sendMessage(ChatColor.GREEN + "All the copies for " + ArenaCommandRunnable.this.copiedArena.getName() + " have been pasted successfully!"); + } + } + ArenaCommandRunnable.this.plugin.getServer().getLogger().info("All the copies for " + ArenaCommandRunnable.this.copiedArena.getName() + " have been pasted successfully!"); + ArenaCommandRunnable.this.plugin.getArenaManager().setGeneratingArenaRunnable(ArenaCommandRunnable.this.plugin.getArenaManager().getGeneratingArenaRunnable() - 1); + this.getPlugin().getArenaManager().reloadArenas(); + } + } + }.run(); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/arena/generate/ArenaCopyRemovalRunnable.java b/Practice/src/main/java/me/devkevin/practice/arena/generate/ArenaCopyRemovalRunnable.java new file mode 100644 index 0000000..2c19ee1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/generate/ArenaCopyRemovalRunnable.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.arena.generate; + +import com.boydti.fawe.util.EditSessionBuilder; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.blocks.BlockID; +import com.sk89q.worldedit.regions.CuboidRegion; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ArenaCopyRemovalRunnable extends BukkitRunnable { + + private final int number; + private final Arena arena; + private final StandaloneArena arenaCopy; + + private final Practice plugin = Practice.getInstance(); + + public ArenaCopyRemovalRunnable(int number, Arena arena, StandaloneArena arenaCopy) { + this.number = number; + this.arena = arena; + this.arenaCopy = arenaCopy; + } + + @Override + public void run() { + TaskManager.IMP.async(() -> { + EditSession editSession = new EditSessionBuilder(arenaCopy.getA().getWorld()).fastmode(true).allowedRegionsEverywhere().autoQueue(false).limitUnlimited().build(); + CuboidRegion copyRegion = new CuboidRegion( + new Vector(arenaCopy.getMax().getX(), arenaCopy.getMax().getY(), arenaCopy.getMax().getZ()), + new Vector(arenaCopy.getMin().getX(), arenaCopy.getMin().getY(), arenaCopy.getMin().getZ()) + ); + + try { + editSession.setBlocks(copyRegion, new BaseBlock(BlockID.AIR)); + } catch (MaxChangedBlocksException e) { + e.printStackTrace(); + } + + editSession.flushQueue(); + }); + + this.plugin.getMainConfig().getConfig().getConfigurationSection("arenas." + arena.getName() + ".standaloneArenas").set(String.valueOf(number), null); + this.plugin.getMainConfig().save(); + + this.plugin.getArenaManager().getArena(arena.getName()).getStandaloneArenas().remove(arenaCopy); + this.plugin.getArenaManager().getArena(arena.getName()).getAvailableArenas().remove(number); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/generate/BlockPlaceRunnable.java b/Practice/src/main/java/me/devkevin/practice/arena/generate/BlockPlaceRunnable.java new file mode 100644 index 0000000..0700ee6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/generate/BlockPlaceRunnable.java @@ -0,0 +1,64 @@ +package me.devkevin.practice.arena.generate; + +import com.boydti.fawe.util.EditSessionBuilder; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import lombok.Getter; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.scheduler.BukkitRunnable; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * @since 12/31/2021 + */ +@Getter +public abstract class BlockPlaceRunnable extends BukkitRunnable { + + private final ConcurrentMap blocks; + private final int totalBlocks; + private final Iterator iterator; + private World world; + private int blockIndex = 0; + private int blocksPlaced = 0; + private boolean completed = false; + + public BlockPlaceRunnable(World world, Map blocks) { + this.world = world; + this.blocks = new ConcurrentHashMap<>(); + this.blocks.putAll(blocks); + this.totalBlocks = blocks.keySet().size(); + this.iterator = blocks.keySet().iterator(); + } + + @Override + public void run() { + if (blocks.isEmpty() || !iterator.hasNext()) { + finish(); + completed = true; + cancel(); + return; + } + + TaskManager.IMP.async(() -> { + EditSession editSession = new EditSessionBuilder(this.world.getName()).fastmode(true).allowedRegionsEverywhere().autoQueue(false).limitUnlimited().build(); + for (Map.Entry entry : this.blocks.entrySet()) { + try { + editSession.setBlock(new Vector(entry.getKey().getBlockX(), entry.getKey().getBlockY(), entry.getKey().getZ()), new BaseBlock(entry.getValue().getTypeId(), entry.getValue().getData())); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + editSession.flushQueue(); + TaskManager.IMP.task(this.blocks::clear); + }); + } + + public abstract void finish(); +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/generate/DuplicateArenaRunnable.java b/Practice/src/main/java/me/devkevin/practice/arena/generate/DuplicateArenaRunnable.java new file mode 100644 index 0000000..1aff176 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/generate/DuplicateArenaRunnable.java @@ -0,0 +1,111 @@ +package me.devkevin.practice.arena.generate; + +import lombok.Getter; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.scheduler.BukkitRunnable; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; + +import java.util.HashMap; +import java.util.Map; + + +/** + * @since 12/31/2021 + */ +@Getter +public abstract class DuplicateArenaRunnable extends BukkitRunnable { + + private final Practice plugin; + private Arena copiedArena; + private int offsetX; + private int offsetZ; + private int incrementX; + private int incrementZ; + private Map paste; + + public DuplicateArenaRunnable(Practice plugin, Arena copiedArena, int offsetX, int offsetZ, int incrementX, int incrementZ) { + this.plugin = plugin; + this.copiedArena = copiedArena; + this.offsetX = offsetX; + this.offsetZ = offsetZ; + this.incrementX = incrementX; + this.incrementZ = incrementZ; + } + + @Override + public void run() { + if (this.paste == null) { + Map copy = this.blocksFromTwoPoints(this.copiedArena.getMin().toBukkitLocation(), this.copiedArena.getMax().toBukkitLocation()); + this.paste = new HashMap<>(); + for (Location loc : copy.keySet()) { + if (copy.get(loc).getType() != Material.AIR) { + this.paste.put(loc.clone().add(this.offsetX, 0, this.offsetZ), copy.get(loc)); + } + } + copy.clear(); + } else { + Map newPaste = new HashMap<>(); + for (Location loc : this.paste.keySet()) { + if (this.paste.get(loc).getType() != Material.AIR) { + newPaste.put(loc.clone().add(this.incrementX, 0, this.incrementZ), this.paste.get(loc)); + } + } + this.paste.clear(); + this.paste.putAll(newPaste); + } + + boolean safe = true; + for (Location loc : this.paste.keySet()) { + Block block = loc.getBlock(); + if (block.getType() != Material.AIR) { + safe = false; + break; + } + } + + if (!safe) { + this.offsetX += this.incrementX; + this.offsetZ += this.incrementZ; + this.run(); + return; + } + + new BlockPlaceRunnable(this.copiedArena.getA().toBukkitLocation().getWorld(), this.paste) { + @Override + public void finish() { + DuplicateArenaRunnable.this.onComplete(); + } + }.runTaskTimer(this.plugin, 0L, 5L); + } + + public Map blocksFromTwoPoints(Location loc1, Location loc2) { + Map blocks = new HashMap<>(); + + int topBlockX = (loc1.getBlockX() < loc2.getBlockX() ? loc2.getBlockX() : loc1.getBlockX()); + int bottomBlockX = (loc1.getBlockX() > loc2.getBlockX() ? loc2.getBlockX() : loc1.getBlockX()); + + int topBlockY = (loc1.getBlockY() < loc2.getBlockY() ? loc2.getBlockY() : loc1.getBlockY()); + int bottomBlockY = (loc1.getBlockY() > loc2.getBlockY() ? loc2.getBlockY() : loc1.getBlockY()); + + int topBlockZ = (loc1.getBlockZ() < loc2.getBlockZ() ? loc2.getBlockZ() : loc1.getBlockZ()); + int bottomBlockZ = (loc1.getBlockZ() > loc2.getBlockZ() ? loc2.getBlockZ() : loc1.getBlockZ()); + + for (int x = bottomBlockX; x <= topBlockX; x++) { + for (int z = bottomBlockZ; z <= topBlockZ; z++) { + for (int y = bottomBlockY; y <= topBlockY; y++) { + Block block = loc1.getWorld().getBlockAt(x, y, z); + if (block.getType() != Material.AIR) { + blocks.put(new Location(loc1.getWorld(), x, y, z), block); + } + } + } + } + + return blocks; + } + + public abstract void onComplete(); +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/manager/ArenaManager.java b/Practice/src/main/java/me/devkevin/practice/arena/manager/ArenaManager.java new file mode 100644 index 0000000..8bd9f3d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/manager/ArenaManager.java @@ -0,0 +1,196 @@ +package me.devkevin.practice.arena.manager; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.chunk.manager.ChunkRestorationManager; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.file.Config; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.location.CustomLocation; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +public class ArenaManager { + private final Practice plugin = Practice.getInstance(); + + private final Config config = new Config("arenas", this.plugin); + + @Getter private final Map arenas = new HashMap<>(); + @Getter private final Map arenaMatchUUIDs = new HashMap<>(); + + @Getter @Setter private int generatingArenaRunnable; + + public ArenaManager() { + this.loadArenas(); + } + + private void loadArenas() { + FileConfiguration fileConfig = config.getConfig(); + ConfigurationSection arenaSection = fileConfig.getConfigurationSection("arenas"); + if (arenaSection == null) { + return; + } + + arenaSection.getKeys(false).forEach(name -> { + String icon = arenaSection.getString(name + ".icon") == null ? Material.PAPER.name() : arenaSection.getString(name + ".icon"); + int iconData = arenaSection.getInt(name + ".icon-data"); + String a = arenaSection.getString(name + ".a"); + String b = arenaSection.getString(name + ".b"); + String min = arenaSection.getString(name + ".min"); + String max = arenaSection.getString(name + ".max"); + int buildMax = arenaSection.getInt(name + ".build-max"); + int deadZone = arenaSection.getInt(name + ".dead-zone"); + int portalProt = arenaSection.getInt(name + ".portalProt"); + + CustomLocation locA = CustomLocation.stringToLocation(a); + CustomLocation locB = CustomLocation.stringToLocation(b); + CustomLocation locMin = CustomLocation.stringToLocation(min); + CustomLocation locMax = CustomLocation.stringToLocation(max); + + List standaloneArenas = new ArrayList<>(); + ConfigurationSection saSection = arenaSection.getConfigurationSection(name + ".standaloneArenas"); + if (saSection != null) { + saSection.getKeys(false).forEach(id -> { + String saA = saSection.getString(id + ".a"); + String saB = saSection.getString(id + ".b"); + String saMin = saSection.getString(id + ".min"); + String saMax = saSection.getString(id + ".max"); + + CustomLocation locSaA = CustomLocation.stringToLocation(saA); + CustomLocation locSaB = CustomLocation.stringToLocation(saB); + CustomLocation locSaMin = CustomLocation.stringToLocation(saMin); + CustomLocation locSaMax = CustomLocation.stringToLocation(saMax); + + StandaloneArena standaloneArena = new StandaloneArena(locSaA, locSaB, locSaMin, locSaMax); + ChunkRestorationManager.getIChunkRestoration().copy(standaloneArena); + + standaloneArenas.add(standaloneArena); + }); + } + + boolean enabled = arenaSection.getBoolean(name + ".enabled", false); + + Arena arena = new Arena(name, standaloneArenas, new ArrayList<>(standaloneArenas), icon, iconData, locA, locB, locMin, locMax, buildMax, deadZone, portalProt, enabled, false, null); + this.arenas.put(name, arena); + }); + } + + public void reloadArenas() { + this.saveArenas(); + this.arenas.clear(); + this.loadArenas(); + } + + public void saveArenas() { + FileConfiguration fileConfig = this.config.getConfig(); + + fileConfig.set("arenas", null); + arenas.forEach((arenaName, arena) -> { + String icon = arena.getIcon(); + int iconData = arena.getIconData(); + String a = CustomLocation.locationToString(arena.getA()); + String b = CustomLocation.locationToString(arena.getB()); + String min = CustomLocation.locationToString(arena.getMin()); + String max = CustomLocation.locationToString(arena.getMax()); + int buildMax = arena.getBuildMax(); + int deadZone = arena.getDeadZone(); + int portalProt = arena.getPortalProt(); + + String arenaRoot = "arenas." + arenaName; + + fileConfig.set(arenaRoot + ".icon", icon); + fileConfig.set(arenaRoot + ".icon-data", iconData); + fileConfig.set(arenaRoot + ".a", a); + fileConfig.set(arenaRoot + ".b", b); + fileConfig.set(arenaRoot + ".min", min); + fileConfig.set(arenaRoot + ".max", max); + fileConfig.set(arenaRoot + ".build-max", buildMax); + fileConfig.set(arenaRoot + ".dead-zone", deadZone); + fileConfig.set(arenaRoot + ".portalProt", portalProt); + fileConfig.set(arenaRoot + ".enabled", arena.isEnabled()); + fileConfig.set(arenaRoot + ".standaloneArenas", null); + + int i = 0; + if (arena.getStandaloneArenas() != null) { + for (StandaloneArena saArena : arena.getStandaloneArenas()) { + String saA = CustomLocation.locationToString(saArena.getA()); + String saB = CustomLocation.locationToString(saArena.getB()); + String saMin = CustomLocation.locationToString(saArena.getMin()); + String saMax = CustomLocation.locationToString(saArena.getMax()); + + String standAloneRoot = arenaRoot + ".standaloneArenas." + i; + + fileConfig.set(standAloneRoot + ".a", saA); + fileConfig.set(standAloneRoot + ".b", saB); + fileConfig.set(standAloneRoot + ".min", saMin); + fileConfig.set(standAloneRoot + ".max", saMax); + + i++; + } + } + }); + + this.config.save(); + } + + public void createArena(String name) { + this.arenas.put(name, new Arena(name)); + } + + public void deleteArena(String name) { + this.arenas.remove(name); + } + + public Arena getArena(String name) { + return this.arenas.get(name); + } + + // Recoded + // Basicaly I added new method 'lastSelectedArena' and we get the info from Profile + // with lastArenaPlayed so basically what we do here is a method that returns a + // random arena from a list of available and enabled arenas. + // + // In this code, if there is only one arena left in the list after removing the ones + // that are not enabled or not in the white list, it returns that arena. If there are + // no arenas left, it returns the lastSelectedArena. If there are more than one arena left, + // it uses a do-while loop to randomly select an arena and keeps track of how many times the + // same arena as lastSelectedArena has been selected in a row using a counter count. The loop + // continues to run as long as the selected arena is the same as lastSelectedArena and the counter + // is less than 2. This ensures that the same arena is not selected more than two times in a row. + public Arena getRandomArena(Kit kit, Arena lastSelectedArena) { + List arenas = new ArrayList<>(this.arenas.values()); + arenas.removeIf(arena -> !arena.isEnabled()); + arenas.removeIf(arena -> !kit.getArenaWhiteList().contains(arena.getName())); + + if (arenas.size() <= 1) { + return arenas.size() == 1 ? arenas.get(0) : lastSelectedArena; + } + + Arena selectedArena; + int count = 0; + do { + selectedArena = arenas.get(ThreadLocalRandom.current().nextInt(arenas.size())); + count++; + } while (selectedArena == lastSelectedArena && count < 2); + + return selectedArena; + } + + public void removeArenaMatchUUID(StandaloneArena arena) { + this.arenaMatchUUIDs.remove(arena); + } + + public UUID getArenaMatchUUID(StandaloneArena arena) { + return this.arenaMatchUUIDs.get(arena); + } + + public void setArenaMatchUUID(StandaloneArena arena, UUID matchUUID) { + this.arenaMatchUUIDs.put(arena, matchUUID); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaCopyMenu.java b/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaCopyMenu.java new file mode 100644 index 0000000..c2b5510 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaCopyMenu.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.arena.menu; + +import lombok.AllArgsConstructor; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.menu.buttons.ArenaCopyButton; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class ArenaCopyMenu extends Menu { + + private final Arena arena; + + @Override + public String getTitle(Player player) { + return "Arena Copies"; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + int i = 0; + for (StandaloneArena arenaCopy : Practice.getInstance().getArenaManager().getArena(arena.getName()).getStandaloneArenas()) { + buttons.put(buttons.size(), new ArenaCopyButton(i, arena, arenaCopy)); + i++; + } + + return buttons; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaGenerationMenu.java b/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaGenerationMenu.java new file mode 100644 index 0000000..bda9703 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaGenerationMenu.java @@ -0,0 +1,43 @@ +package me.devkevin.practice.arena.menu; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.menu.buttons.ArenaGenerateButton; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class ArenaGenerationMenu extends Menu { + + private final Arena arena; + + @Getter + private final int[] clonableAmounts = {1, 2, 3, 4, 5, 10, 15}; + + @Override + public String getTitle(Player player) { + return "Arena Copies Generation"; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + for (int curr : clonableAmounts) { + buttons.put(1 + buttons.size(), new ArenaGenerateButton(arena, curr)); + } + + return buttons; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaManagerMenu.java b/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaManagerMenu.java new file mode 100644 index 0000000..171c8ee --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/menu/ArenaManagerMenu.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.arena.menu; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.menu.buttons.ArenaButton; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.pagination.PageButton; +import me.devkevin.practice.util.menu.pagination.PaginatedMenu; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ArenaManagerMenu extends PaginatedMenu { + + private final Practice plugin = Practice.getInstance(); + + @Override + public String getPrePaginatedTitle(Player player) { + return "Arena Management"; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new HashMap<>(); + this.plugin.getArenaManager().getArenas().forEach((s, arena) -> buttons.put(buttons.size(), new ArenaButton(arena))); + + return buttons; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + + bottomTopButtons(false, buttons, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(15).build()); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 5; + } + + @Override + public int getMaxItemsPerPage(Player player) { + return 9 * 3; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaButton.java b/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaButton.java new file mode 100644 index 0000000..f7f99eb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaButton.java @@ -0,0 +1,71 @@ +package me.devkevin.practice.arena.menu.buttons; + +import lombok.AllArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.menu.ArenaCopyMenu; +import me.devkevin.practice.arena.menu.ArenaGenerationMenu; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class ArenaButton extends Button { + + private final Arena arena; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.valueOf(arena.getIcon())) + .durability(arena.getIconData()) + .name("&6" + arena.getName()) + .lore(CC.translate( + Arrays.asList( + " ", + "&6Arena Information&f:", + " &fState: " + (arena.isEnabled() ? "&aEnabled" : "&cDisabled"), + " &fType: &6" + (arena.getAvailableArenas().size() == 0 ? "Shared" : "Standalone"), + " &fCopies: &6" + (arena.getStandaloneArenas().size() == 0 ? "Not Required." : arena.getStandaloneArenas().size()), + " &fAvailable: &6" + (arena.getAvailableArenas().size() == 0 ? +1 : arena.getAvailableArenas().size()), + " ", + (arena.getStandaloneArenas().size() == 0 ? "&4&l&mMIDDLE-CLICK &4&mto see arena copies" : "&6&lMIDDLE-CLICK &6to see arena copies"), + "&e&lLEFT-CLICK &eto teleport to arena", + "&6&lRIGHT CLICK &6to generate standalone arenas") + ) + ) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + playSuccess(player); + switch (clickType) { + case LEFT: + player.teleport(arena.getA().toBukkitLocation()); + break; + case RIGHT: + Bukkit.getScheduler().runTaskLaterAsynchronously(Practice.getInstance(), () -> new ArenaGenerationMenu(arena).openMenu(player), 1L); + break; + case MIDDLE: + if (arena.getStandaloneArenas().size() >= 1) { + Bukkit.getScheduler().runTaskLaterAsynchronously(Practice.getInstance(), () -> new ArenaCopyMenu(arena).openMenu(player), 1L); + } + break; + } + + player.closeInventory(); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton.java b/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton.java new file mode 100644 index 0000000..1a0dcb3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton.java @@ -0,0 +1,66 @@ +package me.devkevin.practice.arena.menu.buttons; + +import lombok.AllArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.generate.ArenaCopyRemovalRunnable; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class ArenaCopyButton extends Button { + + private final Practice plugin = Practice.getInstance(); + + private final int number; + private final Arena arena; + private final StandaloneArena arenaCopy; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.PAPER) + .name("&8" + number) + .lore(CC.translate( + Arrays.asList( + "&6Copy Information&f:", + " &fParent Arena: &6" + arena.getName() + " &f(&f#" + number + "&f)", + " &f1st Spawn: &6" + Math.round(arenaCopy.getA().getX()) + "&f, &6" + Math.round(arenaCopy.getA().getY()) + "&f, &6" + Math.round(arenaCopy.getA().getZ()), + " &f2nd Spawn: &6" + Math.round(arenaCopy.getB().getX()) + "&f, &6" + Math.round(arenaCopy.getB().getY()) + "&f, &6" + Math.round(arenaCopy.getB().getZ()), + " &fMin Location: &6" + Math.round(arenaCopy.getMin().getX()) + "&f, &6" + Math.round(arenaCopy.getMin().getY()) + "&f, &6" + Math.round(arenaCopy.getMin().getZ()), + " &fMax Location: &6" + Math.round(arenaCopy.getMax().getX()) + "&f, &6" + Math.round(arenaCopy.getMax().getY()) + "&f, &6" + Math.round(arenaCopy.getMax().getZ()), + " ", + "&e&lLEFT-CLICK &eto teleport to this copy!", + "&c&lRIGHT-CLICK &cto delete this copy!" + )) + ) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + switch (clickType) { + case LEFT: + player.teleport(arenaCopy.getA().toBukkitLocation()); + break; + case RIGHT: + new ArenaCopyRemovalRunnable(number, arena, arenaCopy).runTask(this.plugin); + break; + } + + player.closeInventory(); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaGenerateButton.java b/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaGenerateButton.java new file mode 100644 index 0000000..5cc25c5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/menu/buttons/ArenaGenerateButton.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.arena.menu.buttons; + +import lombok.AllArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +/** + * Copyright 31/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class ArenaGenerateButton extends Button { + + private final Arena arena; + private final int currentCopyAmount; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.PAPER) + .name("&aCreate " + currentCopyAmount + " Arena Copies") + .lore(CC.translate( + Arrays.asList( + " ", + "&fClicking here will generate &6&l" + currentCopyAmount, + "&farenas for the map &6" + arena.getName() + "&f!", + " ", + "&a&lLEFT-CLICK &ato generate arenas") + )) + .amount(currentCopyAmount) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.performCommand("arena generate " + arena.getName() + " " + currentCopyAmount); + + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&6&lGENERATING ARENAS&6...")); + player.sendMessage(CC.translate(" ")); + player.sendMessage(CC.translate("&6&luDrop Practice &fis currently generating copies for:")); + player.sendMessage(CC.translate(" &6&l▸ &fArena: &6" + arena.getName())); + player.sendMessage(CC.translate(" &6&l▸ &fCopies: &6" + currentCopyAmount)); + player.sendMessage(CC.translate(" ")); + player.sendMessage(CC.translate("&f&oYou can check the progress in console.")); + player.sendMessage(CC.CHAT_BAR); + + player.closeInventory(); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/arena/standalone/StandaloneArena.java b/Practice/src/main/java/me/devkevin/practice/arena/standalone/StandaloneArena.java new file mode 100644 index 0000000..364cceb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/arena/standalone/StandaloneArena.java @@ -0,0 +1,20 @@ +package me.devkevin.practice.arena.standalone; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.practice.location.CustomLocation; + +@Getter +@Setter +@AllArgsConstructor +@RequiredArgsConstructor +public class StandaloneArena { + + private CustomLocation a; + private CustomLocation b; + + private CustomLocation min; + private CustomLocation max; +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/board/PracticeBoard.java b/Practice/src/main/java/me/devkevin/practice/board/PracticeBoard.java new file mode 100644 index 0000000..a4ecb70 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/board/PracticeBoard.java @@ -0,0 +1,647 @@ +package me.devkevin.practice.board; + +import club.inverted.chatcolor.CC; +import com.bizarrealex.aether.scoreboard.Board; +import com.bizarrealex.aether.scoreboard.BoardAdapter; +import com.bizarrealex.aether.scoreboard.cooldown.BoardCooldown; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeCache; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.hcf.classes.Archer; +import me.devkevin.practice.hcf.classes.Bard; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.match.timer.impl.EnderpearlTimer; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.queue.QueueEntry; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.tournament.Tournament; +import me.devkevin.practice.util.Animation; +import me.devkevin.practice.util.MathUtil; +import me.devkevin.practice.util.PlayerUtil; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.apache.commons.lang3.StringEscapeUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scoreboard.DisplaySlot; +import org.bukkit.scoreboard.Objective; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.util.*; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PracticeBoard implements BoardAdapter { + + /** + * Don't fucking change anything of the boards cause u can fuck up that nigger I had 5 hours to figure it out well + */ + + @Getter private final Practice plugin = Practice.getInstance(); + + public String getTitle(Player player) { + return CC.GOLD + "Practice " + CC.GRAY + "[East]"; + } + + @Override + public List getScoreboard(Player player, Board board, Set cooldowns) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (profile == null) { + this.plugin.getLogger().warning(player.getName() + "'s player data is null"); + return null; + } + + if (!profile.getOptions().isScoreboard()) { + return null; + } + + final List strings = new ArrayList<>(); + + // spawn board + if (profile.isInSpawn()) { + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Online: " + CC.GOLD + PracticeCache.getInstance().getOnlinePlayers() + CC.GRAY + " (" + PracticeCache.getInstance().getQueueingPlayers() + ")"); + strings.add(CC.YELLOW + "Playing: " + CC.GOLD + PracticeCache.getInstance().getPlayingPlayers()); + + strings.add(""); + + if (profile.getState() != ProfileState.EVENT && this.plugin.getTournamentManager().getTournaments().size() >= 1) { + + for (Tournament tournament : this.plugin.getTournamentManager().getTournaments().values()) { + strings.add(CC.YELLOW + "Tournament " + CC.GRAY + tournament.getTeamSize() + "v" + tournament.getTeamSize()); + strings.add(CC.GRAY + "● " + CC.YELLOW + " Ladder: " + CC.GOLD + tournament.getKitName()); + strings.add(CC.GRAY + "● " + CC.YELLOW + " Stage: " + CC.GOLD + tournament.getCurrentRound() + CC.YELLOW + " Round"); + strings.add(CC.GRAY + "● " + CC.YELLOW + " Playing: " + CC.GOLD + tournament.getPlayers().size() + "/" + tournament.getSize()); + + int countdown = tournament.getCountdown(); + + if (countdown > 0 && countdown <= 30) { + strings.add(CC.GRAY + "● " + CC.YELLOW + " Starting: " + CC.GOLD + countdown + CC.R + "'s"); + } + strings.add(""); + } + } + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + + // queue board + if (profile.isInQueue()) { + QueueEntry queueEntry = party == null ? plugin.getQueue().getQueueEntry(player.getUniqueId()) : + plugin.getQueue().getQueueEntry(party.getLeader()); + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Online: " + CC.GOLD + PracticeCache.getInstance().getOnlinePlayers() + CC.GRAY + " (" + PracticeCache.getInstance().getQueueingPlayers() + ")"); + strings.add(CC.YELLOW + "Playing: " + CC.GOLD + PracticeCache.getInstance().getPlayingPlayers()); + strings.add(""); + strings.add(CC.YELLOW + "Queue:"); + strings.add(CC.GOLD + queueEntry.getQueueType().getName() + " " + queueEntry.getKitName()); + + if (queueEntry.getQueueType() != QueueType.UN_RANKED) { + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + long queueTime = System.currentTimeMillis() - + (party == null ? this.plugin.getQueue().getPlayerQueueTime(player + .getUniqueId()) + : this.plugin.getQueue().getPlayerQueueTime(party.getLeader())); + + int eloRange = coreProfile.hasRank(Rank.BASIC) ? profile.getEloRange() : -1; + int seconds = Math.round(queueTime / 1000L); + if (seconds > 5) { + if (eloRange != -1) { + eloRange += seconds * 50; + if (eloRange >= 3000) { + eloRange = 3000; + } + } + } + + int elo; + if (queueEntry.getQueueType() == QueueType.RANKED) { + elo = profile.getElo(queueEntry.getKitName()); + + strings.add(CC.YELLOW + "ELO range:"); + strings.add(CC.GRAY + (eloRange == -1 ? "Unrestricted" : + "[" + Math.max(elo - eloRange / 2, 0) + + " -> " + Math.max(elo + eloRange / 2, 0) + "]")); + } + } + + strings.add(""); + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + + // match board + if (profile.isFighting()) { + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + Player opponent = null; + + if (match == null) { + strings.add(""); + strings.add(CC.GRAY + "Finding match " + match.getInfoAnimation()); + strings.add(""); + } + + if (!match.isFFA() && !match.isParty()) { + opponent = match.getTeams().get(0).getPlayers().get(0) == player.getUniqueId() + ? this.plugin.getServer().getPlayer(match.getTeams().get(1).getPlayers().get(0)) + : this.plugin.getServer().getPlayer(match.getTeams().get(0).getPlayers().get(0)); + + if (opponent == null) { + // no board + return null; + } + + if (match.isStarting()) { + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Kit: " + CC.GOLD + match.getKit().getName()); + strings.add(CC.YELLOW + "Arena id: " + CC.GOLD + match.getArena().getName()); + strings.add(""); + strings.add(CC.YELLOW + "Starting in " + CC.GOLD + match.getCountdown()); + strings.add(""); + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add("inverted.club"); + } + strings.add(PracticeLang.line); + } + + if (match.isFighting()) { + if (match.getKit().isBoxing()) { + MatchTeam playerTeam = match.getTeams().get(profile.getTeamID()); + MatchTeam enemyTeam = playerTeam == match.getTeams().get(0) ? match.getTeams().get(1) : match.getTeams().get(0); + Profile opponentPlayerData = this.plugin.getProfileManager().getProfileData(enemyTeam.getPlayers().get(0)); + + int yourHits = profile.getHits(), theirHits = opponentPlayerData.getHits(); + int yourCombos = profile.getCombo(), theirCombos = opponentPlayerData.getCombo(); + + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Hits: " + (((yourHits - theirHits < theirHits - yourHits ? "&c(" + (yourHits - theirHits) + ")" : "&a(+" + (yourHits - theirHits) + ")"))) + ((yourCombos < 2 && theirCombos < 2) ? "" : yourCombos > theirCombos ? " &a" + yourCombos + " Combo" : " &c" + theirCombos + " Combo")); + strings.add(CC.YELLOW + " You: " + CC.GOLD + yourHits); + strings.add(CC.YELLOW + " Them: " + CC.GOLD + theirHits); + strings.add(""); + strings.add(CC.YELLOW + "Your Ping: " + CC.GOLD + PlayerUtil.getPing(player) + " ms"); + strings.add(CC.YELLOW + "Their Ping: " + CC.GOLD + PlayerUtil.getPing(opponent) + " ms"); + strings.add(""); + } + else { + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Your Ping: " + CC.GOLD + PlayerUtil.getPing(player) + " ms"); + strings.add(CC.YELLOW + "Their Ping: " + CC.GOLD + PlayerUtil.getPing(opponent) + " ms"); + strings.add(""); + } + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + + if (match.isEnding()) { + strings.add(PracticeLang.line); + strings.add(CC.GRAY + "Match Ended."); + strings.add(""); + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + } + else if (match.isParty() && !match.isFFA()) { + MatchTeam opposingTeam = match.isFFA() ? match.getTeams().get(0) : (profile.getTeamID() == 0 ? match.getTeams().get(1) : match.getTeams().get(0)); + MatchTeam playerTeam = match.getTeams().get(profile.getTeamID()); + + //This is how we know it's a 4v4 or not + if (opposingTeam.getPlayers().size() == 4 && playerTeam.getPlayers().size() == 4) { + Player teammate = this.plugin.getServer().getPlayer( + playerTeam.getPlayers().get(0) == player.getUniqueId() ? playerTeam.getPlayers().get(1) : + playerTeam.getPlayers().get(0)); + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Teammates:"); + if (teammate != null) { + if (playerTeam.getAlivePlayers().contains(teammate.getUniqueId())) { + strings.add(CC.GOLD + " " + teammate.getName() + CC.RED + " (" + + MathUtil.roundToHalves(teammate.getHealth() / 2.0D) + " ❤)"); + + boolean potionMatch = false; + boolean soupMatch = false; + + for (ItemStack item : match.getKit().getContents()) { + if (item == null) { + continue; + } + if (item.getType() == Material.MUSHROOM_SOUP) { + soupMatch = true; + break; + } else if (item.getType() == Material.POTION && item.getDurability() == (short) 16421) { + potionMatch = true; + break; + } + } + + if (potionMatch) { + int potCount = (int) Arrays.stream(teammate.getInventory().getContents()).filter(Objects::nonNull) + .map(ItemStack::getDurability).filter(d -> d == 16421).count(); + + if (potCount <= 3) { + strings.add(CC.translate(" &5" + potCount + " &fpots")); + } else if (potCount <= 8) { + strings.add(CC.translate(" &5" + potCount + " &fpots")); + } else if (potCount <= 12) { + strings.add(CC.translate(" &6" + potCount + " &fpots")); + } else if (potCount <= 20) { + strings.add(CC.translate(" &e" + potCount + " &fpots")); + } + } else if (soupMatch) { + int soupCount = (int) Arrays.stream(teammate.getInventory().getContents()).filter(Objects::nonNull).map(ItemStack::getType) + .filter(d -> d == Material.MUSHROOM_SOUP).count(); + + strings.add(" " + CC.YELLOW + soupCount + " soups"); + } + } else { + strings.add(CC.GOLD + " " + teammate.getName() + CC.D_RED + " (✘)"); + } + } + if (opposingTeam.getAlivePlayers().size() > 0) { + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Opponents: "); + for (UUID opponent2 : opposingTeam.getAlivePlayers()) { + strings.add(LandCore.getInstance().getProfileManager().getProfile(opponent2).getGrant().getRank().getColor() + " " + this.plugin.getServer().getPlayer(opponent2).getName()); + } + strings.add(""); + + if (match.isPartyMatch()) { + if (match.getKit().getName().equalsIgnoreCase("HCF")) { + + strings.add(CC.AQUA + "Class: " + CC.GRAY + getClassName(player.getUniqueId())); + + if (!hasExpiredEnderCooldown(player)) { + strings.add(CC.translate("&5EnderPearl: " + CC.GRAY + getEnderPearlRemain(player))); + } + + if (getClassName(player.getUniqueId()).equalsIgnoreCase("Bard")) { + + strings.add(CC.translate("&eEnergy: " + CC.GRAY + Bard.getEnergy(player))); + } + + strings.add(""); + } + } + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + } else { + //Not a 4v4, don't fuck up the board just show the amount of opponents + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Teammates: " + CC.GOLD + playerTeam.getAlivePlayers().size() + "/" + playerTeam.getAlivePlayers().size()); + strings.add(CC.YELLOW + "Opponents: " + CC.GOLD + opposingTeam.getAlivePlayers().size() + "/" + opposingTeam.getAlivePlayers().size()); + strings.add(""); + + if (match.isPartyMatch()) { + if (match.getKit().getName().equalsIgnoreCase("HCF")) { + + strings.add(CC.AQUA + "Class: " + CC.GRAY + getClassName(player.getUniqueId())); + + if (!hasExpiredEnderCooldown(player)) { + strings.add(CC.translate("&5EnderPearl: " + CC.GRAY + getEnderPearlRemain(player))); + } + + if (getClassName(player.getUniqueId()).equalsIgnoreCase("Bard")) { + + strings.add(CC.translate("&eEnergy: " + CC.GRAY + Bard.getEnergy(player))); + } + + strings.add(""); + } + } + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + } else if (match.isFFA()) { + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Opponents: " + CC.GOLD + (match.getTeams().get(0).getAlivePlayers().size() - 1)); + strings.add(""); + + if (match.isPartyMatch()) { + if (match.getKit().getName().equalsIgnoreCase("HCF")) { + + strings.add(CC.AQUA + "Class: " + CC.GRAY + getClassName(player.getUniqueId())); + + if (!hasExpiredEnderCooldown(player)) { + strings.add(CC.translate("&5EnderPearl: " + CC.GRAY + getEnderPearlRemain(player))); + } + + if (getClassName(player.getUniqueId()).equalsIgnoreCase("Bard")) { + + strings.add(CC.translate("&eEnergy: " + CC.GRAY + Bard.getEnergy(player))); + } + + strings.add(""); + } + } + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + } + + // party board + if (profile.isInParty()) { + if (party != null) { + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Online: " + CC.GOLD + PracticeCache.getInstance().getOnlinePlayers() + CC.GRAY + " (" + PracticeCache.getInstance().getQueueingPlayers() + ")"); + strings.add(CC.YELLOW + "Playing: " + CC.GOLD + PracticeCache.getInstance().getPlayingPlayers()); + + strings.add(""); + + strings.add(""); + strings.add(CC.YELLOW + "Party " + CC.GOLD + "(" + party.getMembers().size() + " Player" + (party.getMembers().size() == 1 ? "" : "s") + ")"); + strings.add(" " + CC.GRAY + "● " + " " + CC.YELLOW + "Leader: " + LandCore.getInstance().getProfileManager().getProfile(party.getLeader()).getGrant().getRank().getColor() + Bukkit.getPlayer(party.getLeader()).getName()); + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + } + + // spectating board + if (profile.isSpectating()) { + Match match = this.plugin.getMatchManager().getSpectatingMatch(player.getUniqueId()); + + strings.add(PracticeLang.line); + strings.add(CC.YELLOW + "Kit: " + CC.GOLD + (match.getKit() == null ? "Unknown" : match.getKit().getName())); + if (match.isStarting()) { + strings.add(""); + strings.add(CC.translate(CC.YELLOW + "Starting in " + CC.GOLD + match.getCountdown())); + strings.add(""); + } else { + strings.add(""); + strings.add(CC.YELLOW + "Duration: " + CC.GOLD + match.getDuration()); + strings.add(""); + } + + Player playerSpectate; + Player opponentPlayerSpectate; + + if (!match.isPartyMatch() && match.isFFA()) { + playerSpectate = this.plugin.getServer().getPlayer(match.getTeams().get(0).getPlayers().get(0)); + opponentPlayerSpectate = this.plugin.getServer().getPlayer(match.getTeams().get(1).getPlayers().get(0)); + + strings.add(LandCore.getInstance().getProfileManager().getProfile(playerSpectate.getUniqueId()).getGrant().getRank().getColor() + playerSpectate.getName() + CC.RED + "(" + PlayerUtil.getPing(playerSpectate) + "ms"); + strings.add(CC.GOLD + "vs"); + strings.add(LandCore.getInstance().getProfileManager().getProfile(opponentPlayerSpectate.getUniqueId()).getGrant().getRank().getColor() + opponentPlayerSpectate.getName() + CC.RED + "(" + PlayerUtil.getPing(opponentPlayerSpectate) + "ms"); + strings.add(""); + } else if (match.isPartyMatch() && !match.isFFA()) { + playerSpectate = this.plugin.getServer().getPlayer(match.getTeams().get(0).getPlayers().get(0)); + opponentPlayerSpectate = this.plugin.getServer().getPlayer(match.getTeams().get(1).getPlayers().get(0)); + + strings.add(LandCore.getInstance().getProfileManager().getProfile(playerSpectate.getUniqueId()).getGrant().getRank().getColor() + playerSpectate.getName() + "'s Team " + CC.RED + "(" + PlayerUtil.getPing(playerSpectate) + "ms"); + strings.add(CC.GOLD + "vs"); + strings.add(LandCore.getInstance().getProfileManager().getProfile(opponentPlayerSpectate.getUniqueId()).getGrant().getRank().getColor() + opponentPlayerSpectate.getName() + "'s Team " + CC.RED + "(" + PlayerUtil.getPing(opponentPlayerSpectate) + "ms"); + strings.add(""); + } else if (match.isFFA()) { + int alive = (match.getTeams().get(0).getAlivePlayers().size() - 1); + strings.add(CC.YELLOW + "Remaining: " + CC.GOLD + (match.getTeams().get(0).getAlivePlayers().size()) + " player" + (alive == 1 ? "" : "s")); + strings.add(""); + } + + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + + // event board + if (profile.isInEvent()) { + return null; + } + + // editor board + if (profile.isEditing()) { + strings.add(PracticeLang.line); + strings.add(CC.R + "Your are in Editing state."); + strings.add(""); + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + + if (profile.isInStaffMode()) { + strings.add(PracticeLang.line); + strings.add(CC.translate("&6State&7: &a" + profile.getState())); + strings.add(CC.translate("&6Online Players&7: &f" + PracticeCache.getInstance().getOnlinePlayers())); + strings.add(CC.translate("&6Online in Staff Mode&7: &f" + PracticeCache.getInstance().getOnlineStaffModePlayers())); + strings.add(""); + strings.add(CC.translate("&6Following&7: &f" + (profile.isFollowing() ? Bukkit.getPlayer(profile.getFollowingId()).getName() : "&cNone"))); + strings.add(""); + Animation animation = Animation.getAnimation(player.getUniqueId(), "footer"); + if (animation != null) { + strings.add(CC.translate(animation.getLine())); + } else { + strings.add(CC.GRAY + CC.I + "inverted.club"); + } + strings.add(PracticeLang.line); + } + return strings; + } + + + @Override + public void onScoreboardCreate(Player player, Scoreboard scoreboard) { + if (scoreboard != null) { + Team red = scoreboard.getTeam("red"); + if (red == null) { + red = scoreboard.registerNewTeam("red"); + } + + Team green = scoreboard.getTeam("green"); + if (green == null) { + green = scoreboard.registerNewTeam("green"); + } + + Team blue = scoreboard.getTeam("blue"); + if (blue == null) { + blue = scoreboard.registerNewTeam("blue"); + } + + Team tagged = scoreboard.getTeam("tagged"); + if (tagged == null) { + tagged = scoreboard.registerNewTeam("tagged"); + } + + red.setPrefix(String.valueOf(ChatColor.RED)); + green.setPrefix(String.valueOf(ChatColor.GREEN)); + blue.setPrefix(String.valueOf(ChatColor.BLUE)); + blue.setPrefix(String.valueOf(ChatColor.YELLOW)); + + Profile practicePlayerData = plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (practicePlayerData.getState() != ProfileState.FIGHTING) { + Objective objective = player.getScoreboard().getObjective(DisplaySlot.BELOW_NAME); + if (objective != null) { + objective.unregister(); + } + + for (String entry : red.getEntries()) red.removeEntry(entry); + for (String entry : green.getEntries()) green.removeEntry(entry); + for (String entry : blue.getEntries()) blue.removeEntry(entry); + + for (Player online : Bukkit.getOnlinePlayers()) { + if (online == null) return; + + Team spawn = scoreboard.getTeam(online.getName()); + if (spawn == null) { + spawn = scoreboard.registerNewTeam(online.getName()); + } + + if (online == player) { + spawn.setPrefix(LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor()); + } else { + spawn.setPrefix(LandCore.getInstance().getProfileManager().getProfile(online.getUniqueId()).getGrant().getRank().getColor()); + } + + String onlinePlayer = online.getName(); + if (spawn.hasEntry(onlinePlayer)) { + continue; + } + spawn.addEntry(onlinePlayer); + + return; + } + + return; + } + + Match match = plugin.getMatchManager().getMatch(player.getUniqueId()); + if (match.getKit().getName().equals("BuildUHC") && match.getKit().getName().equals("Invaded") && match.getKit().getName().equals("Strategy")) { + Objective objective = player.getScoreboard().getObjective(DisplaySlot.BELOW_NAME); + if (objective == null) { + objective = player.getScoreboard().registerNewObjective("showhealth", "health"); + } + + objective.setDisplaySlot(DisplaySlot.BELOW_NAME); + objective.setDisplayName(CC.RED + StringEscapeUtils.unescapeJava("\u2764")); + objective.getScore(player.getName()).setScore((int) Math.floor(player.getHealth())); + } + + for (MatchTeam team : match.getTeams()) { + for (UUID teamUUID : team.getAlivePlayers()) { + Player teamPlayer = plugin.getServer().getPlayer(teamUUID); + if (teamPlayer != null) { + String teamPlayerName = teamPlayer.getName(); + + if (team.getTeamID() == practicePlayerData.getTeamID() && !match.isFFA()) { + if (green.hasEntry(teamPlayerName)) { + continue; + } + green.addEntry(teamPlayerName); + } else { + + if (match.isPartyMatch()) { + if (match.getKit().getName().equalsIgnoreCase("HCF")) { + if (Archer.TAGGED != null) { + if (tagged.hasEntry(teamPlayerName)) { + continue; + } + tagged.addEntry(teamPlayerName); + } + } + } else if (red.hasEntry(teamPlayerName)) { + continue; + } + red.addEntry(teamPlayerName); + } + } + } + } + } + } + + private String getClassName(UUID uuid) { + Party party = this.plugin.getPartyManager().getParty(uuid); + + if (party.getBards().contains(uuid)) { + return "Bard"; + } else if (party.getArchers().contains(uuid)) { + return "Archer"; + } else { + return "Diamond"; + } + } + + private boolean hasExpiredEnderCooldown(Player player) { + long cooldown = Practice.getInstance().getTimerManager().getTimer(EnderpearlTimer.class).getRemaining(player); + return !(cooldown > 0); + } + + private String getEnderPearlRemain(Player player) { + if (hasExpiredEnderCooldown(player)) return "Expired"; + long cooldown = Practice.getInstance().getTimerManager().getTimer(EnderpearlTimer.class).getRemaining(player); + + return DurationFormatUtils.formatDurationWords(cooldown, true, true) + .replace("seconds", "") + .replace("second", "") + .replace(" ", ""); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/board/TablistProvider.java b/Practice/src/main/java/me/devkevin/practice/board/TablistProvider.java new file mode 100644 index 0000000..9eaffce --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/board/TablistProvider.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.board; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 09/03/2023 @ 15:55 + * TablistProvider / me.devkevin.practice.board / Practice + */ +/*public class TablistProvider implements TabAdapter { + @Override + public String getHeader(Player player) { + return CC.GOLD + "Prac LOL"; + } + + @Override + public String getFooter(Player player) { + return CC.GRAY + "prac.lol"; + } + + @Override + public List getLines(Player player) { + List lines = Lists.newArrayList(); + + int column = 1; + int row = 0; + + for (Rank rank : ImmutableList.copyOf(Rank.values()).reverse()) { + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile != null) { + if (coreProfile.getRank() == rank) { + + for (Player online : Bukkit.getOnlinePlayers()) { + try { + lines.add(new TabEntry(column, row, LandCore.getInstance().getProfileManager().getProfile(online.getUniqueId()).getGrant().getRank().getColor() + online.getName()).setPing(((CraftPlayer) online).getHandle().ping)); + if (column++ < 3) { + continue; + } + column = 0; + + if (row++ < 19) { + continue; + } + row = 0; + + } catch (Exception ignored) { + break; + } + } + + lines.add(new TabEntry(19, 0, CC.GRAY + "prac.lol")); + lines.add(new TabEntry(19, 0, CC.GRAY + "prac.lol")); + lines.add(new TabEntry(19, 0, CC.GRAY + "prac.lol")); + } + } + } + + return lines; + } +}*/ diff --git a/Practice/src/main/java/me/devkevin/practice/chat/ChatType.java b/Practice/src/main/java/me/devkevin/practice/chat/ChatType.java new file mode 100644 index 0000000..1b03fbf --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/chat/ChatType.java @@ -0,0 +1,11 @@ +package me.devkevin.practice.chat; + +/** + * Copyright 25/04/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public enum ChatType { + NORMAL, + FACTION +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/PracticeCommand.java b/Practice/src/main/java/me/devkevin/practice/command/PracticeCommand.java new file mode 100644 index 0000000..aafb235 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/PracticeCommand.java @@ -0,0 +1,21 @@ +package me.devkevin.practice.command; + +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.command.CommandArgs; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public abstract class PracticeCommand { + + @Getter private static final Practice plugin = Practice.getInstance(); + + public PracticeCommand() { + plugin.getFramework().registerCommands(this, null); + } + + public abstract void onCommand(CommandArgs command); +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/command/general/FlyCommand.java b/Practice/src/main/java/me/devkevin/practice/command/general/FlyCommand.java new file mode 100644 index 0000000..f0bc738 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/general/FlyCommand.java @@ -0,0 +1,55 @@ +package me.devkevin.practice.command.general; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class FlyCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "fly", inGameOnly = true) + public void onCommand(CommandArgs command) { + CommandSender sender = command.getSender(); + Player player = command.getPlayer(); + + if (!(sender instanceof Player)) { + return; + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (!coreProfile.hasDonor()) { + player.sendMessage(PracticeLang.NO_PERMISSION); + return; + } + + me.devkevin.practice.profile.Profile profile2 = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile2.getState() != ProfileState.SPAWN) { + player.sendMessage(CC.RED + "You can't execute that command in your current state."); + return; + } + + player.setAllowFlight(!player.getAllowFlight()); + + if (player.getAllowFlight()) { + player.sendMessage(CC.GREEN + "Your flight mode has been enabled."); + } else { + player.sendMessage(CC.RED + "Your flight mode has been disabled."); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/general/ResetLeaderboardsCommand.java b/Practice/src/main/java/me/devkevin/practice/command/general/ResetLeaderboardsCommand.java new file mode 100644 index 0000000..a1c47d8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/general/ResetLeaderboardsCommand.java @@ -0,0 +1,24 @@ +package me.devkevin.practice.command.general; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 14/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ResetLeaderboardsCommand extends PracticeCommand { + + @Command(name = "resetleaderboards", permission = Rank.DEVELOPER) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Practice.getInstance().getPracticeDatabase().getProfiles().drop(); + player.sendMessage(CC.GREEN + "You have been reset leaderboards"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/general/SetEditorSpawnCommand.java b/Practice/src/main/java/me/devkevin/practice/command/general/SetEditorSpawnCommand.java new file mode 100644 index 0000000..fa01a75 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/general/SetEditorSpawnCommand.java @@ -0,0 +1,30 @@ +package me.devkevin.practice.command.general; + +import lombok.Getter; +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 17/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SetEditorSpawnCommand extends PracticeCommand { + + @Getter + private static Practice plugin = Practice.getInstance(); + + @Command(name = "setspawn.editor", permission = Rank.DEVELOPER, inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + plugin.getCustomLocationManager().setEditor(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Spawn Editor has been set!"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/general/SetEventSpawnCommand.java b/Practice/src/main/java/me/devkevin/practice/command/general/SetEventSpawnCommand.java new file mode 100644 index 0000000..2e70b55 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/general/SetEventSpawnCommand.java @@ -0,0 +1,101 @@ +package me.devkevin.practice.command.general; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 22/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SetEventSpawnCommand extends PracticeCommand { + + @Command(name = "event.setspawn", permission = Rank.DEVELOPER) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "/event setspawn "); + player.sendMessage(""); + player.sendMessage(CC.YELLOW + CC.BOLD + "Sub Commands"); + player.sendMessage(""); + player.sendMessage(CC.GRAY + CC.BOLD + "sumolocation"); + player.sendMessage(CC.GRAY + CC.BOLD + "sumofirst"); + player.sendMessage(CC.GRAY + CC.BOLD + "sumosecond"); + player.sendMessage(CC.GRAY + CC.BOLD + "sumomin"); + player.sendMessage(CC.GRAY + CC.BOLD + "sumomax"); + player.sendMessage(""); + } + + switch (args[0].toLowerCase()) { + case "sumolocation": + Practice.getInstance().getCustomLocationManager().setSumoLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the sumo location."); + break; + case "sumofirst": + Practice.getInstance().getCustomLocationManager().setSumoFirst(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the sumo location A."); + break; + case "sumosecond": + Practice.getInstance().getCustomLocationManager().setSumoSecond(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the sumo location B."); + break; + case "sumomin": + Practice.getInstance().getCustomLocationManager().setSumoMin(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the sumo min."); + break; + case "sumomax": + Practice.getInstance().getCustomLocationManager().setSumoMax(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the sumo max."); + break; + + case "taglocation": + Practice.getInstance().getCustomLocationManager().setTnttagLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the TNTTag location."); + break; + case "taggamelocation": + Practice.getInstance().getCustomLocationManager().setTnttagGameLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the TNTTag game location."); + break; + case "tagmax": + Practice.getInstance().getCustomLocationManager().setTnttagMax(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the TNTTag max."); + break; + case "tagmin": + Practice.getInstance().getCustomLocationManager().setTnttagMin(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the TNTTag min."); + break; + + case "tntrunlocation": { + Practice.getInstance().getCustomLocationManager().setTntLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the tntrun location."); + break; + } + case "tntrunmin": { + Practice.getInstance().getCustomLocationManager().setTntMin(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the tntrun location."); + break; + } + case "tntrunmax": { + Practice.getInstance().getCustomLocationManager().setTntMax(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the tntrun location."); + break; + } + case "lmslocation": + Practice.getInstance().getCustomLocationManager().setLmsLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the lms location."); + break; + case "lms": + Practice.getInstance().getCustomLocationManager().getLmsLocations().add(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Successfully set the LMS spawn-point #" + Practice.getInstance().getCustomLocationManager().getLmsLocations().size() + "."); + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/general/SetSpawnCommand.java b/Practice/src/main/java/me/devkevin/practice/command/general/SetSpawnCommand.java new file mode 100644 index 0000000..43f320f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/general/SetSpawnCommand.java @@ -0,0 +1,82 @@ +package me.devkevin.practice.command.general; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SetSpawnCommand extends PracticeCommand { + + // CLASS RECODED 31/12/2021 + + @Getter private static Practice plugin = Practice.getInstance(); + + @Command(name = "setspawn", permission = Rank.DEVELOPER, inGameOnly = true, usage = "&cUsage: /setspawn ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + switch (args[0]) { + case "spawn": + plugin.getCustomLocationManager().setSpawn(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Spawn has been set!"); + saveLocation(player, "spawn"); + break; + case "min": + plugin.getCustomLocationManager().setSpawnMin(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Spawn Min has been set!"); + saveLocation(player, "spawnMin"); + break; + case "max": + plugin.getCustomLocationManager().setSpawnMax(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "Spawn Max has been set!"); + saveLocation(player, "spawnMax"); + break; + case "hololeaderboard": + plugin.getCustomLocationManager().setHoloLeaderboardsLocation(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "You has set Spawn Holo Leaderboards location.\nSuccessfully saved spawn holo leaderboards location."); + saveLocation(player, "hololeaderboard"); + break; + case "npc1": + plugin.getCustomLocationManager().setNpc1(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "You has set Spawn NPC 1 Leaderboards location.\nSuccessfully saved spawn holo leaderboards location."); + saveLocation(player, "npc1"); + break; + case "npc2": + plugin.getCustomLocationManager().setNpc2(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "You has set Spawn NPC 2 Leaderboards location.\nSuccessfully saved spawn holo leaderboards location."); + saveLocation(player, "npc2"); + break; + case "npc3": + plugin.getCustomLocationManager().setNpc3(CustomLocation.fromBukkitLocation(player.getLocation())); + player.sendMessage(CC.GREEN + "You has set Spawn NPC 3 Leaderboards location.\nSuccessfully saved spawn holo leaderboards location."); + saveLocation(player, "npc3"); + break; + default: + player.sendMessage(CC.translate(command.getCommand().getUsage())); + break; + } + } + + private void saveLocation(Player player, String location) { + FileConfiguration config = plugin.getMainConfig().getConfig(); + config.set(location, CustomLocation.locationToString(CustomLocation.fromBukkitLocation(player.getLocation()))); + plugin.getMainConfig().save(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/general/StatsCommand.java b/Practice/src/main/java/me/devkevin/practice/command/general/StatsCommand.java new file mode 100644 index 0000000..f010d1e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/general/StatsCommand.java @@ -0,0 +1,35 @@ +package me.devkevin.practice.command.general; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 28/01/2023 @ 14:51 + * StatsCommand / me.devkevin.practice.command.general / Practice + */ +public class StatsCommand extends PracticeCommand { + @Override @Command(name = "stats", aliases = {"elo"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.openInventory(getPlugin().getStatsMenu().getStatsMenu(player).getCurrentPage()); + return; + } + + Player target = getPlugin().getServer().getPlayer(args[0]); + + if (target == null || !target.isOnline()) { + assert target != null; + player.sendMessage(CC.RED + "No player matching " + CC.YELLOW + target.getName() + CC.RED + " is connected to this server"); + return; + } + + player.openInventory(getPlugin().getStatsMenu().getStatsMenu(target).getCurrentPage()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/requeue/PlayAgainCommand.java b/Practice/src/main/java/me/devkevin/practice/command/requeue/PlayAgainCommand.java new file mode 100644 index 0000000..02e32c8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/requeue/PlayAgainCommand.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.command.requeue; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +/** + * Copyright 26/11/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PlayAgainCommand extends PracticeCommand { + @Override + @Command(name = "requeue", aliases = {"playagain"}, inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + Profile profile = getPlugin().getProfileManager().getProfileData(player.getUniqueId()); + if (!getPlugin().getMatchManager().hasPlayAgainRequest(player.getUniqueId())) { + player.sendMessage(CC.RED + "The time for requeuing has expired."); + return; + } + + Kit kit = getPlugin().getMatchManager().getPlayAgainRequestKit(profile.getUuid()); + if (kit == null) { + player.sendMessage(CC.RED + "Kit not found."); + return; + } + + if (profile.isInSpawn()) { + getPlugin().getQueue().addPlayer(player, profile, kit.getName(), QueueType.UN_RANKED); + } else if (profile.isFighting() || profile.isSpectating()) { + Match match = getPlugin().getMatchManager().getMatch(profile.getUuid()); + + if (match != null) { + match.getTeams().forEach(team -> team.killPlayer(profile.getUuid())); + match.getSpectators().remove(profile.getUuid()); + } + + getPlugin().getProfileManager().sendToSpawn(player); + getPlugin().getQueue().addPlayer(player, profile, kit.getName(), QueueType.UN_RANKED); + } + + if (player.getItemInHand().isSimilar(getPlugin().getHotbarItem().getPlayAgain())) { + player.setItemInHand(new ItemStack(Material.AIR)); + } + + getPlugin().getMatchManager().removePlayAgainRequest(profile.getUuid()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/staff/CancelMatchCommand.java b/Practice/src/main/java/me/devkevin/practice/command/staff/CancelMatchCommand.java new file mode 100644 index 0000000..fa5ed18 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/staff/CancelMatchCommand.java @@ -0,0 +1,74 @@ +package me.devkevin.practice.command.staff; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.arena.chunk.manager.ChunkRestorationManager; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * Copyright 12/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class CancelMatchCommand extends PracticeCommand { + + @Override @Command(name = "cancelmatch", permission = Rank.ADMIN, usage = "&cUsage: /cancelmatch ") + public void onCommand(CommandArgs command) { + CommandSender sender = command.getSender(); + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Profile profile = getPlugin().getProfileManager().getProfileData(player.getUniqueId()); + Player target = Bukkit.getPlayer(args[0]); + Match match = getPlugin().getMatchManager().getMatch(target.getUniqueId()); + Profile profileTarget = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + + if (args.length == 1) { + if (profileTarget == null) { + player.sendMessage(CC.translate("&cPlayer not found.")); + return; + } + + if (profileTarget.isFighting()) { + if (!match.isPartyMatch()) { + match.setMatchState(MatchState.ENDING); + match.getTeams().forEach(team -> team.alivePlayers().forEach(targets -> getPlugin().getProfileManager().sendToSpawn(targets))); + match.spectatorPlayers().forEach(getPlugin().getMatchManager()::removeSpectator); + profile.getCachedPlayer().clear(); + + match.broadcastMessage(""); + match.broadcastMessage( + CC.translate( + "&fThe match &fwas &ccancelled &fby " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + + )); + match.broadcastMessage(""); + + if (match.getKit().isBuild() || match.getKit().isSpleef()) { + ChunkRestorationManager.getIChunkRestoration().reset(match.getStandaloneArena()); + match.getArena().addAvailableArena(match.getStandaloneArena()); + getPlugin().getArenaManager().removeArenaMatchUUID(match.getStandaloneArena()); + } + } else { + player.sendMessage(CC.translate("&cThis command can only be used on 1v1 matches.")); + } + } else { + player.sendMessage(CC.translate("&c" + target.getName() + " is not in a match.")); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/staff/FollowCommand.java b/Practice/src/main/java/me/devkevin/practice/command/staff/FollowCommand.java new file mode 100644 index 0000000..d534823 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/staff/FollowCommand.java @@ -0,0 +1,78 @@ +package me.devkevin.practice.command.staff; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + * Copyright 12/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class FollowCommand extends PracticeCommand { + + @Override @Command(name = "follow", permission = Rank.TRIAL_MOD, usage = "&cUsage: /follow ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Profile profile = getPlugin().getProfileManager().getProfileData(player.getUniqueId()); + + if (!profile.isInStaffMode()) { + player.sendMessage(CC.translate("&cYou must be on staff mode. do /staff.")); + return; + } + + if (args.length < 1) { + if (profile.isFollowing() && profile.getFollowingId() != null) { + if (profile.getFollowingId() != null) { + if (profile.getFollowingId() == null) { + player.sendMessage(CC.translate("&cYou are currently following nobody.")); + return; + } + + profile.setFollowing(false); + player.sendMessage(CC.translate("&cStopped following " + LandCore.getInstance().getProfileManager().getProfile(Bukkit.getPlayer(profile.getFollowingId()).getUniqueId()).getGrant().getRank().getColor() + Bukkit.getPlayer(profile.getFollowingId()).getName() + "&c!")); + profile.setFollowingId(null); + profile.setState(ProfileState.STAFF); + } + } else { + player.sendMessage(CC.translate("&cYou are currently following nobody.")); + } + return; + } + + Player target = getPlugin().getServer().getPlayer(args[0]); + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + if (target == player) { + player.sendMessage(CC.translate("&cYou cannot follow yourself!")); + return; + } + + if (profile.getFollowingId() != null && profile.getFollowingId().equals(target.getUniqueId())) { + player.sendMessage(CC.translate("&cYou are already following this player.")); + return; + } + + profile.setFollowing(true); + profile.setFollowingId(target.getUniqueId()); + player.sendMessage(CC.translate("&aYou started following " + LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + "&a.")); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/staff/OngoingMatchesCommand.java b/Practice/src/main/java/me/devkevin/practice/command/staff/OngoingMatchesCommand.java new file mode 100644 index 0000000..66eae57 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/staff/OngoingMatchesCommand.java @@ -0,0 +1,75 @@ +package me.devkevin.practice.command.staff; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.apache.commons.lang3.StringUtils; +import org.bukkit.entity.Player; + +import java.util.Arrays; +import java.util.List; + +/** + * Copyright 12/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class OngoingMatchesCommand extends PracticeCommand { + + @Override @Command(name = "ongoing", permission = Rank.ADMIN, usage = "&cUsage: /ongoing ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + player.sendMessage(CC.translate("&7&l ▸ &6Ongoing Matches&7: &f" + (getPlugin().getMatchManager().getMatches().values().size() >= 1 ? getPlugin().getMatchManager().getMatches().values().size() : "&cNone"))); + if (getPlugin().getMatchManager().getMatches().values().size() >= 1) { + player.sendMessage(" "); + } + + for (Match match : getPlugin().getMatchManager().getMatches().values()) { + MatchTeam teamA = match.getTeams().get(0); + MatchTeam teamB = match.getTeams().get(1); + + if (teamB == null) { + continue; + } + + boolean teamAParty = teamA.getAlivePlayers().size() > 1; + boolean teamBParty = (teamB == null ? false : teamB.getAlivePlayers().size() > 1); + + String teamANames = (teamAParty ? teamA.getLeaderName() + "'s Party" : teamA.getLeaderName()); + String teamBNames = ""; + if (teamBParty) { + teamBNames = (teamBParty ? teamB.getLeaderName() + "'s Party" : teamB.getLeaderName()); + } + + List strings = Arrays.asList( + CC.SB_BAR, + "&7&lMatch Info", + "&6&l &fDuration&7: &f" + match.getDuration(), + "&6&l &fArena&7: &f" + match.getArena().getName(), + "&6&l &fKit&7: &f" + match.getKit().getName(), + CC.SB_BAR + ); + + Clickable clickable = new Clickable(CC.translate("&f ● &a" + teamANames + "&7 vs &c" + teamBNames + " &f&l\u239c &a[Click to Spectate]"), + StringUtils.join(CC.translate(strings), "\n"), + "/spectate " + teamA.getLeaderName() + ); + + clickable.sendToPlayer(player); + } + + player.sendMessage(CC.CHAT_BAR); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/staff/StaffModeCommand.java b/Practice/src/main/java/me/devkevin/practice/command/staff/StaffModeCommand.java new file mode 100644 index 0000000..bcc6747 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/staff/StaffModeCommand.java @@ -0,0 +1,31 @@ +package me.devkevin.practice.command.staff; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 09/05/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class StaffModeCommand extends PracticeCommand { + + @Command(name = "staff", aliases = {"modmode"}, permission = Rank.TRIAL_MOD) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.isInStaffMode()) { + player.sendMessage(CC.RED + "You are currently in Staff Mode."); + return; + } + + Practice.getInstance().getStaffMode().staffMode(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/stats/ResetStatsCommand.java b/Practice/src/main/java/me/devkevin/practice/command/stats/ResetStatsCommand.java new file mode 100644 index 0000000..3cc2f0a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/stats/ResetStatsCommand.java @@ -0,0 +1,47 @@ +package me.devkevin.practice.command.stats; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 17/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ResetStatsCommand extends PracticeCommand { + + @Command(name = "reset.elo", permission = Rank.MANAGER) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "Usage: /reset elo (player)"); + return; + } + + Player target = Practice.getInstance().getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(CC.RED + args[0] + " not found."); + return; + } + + Profile profile = Practice.getInstance().getProfileManager().getProfileData(target.getUniqueId()); + for (Kit kit : Practice.getInstance().getKitManager().getKits()) { + profile.setElo(kit.getName(), Profile.DEFAULT_ELO); + profile.setLosses(kit.getName(), 0); + profile.setWins(kit.getName(), 0); + } + + player.sendMessage(LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + CC.YELLOW + "'s stats have been wiped."); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/stats/SetStatsCommand.java b/Practice/src/main/java/me/devkevin/practice/command/stats/SetStatsCommand.java new file mode 100644 index 0000000..056c278 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/stats/SetStatsCommand.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.command.stats; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +/** + * Copyright 27/04/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SetStatsCommand extends PracticeCommand { + + @Command(name = "set.elo", permission = Rank.MANAGER) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "Usage: /set elo (player) (kit) (elo)"); + return; + } + + OfflinePlayer target = Bukkit.getPlayer(args[0]); + + if (!target.hasPlayedBefore() && !target.isOnline()) { + player.sendMessage(CC.translate(CC.RED + "That Player is not online.")); + return; + } + + // Practice.getInstance().getProfileManager().createPlayerData(target); + + Profile targetData = Practice.getInstance().getProfileManager().getProfileData(target.getUniqueId()); + Kit kit = Practice.getInstance().getKitManager().getKit(args[1]); + + if (kit == null) { + player.sendMessage(CC.RED + "Please provide a valid Kit."); + return; + } + + int integer = Integer.parseInt(args[2]); + + targetData.setElo(kit.getName(), integer); + //targetData.recalculateRank(targetData.getGlobalStats("ELO")); + + player.sendMessage(CC.GREEN + "You have been updated " + + LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + + CC.GREEN + " elo."); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/time/DayCommand.java b/Practice/src/main/java/me/devkevin/practice/command/time/DayCommand.java new file mode 100644 index 0000000..8888967 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/time/DayCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.practice.command.time; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.options.item.ProfileOptionsItemState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DayCommand extends PracticeCommand { + + @Command(name = "day") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + player.setPlayerTime(6000L, true); + profile.getOptions().setTime(ProfileOptionsItemState.DAY); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/time/NightCommand.java b/Practice/src/main/java/me/devkevin/practice/command/time/NightCommand.java new file mode 100644 index 0000000..d648a84 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/time/NightCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.practice.command.time; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.options.item.ProfileOptionsItemState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class NightCommand extends PracticeCommand { + + @Command(name = "night") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + player.setPlayerTime(18000L, true); + profile.getOptions().setTime(ProfileOptionsItemState.NIGHT); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/command/time/SunsetCommand.java b/Practice/src/main/java/me/devkevin/practice/command/time/SunsetCommand.java new file mode 100644 index 0000000..e9614b7 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/command/time/SunsetCommand.java @@ -0,0 +1,26 @@ +package me.devkevin.practice.command.time; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.options.item.ProfileOptionsItemState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SunsetCommand extends PracticeCommand { + + @Command(name = "sunset") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + player.setPlayerTime(12000L, true); + profile.getOptions().setTime(ProfileOptionsItemState.SUNSET); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/data/PracticeDatabase.java b/Practice/src/main/java/me/devkevin/practice/data/PracticeDatabase.java new file mode 100644 index 0000000..681f21e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/data/PracticeDatabase.java @@ -0,0 +1,62 @@ +package me.devkevin.practice.data; + +import com.mongodb.MongoClient; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; +import me.devkevin.practice.Practice; +import org.bson.Document; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 22/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class PracticeDatabase { + + @Getter private static PracticeDatabase instance; + + private MongoClient client; + private MongoDatabase database; + + private MongoCollection profiles; + private MongoCollection matchHistory; + private MongoCollection votesCollection; + private MongoCollection factions; + + public PracticeDatabase(Practice plugin) { + if (instance != null) { + throw new RuntimeException("The mongo database has already been instantiated."); + } + + instance = this; + if (plugin.getConfig().getBoolean("DATABASE.MONGO.AUTHENTICATION.ENABLED")) { + + List credentials = new ArrayList<>(); + credentials.add(MongoCredential.createCredential( + plugin.getConfig().getString("DATABASE.MONGO.AUTHENTICATION.USER"), + plugin.getConfig().getString("DATABASE.MONGO.AUTHENTICATION.DATABASE"), + plugin.getConfig().getString("DATABASE.MONGO.AUTHENTICATION.PASSWORD").toCharArray())); + client = new MongoClient(new ServerAddress( + plugin.getConfig().getString("DATABASE.MONGO.HOST"), + plugin.getConfig().getInt("DATABASE.MONGO.PORT")), + credentials); + } else { + client = new MongoClient(new ServerAddress( + plugin.getConfig().getString("DATABASE.MONGO.HOST"), + plugin.getConfig().getInt("DATABASE.MONGO.PORT"))); + } + + database = client.getDatabase("Practice"); + profiles = database.getCollection("profiles"); + matchHistory = database.getCollection("matchHistory"); + votesCollection = database.getCollection("practice_votes"); + factions = database.getCollection("factions"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/elo/EloCalculator.java b/Practice/src/main/java/me/devkevin/practice/elo/EloCalculator.java new file mode 100644 index 0000000..680b30c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/elo/EloCalculator.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.elo; + +/** + * Copyright 19/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EloCalculator { + + public static double[] getEstimations(double rankingA, double rankingB) { + double[] ret = new double[2]; + double estA = 1.0D / (1.0D + Math.pow(10.0D, (rankingB - rankingA) / 400.0D)); + double estB = 1.0D / (1.0D + Math.pow(10.0D, (rankingA - rankingB) / 400.0D)); + ret[0] = estA; + ret[1] = estB; + return ret; + } + + public static int getConstant(int ranking) { + if(ranking < 1000) { + return 32; + } + if(ranking < 1401) { + return 24; + } + return 16; + } + + public static int[] getNewRankings(int rankingA, int rankingB, boolean victoryA) { + double[] ests; + int[] ret = new int[2]; + + ests = getEstimations(rankingA, rankingB); + + int newRankA = (int) (rankingA + getConstant(rankingA) * ((victoryA ? 1 : 0) - ests[0])); + + ret[0] = Math.round(newRankA); + ret[1] = Math.round(rankingB - (newRankA - rankingA)); + return ret; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/elo/EloUtil.java b/Practice/src/main/java/me/devkevin/practice/elo/EloUtil.java new file mode 100644 index 0000000..ecf5208 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/elo/EloUtil.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.elo; + +import me.devkevin.practice.profile.Profile; + +/** + * Copyright 05/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EloUtil { + private static final KFactor[] K_FACTORS = { + new KFactor(0, Profile.DEFAULT_ELO, 25), + new KFactor(1001, 1400, 21), + new KFactor(1401, 1800, 13), + new KFactor(1801, 2200, 6) + }; + + private static final int DEFAULT_K_FACTOR = 25; + private static final int WIN = 1; + private static final int LOSS = 0; + + public static int getNewRating(int rating, int opponentRating, boolean won) { + if(won) { + return EloUtil.getNewRating(rating, opponentRating, EloUtil.WIN); + } else { + return EloUtil.getNewRating(rating, opponentRating, EloUtil.LOSS); + } + } + + public static int getNewRating(int rating, int opponentRating, int score) { + double kFactor = EloUtil.getKFactor(rating); + double expectedScore = EloUtil.getExpectedScore(rating, opponentRating); + int newRating = EloUtil.calculateNewRating(rating, score, expectedScore, kFactor); + + if(score == 1) { + if(newRating == rating) { + newRating++; + } + } + return newRating; + } + + private static int calculateNewRating(int oldRating, int score, double expectedScore, double kFactor) { + return oldRating + (int) (kFactor * (score - expectedScore)); + } + + private static double getKFactor(int rating) { + for(int i = 0; i < EloUtil.K_FACTORS.length; i++) { + if(rating >= EloUtil.K_FACTORS[i].getStartIndex() && rating <= EloUtil.K_FACTORS[i].getEndIndex()) { + return EloUtil.K_FACTORS[i].getValue(); + } + } + return EloUtil.DEFAULT_K_FACTOR; + } + + private static double getExpectedScore(int rating, int opponentRating) { + return 1 / (1 + Math.pow(10, ((double) (opponentRating - rating) / 400))); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/elo/KFactor.java b/Practice/src/main/java/me/devkevin/practice/elo/KFactor.java new file mode 100644 index 0000000..6da0d1c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/elo/KFactor.java @@ -0,0 +1,18 @@ +package me.devkevin.practice.elo; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Copyright 05/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@RequiredArgsConstructor +public class KFactor { + private final int startIndex; + private final int endIndex; + private final double value; +} + diff --git a/Practice/src/main/java/me/devkevin/practice/events/EventCountdownTask.java b/Practice/src/main/java/me/devkevin/practice/events/EventCountdownTask.java new file mode 100644 index 0000000..0a0ab10 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/EventCountdownTask.java @@ -0,0 +1,102 @@ +package me.devkevin.practice.events; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.Clickable; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.scheduler.BukkitRunnable; + +@Setter +@Getter +public abstract class EventCountdownTask extends BukkitRunnable { + private final PracticeEvent event; + private final int countdownTime; + private int timeUntilStart; + + private boolean ended; + + public EventCountdownTask(PracticeEvent event, int countdownTime) { + this.event = event; + this.countdownTime = countdownTime; + this.timeUntilStart = countdownTime; + } + + @Override + public void run() { + if (isEnded()) { + return; + } + + if (timeUntilStart <= 0) { + if (canStart()) { + + Bukkit.getScheduler().runTask(Practice.getInstance(), () -> event.start()); + } else { + Bukkit.getScheduler().runTask(Practice.getInstance(), () -> onCancel()); + } + + ended = true; + return; + } + + if (shouldAnnounce(timeUntilStart)) { + + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(event.getHost().getUniqueId()); + + String toSend = ""; + String toSendDonor = ""; + + if(profile == null) { + toSend = ChatColor.GREEN + "" + event.getName() + " is starting soon. " + ChatColor.GRAY + "[Click to Join]"; + } else { + toSend = ChatColor.GREEN + "" + event.getName() + " is starting soon. " + ChatColor.GRAY + "[Click to Join]"; + toSendDonor = ChatColor.GRAY + "[" + profile.getGrant().getRank().getColor() + ChatColor.BOLD + "*" + ChatColor.GRAY + "] " + profile.getGrant().getRank().getColor() + ChatColor.BOLD + event.getHost().getName() + ChatColor.WHITE + " is hosting a " + profile.getGrant().getRank().getColor() + ChatColor.BOLD + event.getName() + " Event. " + ChatColor.GRAY + "[Click to Join]"; + } + + Clickable message = new Clickable(profile != null && profile.hasDonor() ? toSendDonor : toSend, + ChatColor.GRAY + "Click to join this event.", + "/join " + event.getName()); + Bukkit.getServer().getOnlinePlayers().forEach(message::sendToPlayer); + + } + + timeUntilStart--; + } + + public abstract boolean shouldAnnounce(int timeUntilStart); + + public abstract boolean canStart(); + + public abstract void onCancel(); + + /** + * Because TimeUtil#millisToRoundedTime is shit + */ + private String getTime(int time) { + StringBuilder timeStr = new StringBuilder(); + int minutes = 0; + + if (time % 60 == 0) { + minutes = time / 60; + time = 0; + } else { + while (time - 60 > 0) { + minutes++; + time -= 60; + } + } + + if (minutes > 0) { + timeStr.append(minutes).append("m"); + } + if (time > 0) { + timeStr.append(minutes > 0 ? " " : "").append(time).append("s"); + } + + return timeStr.toString(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/EventPlayer.java b/Practice/src/main/java/me/devkevin/practice/events/EventPlayer.java new file mode 100644 index 0000000..d8f5f1f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/EventPlayer.java @@ -0,0 +1,12 @@ +package me.devkevin.practice.events; + +import java.util.UUID; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class EventPlayer { + private final UUID uuid; + private final PracticeEvent event; +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/EventState.java b/Practice/src/main/java/me/devkevin/practice/events/EventState.java new file mode 100644 index 0000000..a2fffe9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/EventState.java @@ -0,0 +1,8 @@ +package me.devkevin.practice.events; + +public enum EventState { + + UNANNOUNCED, // The event hasn't even been announced yet + WAITING, // Waiting for players to join while the event counts down to start + STARTED // The event has started and is in progress +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/PracticeEvent.java b/Practice/src/main/java/me/devkevin/practice/events/PracticeEvent.java new file mode 100644 index 0000000..a46357e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/PracticeEvent.java @@ -0,0 +1,205 @@ +package me.devkevin.practice.events; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.event.EventStartEvent; +import me.devkevin.practice.events.oitc.OITCEvent; +import me.devkevin.practice.events.oitc.OITCPlayer; +import me.devkevin.practice.events.sumo.SumoEvent; +import me.devkevin.practice.events.sumo.SumoPlayer; +import me.devkevin.practice.events.tnttag.TNTTagEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +@Getter +@Setter +@RequiredArgsConstructor +public abstract class PracticeEvent { + private final Practice plugin = Practice.getInstance(); + + private final String name; + + private int limit = 30; + private Player host; + private EventState state = EventState.UNANNOUNCED; + + public void startCountdown() { + // Restart Logic + if (getCountdownTask().isEnded()) { + getCountdownTask().setTimeUntilStart(getCountdownTask().getCountdownTime()); + getCountdownTask().setEnded(false); + } else { + getCountdownTask().runTaskTimerAsynchronously(plugin, 20L, 20L); + } + } + + public void sendMessage(String message) { + getBukkitPlayers().forEach(player -> player.sendMessage(message)); + } + + public Set getBukkitPlayers() { + return getPlayers().keySet().stream() + .filter(uuid -> plugin.getServer().getPlayer(uuid) != null) + .map(plugin.getServer()::getPlayer) + .collect(Collectors.toSet()); + } + + public void join(Player player) { + + if(this.getPlayers().size() >= this.limit) { + return; + } + + Profile playerData = plugin.getProfileManager().getProfileData(player.getUniqueId()); + playerData.setState(ProfileState.EVENT); + + PlayerUtil.reset(player); + + if (onJoin() != null) { + onJoin().accept(player); + } + + if (this.getSpawnLocations().size() == 1) { + player.teleport(this.getSpawnLocations().get(0).toBukkitLocation()); + } else { + final List spawnLocations = new ArrayList<>(this.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + } + + this.plugin.getProfileManager().giveSpawnItems(player); + + for(Player other : this.getBukkitPlayers()) { + other.showPlayer(player); + player.showPlayer(other); + } + + + this.sendMessage(ChatColor.YELLOW + player.getName() + " has joined the event. (" + this.getPlayers().size() + " player" + (this.getPlayers().size() == 1 ? "": "s") + ")"); + } + + public void leave(Player player) { + + if(this instanceof OITCEvent) { + OITCEvent oitcEvent = (OITCEvent) this; + OITCPlayer oitcPlayer = oitcEvent.getPlayer(player); + oitcPlayer.setState(OITCPlayer.OITCState.ELIMINATED); + } + + if (onDeath() != null) { + onDeath().accept(player); + } + + getPlayers().remove(player.getUniqueId()); + + plugin.getProfileManager().sendToSpawn(player); + } + + public void start() { + + new EventStartEvent(this).call(); + + setState(EventState.STARTED); + + onStart(); + + this.plugin.getEventManager().setCooldown(0L); + } + + public void end() { + setState(EventState.UNANNOUNCED); + + Bukkit.getOnlinePlayers().forEach(player -> { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (profile.getState() == ProfileState.EVENT) { + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> + Bukkit.getWorld(this.getSpawnLocations().get(0).getWorld()).getPlayers().forEach(dsada -> + this.plugin.getProfileManager().sendToSpawn(player)), 2L); + } + }); + + this.plugin.getEventManager().setCooldown(System.currentTimeMillis() + (60 * 5) * 1000L); + + if (this instanceof SumoEvent) { + + SumoEvent sumoEvent = (SumoEvent) this; + for(SumoPlayer sumoPlayer : sumoEvent.getPlayers().values()) { + + if(sumoPlayer.getFightTask() != null) { + sumoPlayer.getFightTask().cancel(); + } + } + } else if (this instanceof TNTTagEvent) { + TNTTagEvent tntTagEvent = (TNTTagEvent)this; + + if (tntTagEvent.getTntTagTask() != null) { + tntTagEvent.getTntTagTask().cancel(); + tntTagEvent.setTntTagTask(null); + } + } + + getPlayers().clear(); + + Iterator iterator = this.plugin.getEventManager().getSpectators().iterator(); + + while(iterator.hasNext()) { + UUID spectatorUUID = iterator.next(); + Player spectator = Bukkit.getPlayer(spectatorUUID); + + if(spectator != null) { + this.plugin.getServer().getScheduler().runTask(this.plugin, () -> this.plugin.getProfileManager().sendToSpawn(spectator)); + iterator.remove(); + } + } + this.getBukkitPlayers().forEach(player -> this.plugin.getProfileManager().sendToSpawn(player)); + this.plugin.getEventManager().getSpectators().clear(); + this.getPlayers().clear(); + getCountdownTask().setEnded(true); + } + + public void handleWin(Player winner) { + Bukkit.broadcastMessage(""); + Bukkit.broadcastMessage( winner.getDisplayName() + CC.GREEN + " has won the " + CC.GREEN + CC.BOLD + name + CC.GREEN + " event!"); + Bukkit.broadcastMessage(""); + } + + public boolean isWaiting() { + return state == EventState.WAITING; + } + + public boolean isEnd() { + return state == EventState.UNANNOUNCED; + } + + public K getPlayer(Player player) { + return getPlayer(player.getUniqueId()); + } + + public K getPlayer(UUID uuid) { + return getPlayers().get(uuid); + } + + public abstract Map getPlayers(); + + public abstract EventCountdownTask getCountdownTask(); + + public abstract List getSpawnLocations(); + + public abstract void onStart(); + + public abstract Consumer onJoin(); + + public abstract Consumer onDeath(); +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/commands/EventManagerCommand.java b/Practice/src/main/java/me/devkevin/practice/events/commands/EventManagerCommand.java new file mode 100644 index 0000000..f966309 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/commands/EventManagerCommand.java @@ -0,0 +1,67 @@ +package me.devkevin.practice.events.commands; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.events.EventState; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 22/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EventManagerCommand extends PracticeCommand { + + @Command(name = "eventmanager", permission = Rank.ADMIN) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 2) { + player.sendMessage(CC.RED + "Usage: /eventmanager "); + return; + } + + String action = args[0]; + String eventName = args[1]; + + if (Practice.getInstance().getEventManager().getByName(eventName) == null) { + player.sendMessage(CC.RED + "That event doesn't exist."); + return; + } + + PracticeEvent event = Practice.getInstance().getEventManager().getByName(eventName); + + if(action.toUpperCase().equalsIgnoreCase("START") && event.getState() == EventState.WAITING) { + event.getCountdownTask().setTimeUntilStart(5); + player.sendMessage(CC.RED + "Event was force started."); + + } else if(action.toUpperCase().equalsIgnoreCase("END") && event.getState() == EventState.STARTED) { + event.end(); + player.sendMessage(CC.RED + "Event was cancelled."); + + } else if(action.toUpperCase().equalsIgnoreCase("STATUS")) { + + String[] message = new String[] { + CC.YELLOW + "Event: " + CC.WHITE + event.getName(), + CC.YELLOW + "Host: " + CC.WHITE + (event.getHost() == null ? "Player Left" : event.getHost().getName()), + CC.YELLOW + "Players: " + CC.WHITE + event.getPlayers().size() + "/" + event.getLimit(), + CC.YELLOW + "State: " + CC.WHITE + event.getState().name(), + }; + + player.sendMessage(message); + + } else if(action.toUpperCase().equalsIgnoreCase("COOLDOWN")) { + + Practice.getInstance().getEventManager().setCooldown(0L); + player.sendMessage(CC.RED + "Event cooldown was cancelled."); + } else { + player.sendMessage(CC.RED + "Usage: /eventmanager "); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/commands/HostCommand.java b/Practice/src/main/java/me/devkevin/practice/events/commands/HostCommand.java new file mode 100644 index 0000000..2de1fb9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/commands/HostCommand.java @@ -0,0 +1,91 @@ +package me.devkevin.practice.events.commands; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.events.EventState; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.events.sumo.SumoEvent; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 22/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class HostCommand extends PracticeCommand { + + @Command(name = "hostevent", permission = Rank.GOLD) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (args.length < 1) { + player.sendMessage(CC.RED + "Usage: /hostevent "); + return; + } + + String eventName = args[0]; + + if (eventName == null) { + return; + } + + if (Practice.getInstance().getEventManager().getByName(eventName) == null) { + player.sendMessage(CC.RED + "That event doesn't exist."); + player.sendMessage(CC.RED + "Available events: Sumo, OITC"); + return; + } + + if(System.currentTimeMillis() < Practice.getInstance().getEventManager().getCooldown()) { + player.sendMessage(CC.RED + "There is a cooldown. Event can't start at this moment."); + return; + } + + PracticeEvent event = Practice.getInstance().getEventManager().getByName(eventName); + if (event.getState() != EventState.UNANNOUNCED) { + player.sendMessage(CC.RED + "There is currently an active event."); + return; + } + + boolean eventBeingHosted = Practice.getInstance().getEventManager().getEvents().values().stream().anyMatch(e -> e.getState() != EventState.UNANNOUNCED); + if (eventBeingHosted) { + player.sendMessage(CC.RED + "There is currently an active event."); + return; + } + + + String toSend = CC.YELLOW + CC.BOLD + "(Event) " + CC.GREEN + "" + event.getName() + " is starting soon. " + CC.GRAY + "[Click to Join]"; + String toSendDonor = CC.GRAY + "[" + profile.getGrant().getRank().getColor() + CC.BOLD + "*" + CC.GRAY + "] " + profile.getGrant().getRank().getColor() + CC.BOLD + player.getName() + CC.WHITE + " is hosting a " + profile.getGrant().getRank().getColor() + CC.BOLD + event.getName() + " Event. " + CC.GRAY + "[Click to Join]"; + + + Clickable message = new Clickable(player.hasPermission("practice.donors.gold") ? toSendDonor : toSend, + CC.GRAY + "Click to join this event.", + "/join " + event.getName()); + Practice.getInstance().getServer().getOnlinePlayers().forEach(message::sendToPlayer); + + if (player.hasPermission("practice.admin")) { + event.setLimit(event instanceof SumoEvent ? 100 : 50); + } else if(player.hasPermission("practice.donors.udrop")) { + event.setLimit(event instanceof SumoEvent ? 50 : 30); + } else if(player.hasPermission("practice.donors.diamond")) { + event.setLimit(event instanceof SumoEvent ? 40 : 25); + } else if(player.hasPermission("practice.donors.emerald")) { + event.setLimit(event instanceof SumoEvent ? 35 : 25); + } else if(player.hasPermission("practice.donors.gold")) { + event.setLimit(event instanceof SumoEvent ? 30 : 20); + } else { + event.setLimit(30); + } + + Practice.getInstance().getEventManager().hostEvent(event, player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/commands/HostEventCommand.java b/Practice/src/main/java/me/devkevin/practice/events/commands/HostEventCommand.java new file mode 100644 index 0000000..9093fda --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/commands/HostEventCommand.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.events.commands; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 26/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class HostEventCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "host") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + + player.openInventory(this.plugin.getHostMenu().getHostMenu().getCurrentPage()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/commands/JoinEventCommand.java b/Practice/src/main/java/me/devkevin/practice/events/commands/JoinEventCommand.java new file mode 100644 index 0000000..6850d24 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/commands/JoinEventCommand.java @@ -0,0 +1,62 @@ +package me.devkevin.practice.events.commands; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.events.EventState; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 22/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class JoinEventCommand extends PracticeCommand { + + @Command(name = "join") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 1) { + player.sendMessage(CC.RED + "Usage: /join "); + return; + } + + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (Practice.getInstance().getPartyManager().getParty(profile.getUuid()) != null || (profile.getState() != ProfileState.SPAWN)) { + player.sendMessage(CC.RED + "Cannot execute this command in your current state."); + return; + } + + String eventName = args[0]; + + if (eventName == null) { + return; + } + + if (Practice.getInstance().getEventManager().getByName(eventName) == null) { + player.sendMessage(CC.RED + eventName + " doesn't exist."); + return; + } + + PracticeEvent event = Practice.getInstance().getEventManager().getByName(eventName); + if (event.getState() != EventState.WAITING) { + player.sendMessage(CC.RED + "You cannot join this event!"); + return; + } + + if (event.getPlayers().containsKey(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are already playing " + event.getName() + "!"); + return; + } + + event.join(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/commands/LeaveEventCommand.java b/Practice/src/main/java/me/devkevin/practice/events/commands/LeaveEventCommand.java new file mode 100644 index 0000000..ed6b23a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/commands/LeaveEventCommand.java @@ -0,0 +1,47 @@ +package me.devkevin.practice.events.commands; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 23/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class LeaveEventCommand extends PracticeCommand { + + @Command(name = "leave") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + boolean isInEvent = Practice.getInstance().getEventManager().getEventPlaying(player) != null; + + if (isInEvent) { + leaveEvent(player); + } else { + player.sendMessage(CC.RED + "There is nothing to leave."); + } + } + + private void leaveEvent(Player player) { + PracticeEvent event = Practice.getInstance().getEventManager().getEventPlaying(player); + + if (event == null) { + player.sendMessage(CC.RED + "That event doesn't exist."); + return; + } + + if(!Practice.getInstance().getEventManager().isPlaying(player, event)) { + player.sendMessage(CC.RED + "You are not in an event."); + return; + } + + event.leave(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/event/BaseEvent.java b/Practice/src/main/java/me/devkevin/practice/events/event/BaseEvent.java new file mode 100644 index 0000000..9bca359 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/event/BaseEvent.java @@ -0,0 +1,26 @@ +package me.devkevin.practice.events.event; + +import org.bukkit.Bukkit; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BaseEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public boolean call() { + Bukkit.getServer().getPluginManager().callEvent(this); + return this instanceof Cancellable && ((Cancellable) this).isCancelled(); + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/event/EventStartEvent.java b/Practice/src/main/java/me/devkevin/practice/events/event/EventStartEvent.java new file mode 100644 index 0000000..43f8de8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/event/EventStartEvent.java @@ -0,0 +1,17 @@ +package me.devkevin.practice.events.event; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.events.PracticeEvent; + +/** + * Copyright 22/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@RequiredArgsConstructor +public class EventStartEvent extends BaseEvent { + private final PracticeEvent event; +} + diff --git a/Practice/src/main/java/me/devkevin/practice/events/lms/LMSCountdownTask.java b/Practice/src/main/java/me/devkevin/practice/events/lms/LMSCountdownTask.java new file mode 100644 index 0000000..30239e4 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/lms/LMSCountdownTask.java @@ -0,0 +1,37 @@ +package me.devkevin.practice.events.lms; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; + +import java.util.Arrays; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class LMSCountdownTask extends EventCountdownTask { + + public LMSCountdownTask(PracticeEvent event) { + super(event, 45); + } + + @Override + public boolean shouldAnnounce(int timeUntilStart) { + return Arrays.asList(90, 60, 30, 15, 10, 5).contains(timeUntilStart); + } + + @Override + public boolean canStart() { + return getEvent().getPlayers().size() >= 2; + } + + @Override + public void onCancel() { + getEvent().sendMessage(CC.RED + "There were not enough players to start the event."); + getEvent().end(); + getEvent().getPlugin().getEventManager().setCooldown(0L); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/events/lms/LMSEvent.java b/Practice/src/main/java/me/devkevin/practice/events/lms/LMSEvent.java new file mode 100644 index 0000000..25017d1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/lms/LMSEvent.java @@ -0,0 +1,187 @@ +package me.devkevin.practice.events.lms; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class LMSEvent extends PracticeEvent { + + private final Map players = new HashMap<>(); + private final LMSCountdownTask countdownTask = new LMSCountdownTask(this); + private LMSEvent.LMSGameTask gameTask; + + public LMSEvent() { + super("LMS"); + } + + @Override + public Map getPlayers() { + return players; + } + + @Override + public EventCountdownTask getCountdownTask() { + return countdownTask; + } + + @Override + public List getSpawnLocations() { + return getPlugin().getCustomLocationManager().getLmsLocations(); + } + + @Override + public void onStart() { + gameTask = new LMSGameTask(); + gameTask.runTaskTimerAsynchronously(getPlugin(), 0, 20L); + } + + public void cancelAll() { + if(gameTask != null) { + gameTask.cancel(); + } + } + + @Override + public Consumer onJoin() { + return player -> players.put(player.getUniqueId(), new LMSPlayer(player.getUniqueId(), this)); + } + + @Override + public Consumer onDeath() { + return player -> { + LMSPlayer data = getPlayer(player); + + if(data.getState() != LMSPlayer.LMSState.FIGHTING) { + return; + } + + Player killer = player.getKiller(); + + data.setState(LMSPlayer.LMSState.ELIMINATED); + + getPlugin().getServer().getScheduler().runTask(getPlugin(), () -> { + getPlugin().getProfileManager().sendToSpawn(player); + if(getPlayers().size() >= 2) { + getPlugin().getEventManager().addSpectatorLMS(player, getPlugin().getProfileManager().getProfileData(player.getUniqueId()), this); + } + }); + + getPlayers().remove(player.getUniqueId()); + + sendMessage(CC.GOLD + CC.BOLD + "(LMS) " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GREEN + " has been eliminated"); + player.sendMessage(""); + player.sendMessage(CC.RED + "You have been eliminated from the event. Better luck next time!"); + if (!player.hasPermission("practice.donors.gold")) { + player.sendMessage(CC.GRAY + "Purchase a rank at https://udrop.buycraft.net/ to host events of your own."); + } + player.sendMessage(""); + + if(getByState(LMSPlayer.LMSState.FIGHTING).size() == 1) { + Player winner = Bukkit.getPlayer(getByState(LMSPlayer.LMSState.FIGHTING).get(0)); + if(winner != null) { + handleWin(winner); + } + + end(); + cancelAll(); + } + }; + } + + private Player getRandomPlayer() { + if(getByState(LMSPlayer.LMSState.FIGHTING).size() == 0) { + return null; + } + + List fighting = getByState(LMSPlayer.LMSState.FIGHTING); + + Collections.shuffle(fighting); + + UUID uuid = fighting.get(ThreadLocalRandom.current().nextInt(fighting.size())); + + return getPlugin().getServer().getPlayer(uuid); + } + + public List getByState(LMSPlayer.LMSState state) { + return players.values().stream().filter(player -> player.getState() == state).map(LMSPlayer::getUuid).collect(Collectors.toList()); + } + /** + * To ensure that the fight does not go on forever and to + * let the players know how much time they have left. + */ + @Getter + @RequiredArgsConstructor + public class LMSGameTask extends BukkitRunnable { + + private int time = 303; + + @Override + public void run() { + if(time == 303) { + PlayerUtil.sendMessage(CC.D_RED + "3...", getBukkitPlayers()); + } else if(time == 302) { + PlayerUtil.sendMessage(CC.RED + "2...", getBukkitPlayers()); + } else if(time == 301) { + PlayerUtil.sendMessage(CC.YELLOW + "1...", getBukkitPlayers()); + } else if(time == 300) { + PlayerUtil.sendMessage(CC.GREEN + "Go!", getBukkitPlayers()); + getPlayers().values().forEach(player -> player.setState(LMSPlayer.LMSState.FIGHTING)); + getBukkitPlayers().forEach(LMSEvent.this::handleInventory); + } else if(time <= 0) { + Player winner = getRandomPlayer(); + + if(winner != null) { + handleWin(winner); + } + + end(); + cancel(); + return; + } + + if(getPlayers().size() == 1) { + Player winner = Bukkit.getPlayer(getByState(LMSPlayer.LMSState.FIGHTING).get(0)); + + if(winner != null) { + handleWin(winner); + } + + end(); + cancel(); + return; + } + + if(Arrays.asList(60, 50, 40, 30, 25, 20, 15, 10).contains(time)) { + sendMessage(CC.GOLD + CC.BOLD + "(LMS) " + CC.GREEN + "Game ends in " + CC.RESET + time + " seconds" + CC.GREEN + "."); + } else if(Arrays.asList(5, 4, 3, 2, 1).contains(time)) { + sendMessage(CC.GOLD + CC.BOLD + "(LMS) " + CC.GREEN + "Game is ending in " + CC.RESET + time + " seconds" + CC.GREEN + "."); + } + + time--; + } + } + + private void handleInventory(Player player) { + //Practice.getInstance().getKitManager().getKit("NoDebuff").applyToPlayer(player); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/events/lms/LMSPlayer.java b/Practice/src/main/java/me/devkevin/practice/events/lms/LMSPlayer.java new file mode 100644 index 0000000..f0f4201 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/lms/LMSPlayer.java @@ -0,0 +1,31 @@ +package me.devkevin.practice.events.lms; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.events.EventPlayer; +import me.devkevin.practice.events.PracticeEvent; + +import java.util.UUID; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Setter +@Getter +public class LMSPlayer extends EventPlayer { + + private LMSState state = LMSState.WAITING; + + public LMSPlayer(UUID uuid, PracticeEvent event) { + super(uuid, event); + } + + public enum LMSState { + WAITING, + FIGHTING, + ELIMINATED + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/events/manager/EventManager.java b/Practice/src/main/java/me/devkevin/practice/events/manager/EventManager.java new file mode 100644 index 0000000..404d0c0 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/manager/EventManager.java @@ -0,0 +1,270 @@ +package me.devkevin.practice.events.manager; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.EventState; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.events.lms.LMSEvent; +import me.devkevin.practice.events.oitc.OITCEvent; +import me.devkevin.practice.events.sumo.SumoEvent; +import me.devkevin.practice.events.tntrun.TntRunEvent; +import me.devkevin.practice.events.tnttag.TNTTagEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.bukkit.GameMode; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + +@Getter +public class EventManager { + private final Map, PracticeEvent> events = new HashMap<>(); + + private final Practice plugin = Practice.getInstance(); + + private List spectators; + + @Setter private long cooldown; + private final World eventWorld; + + public EventManager() { + Arrays.asList( + SumoEvent.class, + OITCEvent.class, + TNTTagEvent.class, + TntRunEvent.class, + LMSEvent.class + ).forEach(clazz -> this.addEvent(clazz)); + + boolean newWorld; + eventWorld = plugin.getServer().getWorld("event"); + newWorld = false; + + this.spectators = new ArrayList<>(); + + this.cooldown = 0L; + + if (eventWorld != null) { + + if (newWorld) { + plugin.getServer().getWorlds().add(eventWorld); + } + + eventWorld.setTime(2000L); + eventWorld.setGameRuleValue("doDaylightCycle", "false"); + eventWorld.setGameRuleValue("doMobSpawning", "false"); + eventWorld.setStorm(false); + eventWorld.getEntities().stream().filter(entity -> !(entity instanceof Player)).forEach(Entity::remove); + } + } + + public PracticeEvent getByName(String name) { + return events.values().stream().filter(event -> event.getName().toLowerCase().equalsIgnoreCase(name.toLowerCase())).findFirst().orElse(null); + } + + public void addSpectatorLMS(Player player, Profile profile, LMSEvent event) { + if(player.isDead()) { + player.setHealth(20.0); + } + + this.addSpectator(player, profile, event); + + List spawnLocations = new ArrayList<>(event.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + + player.setGameMode(GameMode.ADVENTURE); + + player.setAllowFlight(true); + player.setFlying(true); + } + + + public void hostEvent(PracticeEvent event, Player host) { + + event.setState(EventState.WAITING); + event.setHost(host); + event.startCountdown(); + } + + private void addEvent(Class clazz) { + PracticeEvent event = null; + + try { + event = clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + e.printStackTrace(); + } + + events.put(clazz, event); + } + + public void addSpectatorSumo(Player player, Profile playerData, SumoEvent event) { + + this.addSpectator(player, playerData, event); + + player.teleport(Practice.getInstance().getCustomLocationManager().getSumoLocation().toBukkitLocation()); + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + } + + public void addSpectatorOITC(Player player, Profile playerData, OITCEvent event) { + + this.addSpectator(player, playerData, event); + + if (event.getSpawnLocations().size() == 1) { + player.teleport(event.getSpawnLocations().get(0).toBukkitLocation()); + } else { + List spawnLocations = new ArrayList<>(event.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + } + + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + } + + public void addSpectator(Player player, Profile playerData, PracticeEvent event) { + + + this.spectators.add(player.getUniqueId()); + + playerData.setState(ProfileState.SPECTATING); + + player.setAllowFlight(true); + player.setFlying(true); + + player.getInventory().setContents(this.plugin.getHotbarItem().getSpecItems()); + player.updateInventory(); + + this.plugin.getServer().getOnlinePlayers().forEach(online -> { + online.hidePlayer(player); + player.hidePlayer(online); + }); + + } + + public void addSpectatorTNTTag(Player player, Profile profile, TNTTagEvent event) { + + this.addSpectator(player, profile, event); + + if (event.getSpawnLocations().size() == 1) { + player.teleport(event.getSpawnLocations().get(0).toBukkitLocation()); + } else { + List spawnLocations = new ArrayList<>(event.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + } + + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + + player.setGameMode(GameMode.SPECTATOR); + + player.setAllowFlight(true); + player.setFlying(true); + } + + public void addDeathSpectatorTntTag(Player player, Profile profile, TNTTagEvent event) { + + this.plugin.getServer().getOnlinePlayers().forEach(online -> { + online.hidePlayer(player); + player.hidePlayer(online); + }); + + if (event.getSpawnLocations().size() == 1) { + player.teleport(event.getSpawnLocations().get(0).toBukkitLocation()); + } else { + List spawnLocations = new ArrayList<>(event.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + } + + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + + player.setGameMode(GameMode.SURVIVAL); + + player.setAllowFlight(true); + player.setFlying(true); + } + + public void addSpectatorTNTRun(Player player, Profile profile, TntRunEvent event) { + + this.addSpectator(player, profile, event); + + if (event.getSpawnLocations().size() == 1) { + player.teleport(event.getSpawnLocations().get(0).toBukkitLocation()); + } else { + List spawnLocations = new ArrayList<>(event.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + } + + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + + player.setGameMode(GameMode.SURVIVAL); + + player.setAllowFlight(true); + player.setFlying(true); + } + + public void addDeathSpectatorTntRun(Player player, Profile profile, TntRunEvent event) { + + this.plugin.getServer().getOnlinePlayers().forEach(online -> { + online.hidePlayer(player); + player.hidePlayer(online); + }); + + if (event.getSpawnLocations().size() == 1) { + player.teleport(event.getSpawnLocations().get(0).toBukkitLocation()); + } else { + List spawnLocations = new ArrayList<>(event.getSpawnLocations()); + player.teleport(spawnLocations.remove(ThreadLocalRandom.current().nextInt(spawnLocations.size())).toBukkitLocation()); + } + + + for(Player eventPlayer : event.getBukkitPlayers()) { + player.showPlayer(eventPlayer); + } + + player.setGameMode(GameMode.SURVIVAL); + + player.setAllowFlight(true); + player.setFlying(true); + } + + + private void showPlayers() { + + } + + public void removeSpectator(Player player) { + this.getSpectators().remove(player.getUniqueId()); + this.plugin.getProfileManager().sendToSpawn(player); + } + + + public boolean isPlaying(Player player, PracticeEvent event) { + return event.getPlayers().containsKey(player.getUniqueId()); + } + + public PracticeEvent getEventPlaying(Player player) { + return this.events.values().stream().filter(event -> this.isPlaying(player, event)).findFirst().orElse(null); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/events/menu/HostMenu.java b/Practice/src/main/java/me/devkevin/practice/events/menu/HostMenu.java new file mode 100644 index 0000000..a75af7b --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/menu/HostMenu.java @@ -0,0 +1,219 @@ +package me.devkevin.practice.events.menu; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.Arrays; + +import static me.devkevin.practice.util.PlayerUtil.PLACEHOLDER_ITEM; + +/** + * Copyright 23/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class HostMenu { + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI hostMenu = new InventoryUI(CC.DARK_RED + "Host an event", true, 5); + + public HostMenu() { + this.hostMenu(); + } + + private void hostMenu() { + for (int i = 0; i < 9 * 5; i++) { + this.hostMenu.setItem(i, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM)); + } + + this.hostMenu.setItem(0, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.BED) + .name(CC.RED + "Back to General") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.openInventory(plugin.getGeneralSettingMenu().getGeneralMenu().getCurrentPage()); + } + }); + + this.hostMenu.setItem(11, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEASH).name(CC.DARK_RED + "Sumo") + .lore(Arrays.asList( + "", + CC.GRAY + "Knock your opponent off", + CC.GRAY + "the platform until you", + CC.GRAY + "are the last player alive", + "", + CC.RED + "Needed rank: " + CC.GOLD + "Gold", + "", + CC.GREEN + "Click here to host..." + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (!player.hasPermission("practice.donors.gold")) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot host this event with " + profile.getGrant().getRank().getColor() + profile.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase the Gold rank at https://store.inverted.club/ to host events on your own."); + player.sendMessage(""); + return; + } + + player.performCommand("hostevent sumo"); + } + }); + + this.hostMenu.setItem(13, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.TNT).name(CC.DARK_RED + "TnTTag") + .lore(Arrays.asList( + "", + CC.GRAY + "Knock your opponent with", + CC.GRAY + "the TNT before explode until", + CC.GRAY + "you are the last player alive", + "", + CC.RED + "Needed rank: " + CC.DARK_GREEN + "Emerald", + "", + CC.GREEN + "Click here to host...", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + CoreProfile profile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (!player.hasPermission("practice.donors.emerald")) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot host this event with " + profile.getGrant().getRank().getColor() + profile.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase the Emerald rank at https://store.inverted.club/ to host events on your own."); + player.sendMessage(""); + return; + } + + //player.performCommand("hostevent TnTTag"); + } + }); + + this.hostMenu.setItem(15, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.REDSTONE_BLOCK).name(CC.RED + CC.BOLD + "???") + .lore(Arrays.asList( + "", + CC.GRAY + "Under development", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.sendMessage(CC.RED + "Under development"); + /*Profile profile = Profile.getByUuid(player.getUniqueId()); + + if (!profile.getRank().hasRank(Rank.GOLD)) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot host this event with " + profile.getRank().getColor() + profile.getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase the Gold rank at store.udrop.club to host events on your own."); + player.sendMessage(""); + return; + } + + player.performCommand("host sumo");*/ + } + }); + + this.hostMenu.setItem(29, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.REDSTONE_BLOCK).name(CC.RED + CC.BOLD + "???") + .lore(Arrays.asList( + "", + CC.GRAY + "Under development", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.sendMessage(CC.RED + "Under development"); + /*Profile profile = Profile.getByUuid(player.getUniqueId()); + + if (!profile.getRank().hasRank(Rank.GOLD)) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot host this event with " + profile.getRank().getColor() + profile.getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase the Gold rank at store.udrop.club to host events on your own."); + player.sendMessage(""); + return; + } + + player.performCommand("host sumo");*/ + } + }); + + this.hostMenu.setItem(31, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.REDSTONE_BLOCK).name(CC.RED + CC.BOLD + "???") + .lore(Arrays.asList( + "", + CC.GRAY + "Under development", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.sendMessage(CC.RED + "Under development"); + /*Profile profile = Profile.getByUuid(player.getUniqueId()); + + if (!profile.getRank().hasRank(Rank.GOLD)) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot host this event with " + profile.getRank().getColor() + profile.getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase the Gold rank at store.udrop.club to host events on your own."); + player.sendMessage(""); + return; + } + + player.performCommand("host sumo");*/ + } + }); + + this.hostMenu.setItem(33, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.REDSTONE_BLOCK).name(CC.RED + CC.BOLD + "???") + .lore(Arrays.asList( + "", + CC.GRAY + "Under development", + "" + )) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.sendMessage(CC.RED + "Under development"); + /*Profile profile = Profile.getByUuid(player.getUniqueId()); + + if (!profile.getRank().hasRank(Rank.GOLD)) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot host this event with " + profile.getRank().getColor() + profile.getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase the Gold rank at store.udrop.club to host events on your own."); + player.sendMessage(""); + return; + } + + player.performCommand("host sumo");*/ + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCCountdownTask.java b/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCCountdownTask.java new file mode 100644 index 0000000..fe24189 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCCountdownTask.java @@ -0,0 +1,30 @@ +package me.devkevin.practice.events.oitc; + +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import org.bukkit.ChatColor; +import java.util.Arrays; + +public class OITCCountdownTask extends EventCountdownTask { + + public OITCCountdownTask(PracticeEvent event) { + super(event, 60); + } + + @Override + public boolean shouldAnnounce(int timeUntilStart) { + return Arrays.asList(45, 30, 15, 10, 5).contains(timeUntilStart); + } + + @Override + public boolean canStart() { + return getEvent().getPlayers().size() >= 2; + } + + @Override + public void onCancel() { + getEvent().sendMessage(ChatColor.RED + "Not enough players. Event has been cancelled"); + getEvent().end(); + this.getEvent().getPlugin().getEventManager().setCooldown(0L); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCEvent.java b/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCEvent.java new file mode 100644 index 0000000..05e7314 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCEvent.java @@ -0,0 +1,361 @@ +package me.devkevin.practice.events.oitc; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.*; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class OITCEvent extends PracticeEvent { + + private final Map players = new HashMap<>(); + + @Getter private OITCGameTask gameTask = null; + private final OITCCountdownTask countdownTask = new OITCCountdownTask(this); + private List respawnLocations; + + public OITCEvent() { + super("OITC"); + } + + @Override + public Map getPlayers() { + return players; + } + + @Override + public EventCountdownTask getCountdownTask() { + return countdownTask; + } + + @Override + public List getSpawnLocations() { + return Collections.singletonList(this.getPlugin().getCustomLocationManager().getOitcLocation()); + } + + @Override + public void onStart() { + this.respawnLocations = new ArrayList<>(); + this.gameTask = new OITCGameTask(); + this.gameTask.runTaskTimerAsynchronously(getPlugin(), 0, 20); + } + + @Override + public Consumer onJoin() { + return player -> players.put(player.getUniqueId(), new OITCPlayer(player.getUniqueId(), this)); + } + + @Override + public Consumer onDeath() { + + return player -> { + + OITCPlayer data = getPlayer(player); + + if (data == null) { + return; + } + + if(data.getState() == OITCPlayer.OITCState.WAITING) { + return; + } + + if(data.getState() == OITCPlayer.OITCState.ELIMINATED) { + if (this.getByState(OITCPlayer.OITCState.FIGHTING).size() == 1 || this.getPlayers().size() == 1) { + Player winner = Bukkit.getPlayer(this.getByState(OITCPlayer.OITCState.FIGHTING).get(0)); + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + winnerData.setOitcWins(winnerData.getOitcWins() + 1); + + for (int i = 0; i <= 2; i++) { + String announce = ChatColor.YELLOW + "(Event) " + ChatColor.GREEN.toString() + "Winner: " + winner.getName(); + Bukkit.broadcastMessage(announce); + } + + this.gameTask.cancel(); + end(); + } + return; + } + + if(data.getState() == OITCPlayer.OITCState.FIGHTING || data.getState() == OITCPlayer.OITCState.PREPARING || data.getState() == OITCPlayer.OITCState.RESPAWNING) { + + String deathMessage = ChatColor.YELLOW + "(Event) " + ChatColor.RED + player.getName() + "(" + data.getScore() + ")" + ChatColor.GRAY + " has been eliminated from the game."; + + if(data.getLastKiller() != null) { + + OITCPlayer killerData = data.getLastKiller(); + Player killer = getPlugin().getServer().getPlayer(killerData.getUuid()); + + int count = killerData.getScore() + 1; + killerData.setScore(count); + + killer.getInventory().setItem(6, ItemUtil.createItem(Material.GLOWSTONE_DUST, ChatColor.YELLOW.toString() + ChatColor.BOLD + "Kills", killerData.getScore() == 0 ? 1 : killerData.getScore())); + if(killer.getInventory().contains(Material.ARROW)) { + killer.getInventory().getItem(8).setAmount(killer.getInventory().getItem(8).getAmount() + 2); + } else { + killer.getInventory().setItem(8, new ItemStack(Material.ARROW, 2)); + } + killer.updateInventory(); + + killer.playSound(killer.getLocation(), Sound.NOTE_PLING, 1F, 1F); + + FireworkEffect fireworkEffect = FireworkEffect.builder().withColor(Color.fromRGB(127, 56, 56)).withFade(Color.fromRGB(127, 56, 56)).with(FireworkEffect.Type.BALL).build(); + PlayerUtil.sendFirework(fireworkEffect, player.getLocation().add(0, 1.5, 0)); + + data.setLastKiller(null); + + deathMessage = ChatColor.YELLOW + "(Event) " + ChatColor.RED + player.getName() + "(" + data.getScore() + ")" + ChatColor.GRAY + " has been killed" + (killer == null ? "." : " by " + ChatColor.GREEN + killer.getName() + "(" + count + ")"); + + if (count == 25) { + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(killer.getUniqueId()); + winnerData.setOitcWins(winnerData.getOitcWins() + 1); + + for (int i = 0; i <= 2; i++) { + String announce = ChatColor.YELLOW + "(Event) " + ChatColor.GREEN.toString() + "Winner: " + killer.getName(); + Bukkit.broadcastMessage(announce); + } + + this.gameTask.cancel(); + end(); + } + } + + if (data.getLastKiller() == null) { + // Respawn the player + data.setLives((data.getLives() - 1)); + + Profile playerData = this.getPlugin().getProfileManager().getProfileData(player.getUniqueId()); + playerData.setOitcKills(playerData.getOitcKills() + data.getScore()); + playerData.setOitcDeaths(playerData.getOitcDeaths() + 1); + + if(data.getLives() == 0) { + + playerData.setOitcLosses(playerData.getOitcLosses() + 1); + getPlayers().remove(player.getUniqueId()); + + player.sendMessage(ChatColor.YELLOW + "(Event) " + ChatColor.GRAY + "You have been eliminated from the game."); + + getPlugin().getServer().getScheduler().runTask(getPlugin(), () -> { + getPlugin().getProfileManager().sendToSpawn(player); + if(getPlayers().size() >= 2) { + getPlugin().getEventManager().addSpectatorOITC(player, getPlugin().getProfileManager().getProfileData(player.getUniqueId()), OITCEvent.this); + } + }); + } else { + BukkitTask respawnTask = new RespawnTask(player, data).runTaskTimerAsynchronously(getPlugin(), 0, 20); + data.setRespawnTask(respawnTask); + } + } + + sendMessage(deathMessage); + + if (this.getByState(OITCPlayer.OITCState.FIGHTING).size() == 1 || this.getPlayers().size() == 1) { + Player winner = Bukkit.getPlayer(this.getByState(OITCPlayer.OITCState.FIGHTING).get(0)); + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + winnerData.setOitcWins(winnerData.getOitcWins() + 1); + + for (int i = 0; i <= 2; i++) { + String announce = ChatColor.YELLOW + "(Event) " + ChatColor.GREEN.toString() + "Winner: " + winner.getName(); + Bukkit.broadcastMessage(announce); + } + + this.gameTask.cancel(); + end(); + } + } + }; + } + + public void teleportNextLocation(Player player) { + player.teleport(getGameLocations().remove(ThreadLocalRandom.current().nextInt(getGameLocations().size())).toBukkitLocation()); + } + + private List getGameLocations() { + + if(this.respawnLocations != null && this.respawnLocations.size() == 0) { + this.respawnLocations.addAll(this.getPlugin().getCustomLocationManager().getOitcSpawnpoints()); + } + + return this.respawnLocations; + } + + private void giveRespawnItems(Player player, OITCPlayer oitcPlayer) { + + this.getPlugin().getServer().getScheduler().runTask(this.getPlugin(), () -> { + PlayerUtil.reset(player); + player.getInventory().setItem(0, ItemUtil.createItem(Material.WOOD_SWORD, ChatColor.GREEN + "Wood Sword")); + player.getInventory().setItem(1, ItemUtil.createItem(Material.BOW, ChatColor.GREEN + "Bow")); + player.getInventory().setItem(6, ItemUtil.createItem(Material.GLOWSTONE_DUST, ChatColor.YELLOW.toString() + ChatColor.BOLD + "Kills", oitcPlayer.getScore() == 0 ? 1 : oitcPlayer.getScore())); + player.getInventory().setItem(7, ItemUtil.createItem(Material.REDSTONE, ChatColor.RED.toString() + ChatColor.BOLD + "Lives", oitcPlayer.getLives())); + player.getInventory().setItem(8, new ItemStack(Material.ARROW)); + player.updateInventory(); + }); + } + + private Player getRandomPlayer() { + + if(getByState(OITCPlayer.OITCState.FIGHTING).size() == 0) { + return null; + } + + List fighting = getByState(OITCPlayer.OITCState.FIGHTING); + + Collections.shuffle(fighting); + + UUID uuid = fighting.get(ThreadLocalRandom.current().nextInt(fighting.size())); + + return getPlugin().getServer().getPlayer(uuid); + } + + public List getByState(OITCPlayer.OITCState state) { + return players.values().stream().filter(player -> player.getState() == state).map(OITCPlayer::getUuid).collect(Collectors.toList()); + } + + @Getter + @RequiredArgsConstructor + public class RespawnTask extends BukkitRunnable { + + private final Player player; + private final OITCPlayer oitcPlayer; + private int time = 5; + + @Override + public void run() { + + if(oitcPlayer.getLives() == 0) { + cancel(); + return; + } + + if(time > 0) { + player.sendMessage(ChatColor.YELLOW + "(Event) " + ChatColor.GRAY + "Respawning in " + time + "..."); + } + + if(time == 5) { + getPlugin().getServer().getScheduler().runTask(getPlugin(), () -> { + PlayerUtil.reset(player); + getBukkitPlayers().forEach(member -> member.hidePlayer(player)); + }); + + oitcPlayer.setState(OITCPlayer.OITCState.RESPAWNING); + + } else if(time <= 0) { + player.sendMessage(ChatColor.YELLOW + "(Event) " + ChatColor.GRAY + "Respawning..."); + player.sendMessage(ChatColor.YELLOW + "(Event) " + ChatColor.RED.toString() + ChatColor.BOLD + oitcPlayer.getLives() + " " + (oitcPlayer.getLives() == 1 ? "LIFE" : "LIVES") + " REMAINING"); + + + getPlugin().getServer().getScheduler().runTaskLater(getPlugin(), () -> { + giveRespawnItems(player, oitcPlayer); + player.teleport(getGameLocations().remove(ThreadLocalRandom.current().nextInt(getGameLocations().size())).toBukkitLocation()); + getBukkitPlayers().forEach(member -> member.showPlayer(player)); + }, 2L); + + oitcPlayer.setState(OITCPlayer.OITCState.FIGHTING); + + cancel(); + } + + time--; + + } + } + + /** + * To ensure that the fight doesn't go on forever and to + * let the players know how much time they have left. + */ + @Getter + @RequiredArgsConstructor + public class OITCGameTask extends BukkitRunnable { + + private int time = 303; + + @Override + public void run() { + // Make sure we don't get a fuck ton of NPEs + + if (time == 303) { + PlayerUtil.sendMessage(ChatColor.YELLOW + "The game starts in " + ChatColor.GREEN + 3 + ChatColor.YELLOW + "...", getBukkitPlayers()); + } else if (time == 302) { + PlayerUtil.sendMessage(ChatColor.YELLOW + "The game starts in " + ChatColor.GREEN + 2 + ChatColor.YELLOW + "...", getBukkitPlayers()); + } else if (time == 301) { + PlayerUtil.sendMessage(ChatColor.YELLOW + "The game starts in " + ChatColor.GREEN + 1 + ChatColor.YELLOW + "...", getBukkitPlayers()); + } else if (time == 300) { + PlayerUtil.sendMessage(ChatColor.GREEN + "The game has started, good luck!", getBukkitPlayers()); + + for(OITCPlayer player : getPlayers().values()) { + player.setScore(0); + player.setLives(5); + player.setState(OITCPlayer.OITCState.FIGHTING); + } + + for(Player player : getBukkitPlayers()) { + + OITCPlayer oitcPlayer = getPlayer(player.getUniqueId()); + + if(oitcPlayer != null) { + teleportNextLocation(player); + giveRespawnItems(player, oitcPlayer); + } + } + + } else if (time <= 0) { + + Player winner = getRandomPlayer(); + + if(winner != null) { + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + winnerData.setOitcWins(winnerData.getOitcWins() + 1); + + for (int i = 0; i <= 2; i++) { + String announce = ChatColor.YELLOW + "(Event) " + ChatColor.GREEN.toString() + "Winner: " + winner.getName(); + Bukkit.broadcastMessage(announce); + } + } + + gameTask.cancel(); + end(); + cancel(); + return; + } + + if (Arrays.asList(60, 50, 40, 30, 25, 20, 15, 10).contains(time)) { + PlayerUtil.sendMessage(ChatColor.YELLOW + "The game ends in " + ChatColor.GREEN + time + ChatColor.YELLOW + "...", getBukkitPlayers()); + } else if (Arrays.asList(5, 4, 3, 2, 1).contains(time)) { + PlayerUtil.sendMessage(ChatColor.YELLOW + "The game is ending in " + ChatColor.GREEN + time + ChatColor.YELLOW + "...", getBukkitPlayers()); + } + + time--; + } + } + + public List sortedScores() { + List list = new ArrayList<>(this.players.values()); + list.sort(new SortComparator().reversed()); + return list; + } + + private class SortComparator implements Comparator { + + @Override public int compare(OITCPlayer p1, OITCPlayer p2) { + return Integer.compare(p1.getScore(), p2.getScore()); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCPlayer.java b/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCPlayer.java new file mode 100644 index 0000000..2c8e968 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/oitc/OITCPlayer.java @@ -0,0 +1,27 @@ +package me.devkevin.practice.events.oitc; + +import me.devkevin.practice.events.EventPlayer; +import me.devkevin.practice.events.PracticeEvent; +import org.bukkit.scheduler.BukkitTask; +import java.util.UUID; +import lombok.Getter; +import lombok.Setter; + +@Setter +@Getter +public class OITCPlayer extends EventPlayer { + + private OITCState state = OITCState.WAITING; + private int score = 0; + private int lives = 5; + private BukkitTask respawnTask; + private OITCPlayer lastKiller; + + public OITCPlayer(UUID uuid, PracticeEvent event) { + super(uuid, event); + } + + public enum OITCState { + WAITING, PREPARING, FIGHTING, RESPAWNING, ELIMINATED + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoCountdownTask.java b/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoCountdownTask.java new file mode 100644 index 0000000..432a830 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoCountdownTask.java @@ -0,0 +1,29 @@ +package me.devkevin.practice.events.sumo; + +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import org.bukkit.ChatColor; +import java.util.Arrays; + +public class SumoCountdownTask extends EventCountdownTask { + public SumoCountdownTask(PracticeEvent event) { + super(event, 60); + } + + @Override + public boolean shouldAnnounce(int timeUntilStart) { + return Arrays.asList(45, 30, 15, 10, 5).contains(timeUntilStart); + } + + @Override + public boolean canStart() { + return getEvent().getPlayers().size() >= 2; + } + + @Override + public void onCancel() { + getEvent().sendMessage(ChatColor.RED + "Not enough players. Event has been cancelled"); + getEvent().end(); + this.getEvent().getPlugin().getEventManager().setCooldown(0L); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoEvent.java b/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoEvent.java new file mode 100644 index 0000000..e667e38 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoEvent.java @@ -0,0 +1,309 @@ +package me.devkevin.practice.events.sumo; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +public class SumoEvent extends PracticeEvent { + + private final Map players = new HashMap<>(); + + @Getter final HashSet fighting = new HashSet<>(); + private final SumoCountdownTask countdownTask = new SumoCountdownTask(this); + + public SumoEvent() { + super("Sumo"); + + new WaterCheckTask().runTaskTimer(getPlugin(), 0, 20); + } + + @Override + public Map getPlayers() { + return players; + } + + @Override + public EventCountdownTask getCountdownTask() { + return countdownTask; + } + + @Override + public List getSpawnLocations() { + return Collections.singletonList(this.getPlugin().getCustomLocationManager().getSumoLocation()); + } + + @Override + public void onStart() { + for(UUID playerUUID : players.keySet()) { + + Player player = Bukkit.getPlayer(playerUUID); + + if(player != null) { + PlayerUtil.reset(player); + } + } + selectPlayers(); + } + + @Override + public Consumer onJoin() { + return player -> players.put(player.getUniqueId(), new SumoPlayer(player.getUniqueId(), this)); + } + + @Override + public Consumer onDeath() { + + return player -> { + + SumoPlayer data = getPlayer(player); + + if (data == null || data.getFighting() == null) { + return; + } + + if(data.getState() == SumoPlayer.SumoState.FIGHTING || data.getState() == SumoPlayer.SumoState.PREPARING) { + + SumoPlayer killerData = data.getFighting(); + Player killer = getPlugin().getServer().getPlayer(killerData.getUuid()); + + data.getFightTask().cancel(); + killerData.getFightTask().cancel(); + + + Profile playerData = this.getPlugin().getProfileManager().getProfileData(player.getUniqueId()); + + if (playerData != null) { + playerData.setSumoLosses(playerData.getSumoLosses() + 1); + } + + data.setState(SumoPlayer.SumoState.ELIMINATED); + killerData.setState(SumoPlayer.SumoState.WAITING); + + PlayerUtil.reset(player); + this.getPlugin().getProfileManager().giveSpawnItems(player); + + PlayerUtil.reset(killer); + this.getPlugin().getProfileManager().giveSpawnItems(killer); + + if (getSpawnLocations().size() == 1) { + player.teleport(getSpawnLocations().get(0).toBukkitLocation()); + killer.teleport(getSpawnLocations().get(0).toBukkitLocation()); + } + + sendMessage(LandCore.getInstance().getProfileManager().getProfile(killer.getUniqueId()).getGrant().getRank().getColor() + killer.getName() + CC.GREEN + " won against " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + "!"); + player.sendMessage(""); + player.sendMessage(CC.RED + "You have been eliminated from the event. Better luck next time!"); + if (!player.hasPermission("practice.donors.gold")) { + player.sendMessage(CC.GRAY + "Purchase a rank at https://udrop.buycraft.net/ to host events of your own."); + } + player.sendMessage(" "); + + if (this.getByState(SumoPlayer.SumoState.WAITING).size() == 1) { + Player winner = Bukkit.getPlayer(this.getByState(SumoPlayer.SumoState.WAITING).get(0)); + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + winnerData.setSumoWins(winnerData.getSumoWins() + 1); + + handleWin(killer); + + this.fighting.clear(); + end(); + } else { + getPlugin().getServer().getScheduler().runTaskLater(getPlugin(), () -> selectPlayers(), 3 * 20); + } + } + }; + } + + private CustomLocation[] getSumoLocations() { + CustomLocation[] array = new CustomLocation[2]; + array[0] = this.getPlugin().getCustomLocationManager().getSumoFirst(); + array[1] = this.getPlugin().getCustomLocationManager().getSumoSecond(); + return array; + } + + private void selectPlayers() { + + if (this.getByState(SumoPlayer.SumoState.WAITING).size() == 1) { + Player winner = Bukkit.getPlayer(this.getByState(SumoPlayer.SumoState.WAITING).get(0)); + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + winnerData.setSumoWins(winnerData.getSumoWins() + 1); + + this.fighting.clear(); + end(); + return; + } + + sendMessage(CC.GOLD + CC.BOLD + "(Sumo) " + ChatColor.GRAY + CC.I + "Selecting random players..."); + + this.fighting.clear(); + + //if (getByState(SumoPlayer.SumoState.WAITING).size() < 2) { + // players.values().forEach(player -> player.setState(SumoPlayer.SumoState.WAITING)); + //} + + Player picked1 = getRandomPlayer(); + Player picked2 = getRandomPlayer(); + + SumoPlayer picked1Data = getPlayer(picked1); + SumoPlayer picked2Data = getPlayer(picked2); + + picked1Data.setFighting(picked2Data); + picked2Data.setFighting(picked1Data); + + this.fighting.add(picked1.getName()); + this.fighting.add(picked2.getName()); + + PlayerUtil.reset(picked1); + PlayerUtil.reset(picked2); + + picked1.teleport(getSumoLocations()[0].toBukkitLocation()); + picked2.teleport(getSumoLocations()[1].toBukkitLocation()); + + for(Player other : this.getBukkitPlayers()) { + if(other != null) { + other.showPlayer(picked1); + other.showPlayer(picked2); + } + } + + for(UUID spectatorUUID : this.getPlugin().getEventManager().getSpectators()) { + Player spectator = Bukkit.getPlayer(spectatorUUID); + if(spectatorUUID != null) { + spectator.showPlayer(picked1); + spectator.showPlayer(picked2); + } + } + + picked1.showPlayer(picked2); + picked2.showPlayer(picked1); + + sendMessage(LandCore.getInstance().getProfileManager().getProfile(picked1.getUniqueId()).getGrant().getRank().getColor() + picked1.getName() + CC.GREEN + " VS " + LandCore.getInstance().getProfileManager().getProfile(picked2.getUniqueId()).getGrant().getRank().getColor() + picked2.getName()); + + BukkitTask task = new SumoFightTask(picked1, picked2, picked1Data, picked2Data).runTaskTimer(getPlugin(), 0, 20); + + picked1Data.setFightTask(task); + picked2Data.setFightTask(task); + } + + private Player getRandomPlayer() { + + if(getByState(SumoPlayer.SumoState.WAITING).size() == 0) { + return null; + } + + + List waiting = getByState(SumoPlayer.SumoState.WAITING); + + Collections.shuffle(waiting); + + UUID uuid = waiting.get(ThreadLocalRandom.current().nextInt(waiting.size())); + + SumoPlayer data = getPlayer(uuid); + data.setState(SumoPlayer.SumoState.PREPARING); + + return getPlugin().getServer().getPlayer(uuid); + } + + public List getByState(SumoPlayer.SumoState state) { + return players.values().stream().filter(player -> player.getState() == state).map(SumoPlayer::getUuid).collect(Collectors.toList()); + } + + /** + * To ensure that the fight doesn't go on forever and to + * let the players know how much time they have left. + */ + @Getter + @RequiredArgsConstructor + public class SumoFightTask extends BukkitRunnable { + private final Player player; + private final Player other; + + private final SumoPlayer playerSumo; + private final SumoPlayer otherSumo; + + private int time = 60; + + @Override + public void run() { + // Make sure we don't get a fuck ton of NPEs + + if (player == null || other == null || !player.isOnline() || !other.isOnline()) { + cancel(); + return; + } + + if (time == 60) { + PlayerUtil.sendMessage(CC.D_RED + "3...", player, other); + } else if (time == 59) { + PlayerUtil.sendMessage(CC.RED + "2...", player, other); + } else if (time == 58) { + PlayerUtil.sendMessage(CC.YELLOW + "1...", player, other); + } else if (time == 57) { + PlayerUtil.sendMessage(CC.GREEN + "Fight!", player, other); + this.otherSumo.setState(SumoPlayer.SumoState.FIGHTING); + this.playerSumo.setState(SumoPlayer.SumoState.FIGHTING); + } else if (time <= 0) { + List players = Arrays.asList(player, other); + Player winner = players.get(ThreadLocalRandom.current().nextInt(players.size())); + players.stream().filter(pl -> !pl.equals(winner)).forEach(pl -> onDeath().accept(pl)); + + cancel(); + return; + } + + if (Arrays.asList(30, 25, 20, 15, 10).contains(time)) { + PlayerUtil.sendMessage(CC.GOLD + "Fight ends in " + time + " seconds.", player, other); + } else if (Arrays.asList(5, 4, 3, 2, 1).contains(time)) { + PlayerUtil.sendMessage(CC.GOLD + "A winner will be automatically selected in " + time + " seconds.", player, other); + } + + time--; + } + } + + @RequiredArgsConstructor + private class WaterCheckTask extends BukkitRunnable { + @Override + public void run() { + + if (getPlayers().size() <= 1) { + return; + } + + getBukkitPlayers().forEach(player -> { + + if (getPlayer(player) != null && getPlayer(player).getState() != SumoPlayer.SumoState.FIGHTING) { + return; + } + + Block legs = player.getLocation().getBlock(); + Block head = legs.getRelative(BlockFace.UP); + if (legs.getType() == Material.WATER || legs.getType() == Material.STATIONARY_WATER || head.getType() == Material.WATER || head.getType() == Material.STATIONARY_WATER) { + onDeath().accept(player); + } + }); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoPlayer.java b/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoPlayer.java new file mode 100644 index 0000000..b33b6f9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/sumo/SumoPlayer.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.events.sumo; + +import java.util.UUID; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.events.EventPlayer; +import me.devkevin.practice.events.PracticeEvent; +import org.bukkit.scheduler.BukkitTask; + +@Setter +@Getter +public class SumoPlayer extends EventPlayer { + + private SumoState state = SumoState.WAITING; + private BukkitTask fightTask; + private SumoPlayer fighting; + + public SumoPlayer(UUID uuid, PracticeEvent event) { + super(uuid, event); + } + + public enum SumoState { + WAITING, PREPARING, FIGHTING, ELIMINATED + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunCountdownTask.java b/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunCountdownTask.java new file mode 100644 index 0000000..f2b4923 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunCountdownTask.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.events.tntrun; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; + +import java.util.Arrays; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TntRunCountdownTask extends EventCountdownTask { + + public TntRunCountdownTask(PracticeEvent event) { + super(event, 60); + } + + @Override + public boolean shouldAnnounce(int timeUntilStart) { + return Arrays.asList(45, 30, 15, 10, 5).contains(timeUntilStart); + } + + @Override + public boolean canStart() { + return getEvent().getPlayers().size() >= 2; + } + + @Override + public void onCancel() { + getEvent().sendMessage(CC.RED + "Not enough players. Event has been cancelled"); + getEvent().end(); + this.getEvent().getPlugin().getEventManager().setCooldown(0L); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunEvent.java b/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunEvent.java new file mode 100644 index 0000000..6cca952 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunEvent.java @@ -0,0 +1,273 @@ +package me.devkevin.practice.events.tntrun; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Maps; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.NumberConversions; + +import java.util.*; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TntRunEvent extends PracticeEvent { + + private final Map players = new HashMap<>(); + + private final TntRunCountdownTask countdownTask = new TntRunCountdownTask(this); + + private VoidCheckTask voidCheckTask; + private RemoveBlocksTask removeBlocksTask; + + @Getter + private final Map removeBlocks = Maps.newConcurrentMap(); + + public TntRunEvent() { + super("TNTRun"); + } + + @Override + public Map getPlayers() { + return players; + } + + @Override + public EventCountdownTask getCountdownTask() { + return countdownTask; + } + + @Override + public List getSpawnLocations() { + return Collections.singletonList(this.getPlugin().getCustomLocationManager().getTntLocation()); + } + + public void addBlock(Location location,Block block){ + this.removeBlocks.put(location, block.getType()); + } + + @Override + public void onStart() { + new TNTRunGameTask().runTaskTimer(Practice.getInstance(), 0, 20L); + voidCheckTask = new VoidCheckTask(); + voidCheckTask.runTaskTimer(Practice.getInstance(), 0, 5L); + removeBlocksTask = new RemoveBlocksTask(); + removeBlocksTask.runTaskTimer(Practice.getInstance(), 0, 1L); + } + + @Override + public Consumer onJoin() { + return player -> players.put(player.getUniqueId(), new TntRunPlayer(player.getUniqueId(), this)); + } + + @Override + public Consumer onDeath() { + + return player -> { + + TntRunPlayer data = getPlayer(player); + + if(data.getState() == TntRunPlayer.TntRunState.IN_GAME){ + data.setState(TntRunPlayer.TntRunState.ELIMINATED); + + Profile deathData = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + deathData.setTntrunEventLosses(deathData.getTntrunEventLosses() + 1); + PlayerUtil.reset(player); + this.getPlugin().getProfileManager().giveSpawnItems(player); + Practice.getInstance().getEventManager().addDeathSpectatorTntRun(player, + Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()), this); + + + sendMessage(CC.GOLD + CC.BOLD + "(TnTRun) " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GREEN + " has been eliminated"); + player.sendMessage(""); + player.sendMessage(CC.RED + "You have been eliminated from the event. Better luck next time!"); + if (!player.hasPermission("practice.donors.gold")) { + player.sendMessage(CC.GRAY + "Purchase a rank at https://udrop.buycraft.net/ to host events of your own."); + } + player.sendMessage(""); + } + + if (this.getByState(TntRunPlayer.TntRunState.IN_GAME).size() == 1) { + Player winner = Bukkit.getPlayer(this.getByState(TntRunPlayer.TntRunState.IN_GAME).get(0)); + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + winnerData.setTntrunEventWins(winnerData.getTntrunEventWins() + 1); + + handleWin(winner); + + voidCheckTask.cancel(); + removeBlocksTask.cancel(); + + end(); + + this.removeBlocks.forEach((location, block) -> { + new BukkitRunnable(){ + @Override + public void run() { + location.getBlock().setType(block); + location.getBlock().getState().update(); + } + }.runTaskLater(Practice.getInstance(), 10L); + }); + } + }; + } + + public List getByState(TntRunPlayer.TntRunState state) { + return players.values().stream().filter(player -> player.getState() == state).map(TntRunPlayer::getUuid).collect(Collectors.toList()); + } + + private static double PLAYER_BOUNDINGBOX_ADD = 0.5; + + private static Block getBlockUnderPlayer(Location location) { + PlayerPosition loc = new PlayerPosition(location); + Block b11 = loc.getBlock(location.getWorld(), +PLAYER_BOUNDINGBOX_ADD, -PLAYER_BOUNDINGBOX_ADD); + if (b11.getType() != Material.AIR) { + return b11; + } + Block b12 = loc.getBlock(location.getWorld(), -PLAYER_BOUNDINGBOX_ADD, +PLAYER_BOUNDINGBOX_ADD); + if (b12.getType() != Material.AIR) { + return b12; + } + Block b21 = loc.getBlock(location.getWorld(), +PLAYER_BOUNDINGBOX_ADD, +PLAYER_BOUNDINGBOX_ADD); + if (b21.getType() != Material.AIR) { + return b21; + } + Block b22 = loc.getBlock(location.getWorld(), -PLAYER_BOUNDINGBOX_ADD, -PLAYER_BOUNDINGBOX_ADD); + if (b22.getType() != Material.AIR) { + return b22; + } + return null; + } + + /** + * To ensure that the fight doesn't go on forever and to + * let the players know how much time they have left. + */ + @Getter + @RequiredArgsConstructor + public class TNTRunGameTask extends BukkitRunnable { + + private int time = 3; + + @Override + public void run() { + + if (time == 3) { + PlayerUtil.sendMessage(CC.D_RED + "3...", getBukkitPlayers()); + } else if (time == 2) { + PlayerUtil.sendMessage(CC.RED + "2...", getBukkitPlayers()); + } else if (time == 1) { + PlayerUtil.sendMessage(CC.YELLOW + "1...", getBukkitPlayers()); + } else if (time == 0) { + PlayerUtil.sendMessage(CC.GREEN + "Go!", getBukkitPlayers()); + + for (TntRunPlayer player : getPlayers().values()) { + player.setState(TntRunPlayer.TntRunState.IN_GAME); + this.cancel(); + } + + getBukkitPlayers().forEach(player -> { + Location location = player.getLocation().subtract(0, 1, 0); + if (location.getBlock().getType() != Material.AIR){ + addBlock(location, location.getBlock()); + + location.getBlock().setType(Material.AIR); + location.getBlock().getState().update(); + + player.sendBlockChange(location.getBlock().getLocation(), Material.AIR, (byte)0); + } + }); + } + time--; + } + } + + @Getter + @RequiredArgsConstructor + public class VoidCheckTask extends BukkitRunnable { + @Override + public void run() { + + if (getPlayers().size() <= 1) { + return; + } + + getBukkitPlayers().forEach(player -> { + if (getPlayer(player) != null && getPlayer(player).getState() != TntRunPlayer.TntRunState.IN_GAME) { + return; + } + if (player.getLocation().getY() <= 0) { + onDeath().accept(player); + } + }); + } + } + + @Getter + @RequiredArgsConstructor + public class RemoveBlocksTask extends BukkitRunnable { + @Override + public void run() { + + getByState(TntRunPlayer.TntRunState.IN_GAME).forEach(uuid -> { + Player player = Bukkit.getPlayer(uuid); + + Location location = player.getLocation().subtract(0, 1, 0); + + if (location.getBlock().getType() != Material.AIR) { + Block blocktoremove1 = getBlockUnderPlayer(location); + if (blocktoremove1 != null) { + addBlock(location, blocktoremove1); + + blocktoremove1.setType(Material.AIR); + blocktoremove1.getState().update(); + player.sendBlockChange(blocktoremove1.getLocation(), Material.AIR, (byte)0); + } + } + }); + } + } + + private static class PlayerPosition { + + private double x; + private int y; + private double z; + + @SuppressWarnings("unused") + public PlayerPosition(double x, int y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public PlayerPosition(Location location) { + this.x = location.getX(); + this.y = (int) location.getY(); + this.z = location.getZ(); + } + + public Block getBlock(World world, double addx, double addz) { + return world.getBlockAt(NumberConversions.floor(x + addx), y, NumberConversions.floor(z + addz)); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunPlayer.java b/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunPlayer.java new file mode 100644 index 0000000..9e3bc34 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/tntrun/TntRunPlayer.java @@ -0,0 +1,33 @@ +package me.devkevin.practice.events.tntrun; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.events.EventPlayer; +import me.devkevin.practice.events.PracticeEvent; +import org.bukkit.scheduler.BukkitTask; + +import java.util.UUID; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@Setter +public class TntRunPlayer extends EventPlayer { + + private TntRunState state = TntRunState.WAITING; + private BukkitTask fightTask; + private TntRunPlayer fighting; + + public TntRunPlayer(UUID uuid, PracticeEvent event) { + super(uuid, event); + } + + public enum TntRunState { + WAITING, + IN_GAME, + ELIMINATED + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagCountdownTask.java b/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagCountdownTask.java new file mode 100644 index 0000000..fbdd402 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagCountdownTask.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.events.tnttag; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; + +import java.util.Arrays; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TNTTagCountdownTask extends EventCountdownTask { + + public TNTTagCountdownTask(PracticeEvent event) { + super(event, 60); + } + + @Override + public boolean shouldAnnounce(int timeUntilStart) { + return Arrays.asList(45, 30, 15, 10, 5).contains(timeUntilStart); + } + + @Override + public boolean canStart() { + return getEvent().getPlayers().size() >= 2; + } + + @Override + public void onCancel() { + getEvent().sendMessage(CC.RED + "Not enough players. Event has been cancelled."); + getEvent().end(); + this.getEvent().getPlugin().getEventManager().setCooldown(0L); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagEvent.java b/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagEvent.java new file mode 100644 index 0000000..000dce8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagEvent.java @@ -0,0 +1,311 @@ +package me.devkevin.practice.events.tnttag; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.EventCountdownTask; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TNTTagEvent extends PracticeEvent { + + private final Map players = new HashMap<>(); + private final TNTTagCountdownTask countdownTask = new TNTTagCountdownTask(this); + @Getter @Setter + private TNTTagTask tntTagTask; + + public TNTTagEvent() { + super("TNTTag"); + } + + @Override + public Map getPlayers() { + return players; + } + + @Override + public EventCountdownTask getCountdownTask() { + return countdownTask; + } + + @Override + public List getSpawnLocations() { + return Collections.singletonList(this.getPlugin().getCustomLocationManager().getTnttagLocation()); + } + + @Override + public void onStart() { + new TNTTagGameTask().runTaskTimer(Practice.getInstance(), 0,20L); + } + + @Override + public Consumer onJoin() { + return player -> players.put(player.getUniqueId(), new TNTTagPlayer(player.getUniqueId(), this)); + } + + @Override + public Consumer onDeath() { + return player -> { + + TNTTagPlayer data = getPlayer(player); + + if(!player.isOnline()){ + return; + } + + + if(data.getState() == TNTTagPlayer.TNTTagState.TAGGED){ + data.setState(TNTTagPlayer.TNTTagState.ELIMINATED); + PlayerUtil.reset(player); + this.getPlugin().getProfileManager().giveSpawnItems(player); + Practice.getInstance().getEventManager().addDeathSpectatorTntTag(player, + Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()), this); + + + sendMessage(CC.GOLD + CC.BOLD + "(TnTTag) " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GREEN + " has been eliminated"); + player.sendMessage(""); + player.sendMessage(CC.RED + "You have been eliminated from the event. Better luck next time!"); + if (!player.hasPermission("practice.donors.gold")) { + player.sendMessage(CC.GRAY + "Purchase a rank at https://udrop.buycraft.net/ to host events of your own."); + } + player.sendMessage(""); + + if (this.getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() <= 5){ + this.getByState(TNTTagPlayer.TNTTagState.IN_GAME).forEach(tntplayer -> { + + Player other = Bukkit.getPlayer(tntplayer); + + other.teleport(Practice.getInstance().getCustomLocationManager().getTnttagGameLocation().toBukkitLocation()); + }); + + this.getByState(TNTTagPlayer.TNTTagState.TAGGED).forEach(tntplayer -> { + + Player other = Bukkit.getPlayer(tntplayer); + + other.teleport(Practice.getInstance().getCustomLocationManager().getTnttagGameLocation().toBukkitLocation()); + + }); + } + } + + if (this.getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() == 1 && this.getByState(TNTTagPlayer.TNTTagState.TAGGED).size() == 0) { + Player winner = Bukkit.getPlayer(this.getByState(TNTTagPlayer.TNTTagState.IN_GAME).get(0)); + + Profile winnerData = Practice.getInstance().getProfileManager().getProfileData(winner.getUniqueId()); + //winnerData.settn(winnerData.getSumoEventWins() + 1); + + handleWin(winner); + end(); + } + + }; + } + + public List getByState(TNTTagPlayer.TNTTagState state) { + return players.values().stream().filter(player -> player.getState() == state).map(TNTTagPlayer::getUuid).collect(Collectors.toList()); + } + + public void explodePlayer(){ + + getByState(TNTTagPlayer.TNTTagState.TAGGED).forEach(tntplayer -> { + Player player = Bukkit.getPlayer(tntplayer); + + player.getWorld().createExplosion(player.getLocation(), 0.0F); + + onDeath().accept(player); + }); + + if (getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() >= 30){ + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + } else if(getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() >= 20){ + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + } else if(getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() >= 10){ + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + } else if(getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() >= 5){ + pickRandomPlayer(); + pickRandomPlayer(); + } else { + pickRandomPlayer(); + } + } + + public void tagPlayer(Player player, Player attacker){ + + if(getPlayer(player.getUniqueId()).getState() == TNTTagPlayer.TNTTagState.TAGGED){ + return; + } + + getPlayer(player.getUniqueId()).setState(TNTTagPlayer.TNTTagState.TAGGED); + getPlayer(attacker.getUniqueId()).setState(TNTTagPlayer.TNTTagState.IN_GAME); + + player.getInventory().setHelmet(new ItemStack(Material.TNT, 1)); + player.getInventory().setItem(0, new ItemStack(Material.TNT, 1)); + + for (PotionEffect effect : attacker.getActivePotionEffects()) { + attacker.removePotionEffect(effect.getType()); + } + for (PotionEffect effect : player.getActivePotionEffects()) { + player.removePotionEffect(effect.getType()); + } + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 3)); + attacker.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 2)); + + + player.getInventory().setHelmet(new ItemStack(Material.TNT, 1)); + attacker.getInventory().setHelmet(new ItemStack(Material.AIR, 1)); + + attacker.getInventory().setItem(0, new ItemStack(Material.AIR, 1)); + player.getInventory().setItem(0, new ItemStack(Material.TNT, 1)); + + player.playSound(player.getLocation(), Sound.NOTE_PIANO, 20f, 0.1f); + + sendMessage(CC.GOLD + CC.BOLD + "(TnTTag) " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GRAY + " is IT!"); + + + //FireworkEffect effect = FireworkEffect.builder().withColor(Color.RED).with(FireworkEffect.Type.CREEPER).build(); + } + + public Player pickRandomPlayer(){ + if (getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() == 0) { + return null; + } + + List waiting = getByState(TNTTagPlayer.TNTTagState.IN_GAME); + + Collections.shuffle(waiting); + + UUID uuid = waiting.get(ThreadLocalRandom.current().nextInt(waiting.size())); + + getPlayer(uuid).setState(TNTTagPlayer.TNTTagState.TAGGED); + + Player player = getPlugin().getServer().getPlayer(uuid); + + player.getInventory().setHelmet(new ItemStack(Material.TNT, 1)); + player.getInventory().setItem(0, new ItemStack(Material.TNT, 1)); + for (PotionEffect effect : player.getActivePotionEffects()) { + player.removePotionEffect(effect.getType()); + } + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 3)); + player.playSound(player.getLocation(), Sound.NOTE_PIANO, 20f, 0.1f); + sendMessage(CC.GOLD + CC.BOLD + "(TnTTag) " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GRAY + " is IT!"); + + return player; + } + + /** + * To ensure that the fight doesn't go on forever and to + * let the players know how much time they have left. + */ + @Getter + @RequiredArgsConstructor + public class TNTTagGameTask extends BukkitRunnable { + + private int time = 3; + + @Override + public void run() { + + if (time == 3) { + PlayerUtil.sendMessage(CC.D_RED + "3...", getBukkitPlayers()); + } else if (time == 2) { + PlayerUtil.sendMessage(CC.RED + "2...", getBukkitPlayers()); + } else if (time == 1) { + PlayerUtil.sendMessage(CC.YELLOW + "1...", getBukkitPlayers()); + } else if (time == 0) { + PlayerUtil.sendMessage(CC.GREEN + "Go!", getBukkitPlayers()); + + for (TNTTagPlayer player : getPlayers().values()) { + player.setState(TNTTagPlayer.TNTTagState.IN_GAME); + this.cancel(); + } + + getBukkitPlayers().forEach(player -> { + player.teleport(Practice.getInstance().getCustomLocationManager().getTnttagGameLocation().toBukkitLocation()); + for (PotionEffect effect : player.getActivePotionEffects()) { + player.removePotionEffect(effect.getType()); + } + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 2)); + }); + + if (getPlayers().size() >= 30){ + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + } else if(getPlayers().size() >= 20){ + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + } else if(getPlayers().size() >= 10){ + pickRandomPlayer(); + pickRandomPlayer(); + pickRandomPlayer(); + } else if(getPlayers().size() >= 5){ + pickRandomPlayer(); + pickRandomPlayer(); + } else { + pickRandomPlayer(); + } + tntTagTask = new TNTTagTask(); + tntTagTask.runTaskTimer(Practice.getInstance(), 0,20L); + return; + } + time--; + } + } + + + @Getter + @RequiredArgsConstructor + public class TNTTagTask extends BukkitRunnable { + + private int time = 30; + + @Override + public void run() { + + if (time == 0){ + explodePlayer(); + if (getByState(TNTTagPlayer.TNTTagState.IN_GAME).size() == 1 && getByState(TNTTagPlayer.TNTTagState.TAGGED).size() == 0){ + return; + } + time = 30; + } + time--; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagPlayer.java b/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagPlayer.java new file mode 100644 index 0000000..9667f87 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/events/tnttag/TNTTagPlayer.java @@ -0,0 +1,34 @@ +package me.devkevin.practice.events.tnttag; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.events.EventPlayer; +import me.devkevin.practice.events.PracticeEvent; +import org.bukkit.scheduler.BukkitTask; + +import java.util.UUID; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@Setter +public class TNTTagPlayer extends EventPlayer { + + private TNTTagPlayer.TNTTagState state = TNTTagPlayer.TNTTagState.WAITING; + private BukkitTask fightTask; + private TNTTagPlayer fighting; + + public TNTTagPlayer(UUID uuid, PracticeEvent event) { + super(uuid, event); + } + + public enum TNTTagState { + WAITING, + IN_GAME, + ELIMINATED, + TAGGED + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/file/Config.java b/Practice/src/main/java/me/devkevin/practice/file/Config.java new file mode 100644 index 0000000..352715a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/file/Config.java @@ -0,0 +1,46 @@ +package me.devkevin.practice.file; + +import lombok.Getter; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +@Getter +public class Config { + + private final FileConfiguration config; + private final File configFile; + protected boolean wasCreated; + + public Config(String name, JavaPlugin plugin) { + this.configFile = new File(plugin.getDataFolder() + "/" + name + ".yml"); + if (!this.configFile.exists()) { + try { + this.configFile.getParentFile().mkdirs(); + this.configFile.createNewFile(); + this.wasCreated = true; + } catch (IOException e) { + e.printStackTrace(); + } + } + this.config = YamlConfiguration.loadConfiguration(this.configFile); + } + + public void save() { + try { + this.config.save(configFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public FileConfiguration getConfig() { + return config; + } + + public File getConfigFile() { + return configFile; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/file/ConfigFile.java b/Practice/src/main/java/me/devkevin/practice/file/ConfigFile.java new file mode 100644 index 0000000..bbcbe35 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/file/ConfigFile.java @@ -0,0 +1,102 @@ +package me.devkevin.practice.file; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class ConfigFile { + + @Getter private File file; + @Getter private YamlConfiguration configuration; + + public ConfigFile(JavaPlugin plugin, String name) { + file = new File(plugin.getDataFolder(), name + ".yml"); + + if (!file.getParentFile().exists()) { + file.getParentFile().mkdir(); + } + + plugin.saveResource(name + ".yml", false); + + configuration = YamlConfiguration.loadConfiguration(file); + } + + public double getDouble(String path) { + if (configuration.contains(path)) { + return configuration.getDouble(path); + } + return 0; + } + + public int getInt(String path) { + if (configuration.contains(path)) { + return configuration.getInt(path); + } + return 0; + } + + public boolean getBoolean(String path) { + if (configuration.contains(path)) { + return configuration.getBoolean(path); + } + return false; + } + + public String getString(String path) { + if (configuration.contains(path)) { + return ChatColor.translateAlternateColorCodes('&', configuration.getString(path)); + } + return "ERROR: STRING NOT FOUND"; + } + + public String getString(String path, String callback, boolean colorize) { + if (configuration.contains(path)) { + if (colorize) { + return ChatColor.translateAlternateColorCodes('&', configuration.getString(path)); + } else { + return configuration.getString(path); + } + } + return callback; + } + + public List getReversedStringList(String path) { + List list = getStringList(path); + if (list != null) { + int size = list.size(); + List toReturn = new ArrayList<>(); + for (int i = size - 1; i >= 0; i--) { + toReturn.add(list.get(i)); + } + return toReturn; + } + return Arrays.asList("ERROR: STRING LIST NOT FOUND!"); + } + + public List getStringList(String path) { + if (configuration.contains(path)) { + ArrayList strings = new ArrayList<>(); + for (String string : configuration.getStringList(path)) { + strings.add(ChatColor.translateAlternateColorCodes('&', string)); + } + return strings; + } + return Arrays.asList("ERROR: STRING LIST NOT FOUND!"); + } + + public List getStringListOrDefault(String path, List toReturn) { + if (configuration.contains(path)) { + ArrayList strings = new ArrayList<>(); + for (String string : configuration.getStringList(path)) { + strings.add(ChatColor.translateAlternateColorCodes('&', string)); + } + return strings; + } + return toReturn; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/general/GeneralSettingMenu.java b/Practice/src/main/java/me/devkevin/practice/general/GeneralSettingMenu.java new file mode 100644 index 0000000..dad00d9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/general/GeneralSettingMenu.java @@ -0,0 +1,67 @@ +package me.devkevin.practice.general; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import static me.devkevin.practice.util.PlayerUtil.PLACEHOLDER_ITEM; + +/** + * Copyright 16/12/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class GeneralSettingMenu { + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI generalMenu = new InventoryUI(CC.GRAY + "General Setting Menu", 3); + + public GeneralSettingMenu() { + setupMenu(); + } + + private void setupMenu() { + for (int i = 0; i < 9 * 3; i++) { + this.generalMenu.setItem(i, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM)); + } + + generalMenu.setItem(11, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.LEASH) + .name(CC.YELLOW + "Host Tournament") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.performCommand("tournament host"); + } + }); + + generalMenu.setItem(13, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.JUKEBOX) + .name(CC.YELLOW + "Host Event") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.openInventory(plugin.getHostMenu().getHostMenu().getCurrentPage()); + } + }); + + generalMenu.setItem(15, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.CHEST) + .name(CC.YELLOW + "Settings") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.performCommand("poptions"); + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/handler/MovementHandler.java b/Practice/src/main/java/me/devkevin/practice/handler/MovementHandler.java new file mode 100644 index 0000000..01dff84 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/handler/MovementHandler.java @@ -0,0 +1,93 @@ +package me.devkevin.practice.handler; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.events.oitc.OITCEvent; +import me.devkevin.practice.events.oitc.OITCPlayer; +import me.devkevin.practice.events.sumo.SumoEvent; +import me.devkevin.practice.events.sumo.SumoPlayer; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.BlockUtil; +import net.minecraft.server.v1_8_R3.PacketPlayInFlying; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffectType; + +/** + * Copyright 03/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MovementHandler implements xyz.refinedev.spigot.api.handlers.impl.MovementHandler { + private final Practice plugin = Practice.getInstance(); + + @Override + public void handleUpdateLocation(Player player, Location to, Location from, PacketPlayInFlying packetPlayInFlying) { + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + Practice.getInstance().getLogger().warning(player.getName() + "'s player data is null"); + player.kickPlayer(CC.RED + "Your data is null please reconnect or contact with the Developer"); + return; + } + + if (profile.getState() == ProfileState.FIGHTING) { + Match match = Practice.getInstance().getMatchManager().getMatch(player.getUniqueId()); + + if (match == null) { + return; + } + + if (match.getKit().isSumo()) { + if (BlockUtil.isOnLiquid(to, 0) || BlockUtil.isOnLiquid(to,1)) { + Practice.getInstance().getMatchManager().removeFighter(player, profile, true); + //((CraftPlayer) player).getHandle().playerConnection. = false; + } + + if (to.getX() != from.getX() || to.getZ() != from.getZ()) { + if (match.getMatchState() == MatchState.STARTING) { + player.teleport(from); + //((CraftPlayer) player).getHandle().playerConnection.checkMovement = false; + } + } + } + + if (player.hasPotionEffect(PotionEffectType.WEAKNESS)) { + return; + } + } + + PracticeEvent event = Practice.getInstance().getEventManager().getEventPlaying(player); + + if (event != null) { + + if(event instanceof SumoEvent) { + SumoEvent sumoEvent = (SumoEvent) event; + + if (sumoEvent.getPlayer(player).getFighting() != null && sumoEvent.getPlayer(player).getState() == SumoPlayer.SumoState.PREPARING) { + player.teleport(from); + } + } else if(event instanceof OITCEvent) { + OITCEvent oitcEvent = (OITCEvent) event; + + if (oitcEvent.getPlayer(player).getState() == OITCPlayer.OITCState.RESPAWNING) { + player.teleport(from); + } else if(oitcEvent.getPlayer(player).getState() == OITCPlayer.OITCState.FIGHTING) { + if(player.getLocation().getBlockY() >= 90) { + oitcEvent.teleportNextLocation(player); + } + } + } + + } + } + + @Override + public void handleUpdateRotation(Player player, Location location, Location location1, PacketPlayInFlying packetPlayInFlying) { + + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/HCFClass.java b/Practice/src/main/java/me/devkevin/practice/hcf/HCFClass.java new file mode 100644 index 0000000..4df2302 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/HCFClass.java @@ -0,0 +1,50 @@ +package me.devkevin.practice.hcf; + +import lombok.Getter; +import me.devkevin.practice.Practice; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.potion.PotionEffect; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:01 + * HCFClass / me.devkevin.practice.hcf / Practice + */ +@Getter +public abstract class HCFClass implements Listener { + + public static long DEFAULT_MAX_DURATION = TimeUnit.MINUTES.toMillis(8L); + + private final String name; + private final List effects = new ArrayList<>(); + + public HCFClass(String name) { + this.name = name; + Practice.getInstance().getHcfManager().getClasses().add(this); + } + + public abstract boolean canApply(Player player); + + public abstract boolean onEquip(Player player); + + public abstract void onUnEquip(Player player); + + public abstract void onQuit(Player player); + + public void registerHCFListeners() { + Bukkit.getPluginManager().registerEvents(this, Practice.getInstance()); + } + + @EventHandler + public void onPlayerQuitEvent(PlayerQuitEvent event) { + onQuit(event.getPlayer()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/classes/Archer.java b/Practice/src/main/java/me/devkevin/practice/hcf/classes/Archer.java new file mode 100644 index 0000000..872e61a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/classes/Archer.java @@ -0,0 +1,296 @@ +package me.devkevin.practice.hcf.classes; + +import club.inverted.chatcolor.CC; +import gnu.trove.map.TObjectLongMap; +import gnu.trove.map.hash.TObjectLongHashMap; +import me.devkevin.practice.Practice; +import me.devkevin.practice.hcf.HCFClass; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.bukkit.ChatColor; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.projectiles.ProjectileSource; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:32 + * Archer / me.devkevin.practice.hcf.classes / Practice + */ +public class Archer extends HCFClass { + + private final Practice plugin = Practice.getInstance(); + + public static PotionEffect ARCHER_SPEED_EFFECT = new PotionEffect(PotionEffectType.SPEED, 160, 3); + public static PotionEffect ARCHER_JUMP_EFFECT = new PotionEffect(PotionEffectType.JUMP, 160, 7); + public static PotionEffect ARCHER_RESISTANCE_EFFECT = new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 160, 2); + + public static TObjectLongMap archerSpeedCooldowns = new TObjectLongHashMap<>(); + public static TObjectLongMap archerJumpCooldowns = new TObjectLongHashMap<>(); + public static TObjectLongMap archerResistanceCooldowns = new TObjectLongHashMap<>(); + + public static ArrayList tag = new ArrayList<>(); + public static HashMap TAGGED = new HashMap<>(); + public static Random random = new Random(); + + public static long ARCHER_SPEED_COOLDOWN_DELAY = TimeUnit.SECONDS.toMillis(30); + public static long ARCHER_JUMP_COOLDOWN_DELAY = TimeUnit.SECONDS.toMillis(30); + public static long ARCHER_RESISTANCE_COOLDOWN_DELAY = TimeUnit.SECONDS.toMillis(30); + + public Archer() { + super("Archer"); + getEffects().add(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, Integer.MAX_VALUE, 1)); + getEffects().add(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 2)); + } + + @Override + public boolean canApply(Player player) { + PlayerInventory playerInventory = player.getInventory(); + ItemStack helmet = playerInventory.getHelmet(); + if ((helmet == null) || (helmet.getType() != Material.LEATHER_HELMET)) { + return false; + } + + ItemStack chestplate = playerInventory.getChestplate(); + if ((chestplate == null) || (chestplate.getType() != Material.LEATHER_CHESTPLATE)) { + return false; + } + + ItemStack leggings = playerInventory.getLeggings(); + if ((leggings == null) || (leggings.getType() != Material.LEATHER_LEGGINGS)) { + return false; + } + + ItemStack boots = playerInventory.getBoots(); + return (boots != null) && (boots.getType() == Material.LEATHER_BOOTS); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST) + public void onEntityDamage(EntityDamageByEntityEvent event) { + Entity entity = event.getEntity(); + Entity damager = event.getDamager(); + if (((entity instanceof Player)) && ((damager instanceof Arrow))) { + Arrow arrow = (Arrow) damager; + ProjectileSource source = arrow.getShooter(); + if ((source instanceof Player)) { + Player damaged = (Player) event.getEntity(); + Player shooter = (Player) source; + HCFClass equipped = this.plugin.getHcfManager().getHCFClass(shooter); + if ((equipped == null) || (!equipped.equals(this))) { + return; + } + if ((this.plugin.getHcfManager().getHCFClass(damaged) != null) && (this.plugin.getHcfManager().getHCFClass(damaged).equals(this))) { + return; + } + + new TaggedTask(damaged); + + int heartdamage = 1; + if (TAGGED.containsKey(damaged.getUniqueId())) { + heartdamage = 2; + } + + event.setDamage(0); + + damaged.setHealth(Math.max(0, damaged.getHealth() - (heartdamage * 2))); + + TAGGED.put(damaged.getUniqueId(), shooter.getUniqueId()); + double distance = shooter.getLocation().distance(damaged.getLocation()); + + shooter.sendMessage(CC.translate("&bRange: " + String.format("%.1f", distance))); + shooter.sendMessage(CC.translate("&7Marked &b" + damaged.getName() + " &7for &b10 seconds &b" + heartdamage + "(&4heart)")); + + damaged.sendMessage(CC.translate("&bMarked! &7" + shooter.getName() + " has &bshot &7you and &bmarked &7you (+25% damage) for &b10 seconds&7. &b(" + String.format("%.1f", distance) + " blocks away)")); + + LeatherArmorMeta helmMeta = (LeatherArmorMeta) shooter.getInventory().getHelmet().getItemMeta(); + LeatherArmorMeta chestMeta = (LeatherArmorMeta) shooter.getInventory().getChestplate().getItemMeta(); + LeatherArmorMeta leggingsMeta = (LeatherArmorMeta) shooter.getInventory().getLeggings().getItemMeta(); + LeatherArmorMeta bootsMeta = (LeatherArmorMeta) shooter.getInventory().getBoots().getItemMeta(); + + Color green = Color.fromRGB(6717235); + + double r = random.nextDouble(); + + if ((r <= 0.5D) && (helmMeta.getColor().equals(green)) && (chestMeta.getColor().equals(green)) && (leggingsMeta.getColor().equals(green)) && (bootsMeta.getColor().equals(green))) { + damaged.addPotionEffect(new PotionEffect(PotionEffectType.POISON, 120, 0)); + shooter.sendMessage(ChatColor.GRAY + "Since your armor is green, you gave " + damaged.getName() + " the poison effect for 6 seconds..."); + damaged.sendMessage(ChatColor.GRAY + "Since " + shooter.getName() + "'s armor is green, you were given the poison effect for 6 seconds..."); + } + Color blue = Color.fromRGB(3361970); + if ((r <= 0.5D) && (helmMeta.getColor().equals(blue)) && (chestMeta.getColor().equals(blue)) && (leggingsMeta.getColor().equals(blue)) && (bootsMeta.getColor().equals(blue))) { + damaged.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 120, 0)); + shooter.sendMessage(ChatColor.GRAY + "Since your armor is blue, you gave " + damaged.getName() + " the slowness effect for 6 seconds..."); + damaged.sendMessage(ChatColor.GRAY + "Since " + shooter.getName() + "'s armor is blue, you were given the slowness effect for 6 seconds..."); + } + Color gray = Color.fromRGB(5000268); + if ((r <= 0.5D) && (helmMeta.getColor().equals(gray)) && (chestMeta.getColor().equals(gray)) && (leggingsMeta.getColor().equals(gray)) && (bootsMeta.getColor().equals(gray))) { + damaged.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 120, 0)); + shooter.sendMessage(ChatColor.GRAY + "Since your armor is gray, you gave " + damaged.getName() + " the blindness effect for 6 seconds..."); + damaged.sendMessage(ChatColor.GRAY + "Since " + shooter.getName() + "'s armor is gray, you were given the blindness effect for 6 seconds..."); + } + Color black = Color.fromRGB(1644825); + if ((r <= 0.2D) && (helmMeta.getColor().equals(black)) && (chestMeta.getColor().equals(black)) && (leggingsMeta.getColor().equals(black)) && (bootsMeta.getColor().equals(black))) { + damaged.addPotionEffect(new PotionEffect(PotionEffectType.WITHER, 120, 0)); + shooter.sendMessage(ChatColor.GRAY + "Since your armor is black, you gave " + damaged.getName() + " the wither effect for 6 seconds..."); + damaged.sendMessage(ChatColor.GRAY + "Since " + shooter.getName() + "'s armor is black, you were given the wither effect for 6 seconds..."); + } + } + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + UUID uuid = player.getUniqueId(); + Action action = event.getAction(); + if (((action == Action.RIGHT_CLICK_AIR) || (action == Action.RIGHT_CLICK_BLOCK)) && (event.hasItem()) && (event.getItem().getType() == Material.SUGAR)) { + if (this.plugin.getHcfManager().getHCFClass(event.getPlayer()) != this) { + return; + } + + long timestamp = archerSpeedCooldowns.get(uuid); + long millis = System.currentTimeMillis(); + long remaining = timestamp == archerSpeedCooldowns.getNoEntryValue() ? -1L : timestamp - millis; + if (remaining > 0L) { + player.sendMessage(CC.RED + "You cannot use this for another " + CC.BOLD + DurationFormatUtils.formatDurationWords(remaining, true, true) + "."); + } else { + ItemStack stack = player.getItemInHand(); + if (stack.getAmount() == 1) { + player.setItemInHand(new ItemStack(Material.AIR, 1)); + } else { + stack.setAmount(stack.getAmount() - 1); + } + + this.plugin.getEffectRestorer().setRestoreEffect(player, ARCHER_SPEED_EFFECT); + archerSpeedCooldowns.put(event.getPlayer().getUniqueId(), System.currentTimeMillis() + ARCHER_SPEED_COOLDOWN_DELAY); + + Profile practicePlayerData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> { + if (practicePlayerData.getState() == ProfileState.FIGHTING) { + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 2)); + } + }, 161L); + } + } else if (((action == Action.RIGHT_CLICK_AIR) || (action == Action.RIGHT_CLICK_BLOCK)) && (event.hasItem()) && (event.getItem().getType() == Material.FEATHER)) { + if (this.plugin.getHcfManager().getHCFClass(event.getPlayer()) != this) { + return; + } + + long timestamp1 = archerJumpCooldowns.get(uuid); + long millis1 = System.currentTimeMillis(); + long remaining1 = timestamp1 == archerJumpCooldowns.getNoEntryValue() ? -1L : timestamp1 - millis1; + if (remaining1 > 0L) { + player.sendMessage(CC.RED + "You cannot use this for another " + CC.BOLD + DurationFormatUtils.formatDurationWords(remaining1, true, true) + "."); + } else { + ItemStack stack = player.getItemInHand(); + if (stack.getAmount() == 1) { + player.setItemInHand(new ItemStack(Material.AIR, 1)); + } else { + stack.setAmount(stack.getAmount() - 1); + } + + this.plugin.getEffectRestorer().setRestoreEffect(player, ARCHER_JUMP_EFFECT); + archerJumpCooldowns.put(event.getPlayer().getUniqueId(), System.currentTimeMillis() + ARCHER_JUMP_COOLDOWN_DELAY); + } + } else if (((action == Action.RIGHT_CLICK_AIR) || (action == Action.RIGHT_CLICK_BLOCK)) && (event.hasItem()) && (event.getItem().getType() == Material.IRON_INGOT)) { + if (this.plugin.getHcfManager().getHCFClass(event.getPlayer()) != this) { + return; + } + + long timestamp = archerResistanceCooldowns.get(uuid); + long millis = System.currentTimeMillis(); + long remaining = timestamp == archerResistanceCooldowns.getNoEntryValue() ? -1L : timestamp - millis; + if (remaining > 0L) { + player.sendMessage(CC.RED + "You cannot use this for another " + CC.BOLD + DurationFormatUtils.formatDurationWords(remaining, true, true) + "."); + } else { + ItemStack stack = player.getItemInHand(); + if (stack.getAmount() == 1) { + player.setItemInHand(new ItemStack(Material.AIR, 1)); + } else { + stack.setAmount(stack.getAmount() - 1); + } + + this.plugin.getEffectRestorer().setRestoreEffect(player, ARCHER_RESISTANCE_EFFECT); + archerResistanceCooldowns.put(event.getPlayer().getUniqueId(), System.currentTimeMillis() + ARCHER_RESISTANCE_COOLDOWN_DELAY); + } + } + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent event) { + if (!(event.getEntity() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity(); + if (!tag.contains(player.getUniqueId())) { + return; + } + + double damage = event.getDamage() * 0.25; + event.setDamage(event.getDamage() + damage); + } + + @Override + public boolean onEquip(Player player) { + for (PotionEffect effect : getEffects()) { + player.addPotionEffect(effect, true); + } + + return true; + } + + @Override + public void onUnEquip(Player player) { + for (PotionEffect effect : this.getEffects()) { + for (PotionEffect active : player.getActivePotionEffects()) { + if (active.getDuration() > HCFClass.DEFAULT_MAX_DURATION && active.getType().equals(effect.getType()) && active.getAmplifier() == effect.getAmplifier()) { + player.removePotionEffect(effect.getType()); + break; + } + } + } + } + + @Override + public void onQuit(Player player) { + TAGGED.remove(player.getUniqueId()); + } + + public static class TaggedTask extends BukkitRunnable { + + private final Player victim; + + public TaggedTask(Player victim) { + this.victim = victim; + tag.add(victim.getUniqueId()); + this.runTaskLater(Practice.getInstance(), 200L); + } + + public void run() { + tag.remove(this.victim.getUniqueId()); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/classes/Bard.java b/Practice/src/main/java/me/devkevin/practice/hcf/classes/Bard.java new file mode 100644 index 0000000..7412eab --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/classes/Bard.java @@ -0,0 +1,324 @@ +package me.devkevin.practice.hcf.classes; + +import club.inverted.chatcolor.CC; +import gnu.trove.map.TObjectLongMap; +import gnu.trove.map.hash.TObjectLongHashMap; +import me.devkevin.practice.Practice; +import me.devkevin.practice.hcf.HCFClass; +import me.devkevin.practice.hcf.effects.BardData; +import me.devkevin.practice.hcf.effects.EffectData; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:32 + * Bard / me.devkevin.practice.hcf.classes / Practice + */ +public class Bard extends HCFClass { + + private final Practice plugin = Practice.getInstance(); + + public static TObjectLongMap cooldowns = new TObjectLongHashMap<>(); + public static long buff_cooldown = TimeUnit.SECONDS.toMillis(10L); + + public static long held_reapply_ticks = 20L; + public static final Map bardDataMap = new HashMap<>(); + public static Map bardEffects = new EnumMap<>(Material.class); + + public Bard() { + super("Bard"); + + this.getEffects().add(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, Integer.MAX_VALUE, 1)); + this.getEffects().add(new PotionEffect(PotionEffectType.REGENERATION, Integer.MAX_VALUE, 0)); + this.getEffects().add(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1)); + + bardEffects.put(Material.FERMENTED_SPIDER_EYE, new EffectData(60, new PotionEffect(PotionEffectType.INVISIBILITY, 120, 1), new PotionEffect(PotionEffectType.INVISIBILITY, 100, 0))); + bardEffects.put(Material.WHEAT, new EffectData(35, new PotionEffect(PotionEffectType.SATURATION, 120, 1), new PotionEffect(PotionEffectType.SATURATION, 100, 0))); + bardEffects.put(Material.SUGAR, new EffectData(25, new PotionEffect(PotionEffectType.SPEED, 120, 2), new PotionEffect(PotionEffectType.SPEED, 100, 1))); + bardEffects.put(Material.BLAZE_POWDER, new EffectData(50, new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 120, 1), new PotionEffect(PotionEffectType.INCREASE_DAMAGE, 100, 0))); + bardEffects.put(Material.IRON_INGOT, new EffectData(35, new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 80, 2), new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 100, 0))); + bardEffects.put(Material.GHAST_TEAR, new EffectData(45, new PotionEffect(PotionEffectType.REGENERATION, 60, 2), new PotionEffect(PotionEffectType.REGENERATION, 100, 0))); + bardEffects.put(Material.FEATHER, new EffectData(30, new PotionEffect(PotionEffectType.JUMP, 120, 5), new PotionEffect(PotionEffectType.JUMP, 100, 0))); + bardEffects.put(Material.SPIDER_EYE, new EffectData(50, new PotionEffect(PotionEffectType.WITHER, 100, 1), null)); + bardEffects.put(Material.MAGMA_CREAM, new EffectData(10, new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 900, 0), new PotionEffect(PotionEffectType.FIRE_RESISTANCE, 120, 0))); + } + + public static double getEnergy(Player player) { + BardData bardData = bardDataMap.get(player.getUniqueId()); + return (bardData == null) ? 0.0 : bardData.getEnergy(); + } + + @Override + public boolean canApply(Player player) { + ItemStack helmet = player.getInventory().getHelmet(); + if (helmet == null || helmet.getType() != Material.GOLD_HELMET) { + return false; + } + + ItemStack chestplate = player.getInventory().getChestplate(); + if (chestplate == null || chestplate.getType() != Material.GOLD_CHESTPLATE) { + return false; + } + + ItemStack leggings = player.getInventory().getLeggings(); + if (leggings == null || leggings.getType() != Material.GOLD_LEGGINGS) { + return false; + } + + ItemStack boots = player.getInventory().getBoots(); + return !(boots == null || boots.getType() != Material.GOLD_BOOTS); + } + + @Override + public boolean onEquip(Player player) { + for (PotionEffect effect : getEffects()) { + player.addPotionEffect(effect, true); + } + + BardData bardData = new BardData(); + bardDataMap.put(player.getUniqueId(), bardData); + bardData.startEnergyTracking(); + + bardData.heldTask = new BukkitRunnable() { + int lastEnergy; + + public void run() { + ItemStack held = player.getItemInHand(); + if (held != null) { + EffectData bardEffect = bardEffects.get(held.getType()); + if (bardEffect == null) { + return; + } + + getNearbyPlayers(player, true).forEach(bardPlayer -> { + Practice.getInstance().getEffectRestorer().setRestoreEffect(bardPlayer, bardEffect.heldable); + }); + } + + int energy = (int) getEnergy(player); + if (energy != 0 && energy != lastEnergy && (energy % 10 == 0 || lastEnergy - energy - 1 > 0 || energy == BardData.MAX_ENERGY)) { + lastEnergy = energy; + + player.sendMessage(CC.translate("&eBard Energy: &d" + energy)); + } + } + }.runTaskTimerAsynchronously(this.plugin, 0L, held_reapply_ticks); + + return true; + } + + private void clearBardData(UUID uuid) { + BardData bardData = bardDataMap.remove(uuid); + if (bardData != null && bardData.getHeldTask() != null) { + bardData.getHeldTask().cancel(); + } + } + + public long getEnergyMillis(Player player) { + synchronized (bardDataMap) { + BardData bardData = bardDataMap.get(player.getUniqueId()); + return (bardData == null) ? 0L : bardData.getEnergyMillis(); + } + } + + public double setEnergy(Player player, double energy) { + BardData bardData = bardDataMap.get(player.getUniqueId()); + if (bardData == null) { + return 0.0; + } + + bardData.setEnergy(energy); + return bardData.getEnergy(); + } + + public List getNearbyPlayers(Player player, boolean friend) { + List players = new ArrayList<>(); + Profile practicePlayerData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (practicePlayerData.getState() != ProfileState.FIGHTING) { + return players; + } + if (!practicePlayerData.isInParty()) { + return players; + } + + Match match = this.plugin.getMatchManager().getMatch(practicePlayerData.getUuid()); + MatchTeam opposingTeam = match.isFFA() ? match.getTeams().get(0) : (practicePlayerData.getTeamID() == 0 ? match.getTeams().get(1) : match.getTeams().get(0)); + MatchTeam playerTeam = match.getTeams().get(practicePlayerData.getTeamID()); + if (friend) { + playerTeam.getAlivePlayers().forEach(uuid -> { + players.add(Bukkit.getPlayer(uuid)); + }); + players.add(player); + } else { + opposingTeam.getAlivePlayers().forEach(uuid -> { + players.add(Bukkit.getPlayer(uuid)); + }); + } + + return players; + } + + @Override + public void onUnEquip(Player player) { + for (PotionEffect effect : getEffects()) { + player.removePotionEffect(effect.getType()); + } + + clearBardData(player.getUniqueId()); + } + + @Override + public void onQuit(Player player) { + clearBardData(player.getUniqueId()); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerKick(PlayerKickEvent event) { + this.clearBardData(event.getPlayer().getUniqueId()); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onItemHeld(PlayerItemHeldEvent event) { + Player player = event.getPlayer(); + HCFClass equipped = this.plugin.getHcfManager().getHCFClass(player); + if (equipped == null || !equipped.equals(this)) { + return; + } + + UUID uuid = player.getUniqueId(); + long lastMessage = cooldowns.get(uuid); + long millis = System.currentTimeMillis(); + + if (lastMessage != cooldowns.getNoEntryValue() && lastMessage - millis > 0L) { + return; + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (!event.hasItem()) { + return; + } + + Action action = event.getAction(); + if (action == Action.RIGHT_CLICK_AIR || (!event.isCancelled() && action == Action.RIGHT_CLICK_BLOCK)) { + Player player = event.getPlayer(); + ItemStack stack = event.getItem(); + EffectData bardEffect = bardEffects.get(stack.getType()); + if (bardEffect == null || bardEffect.clickable == null) { + return; + } + + event.setUseItemInHand(Event.Result.DENY); + BardData bardData = bardDataMap.get(player.getUniqueId()); + if (bardData != null) { + if (!this.canUseBardEffect(player, bardData, bardEffect, true)) { + return; + } + if (stack.getAmount() > 1) { + stack.setAmount(stack.getAmount() - 1); + } else { + player.setItemInHand(new ItemStack(Material.AIR, 1)); + } + + Profile data = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (data != null && !bardEffect.clickable.getType().equals(PotionEffectType.SLOW_DIGGING)) { + getNearbyPlayers(player, true).stream().filter(player1 -> player1.getUniqueId() != player.getUniqueId()).forEach(bardPlayer -> { + this.plugin.getEffectRestorer().setRestoreEffect(bardPlayer, bardEffect.clickable); + }); + } else if (data != null && bardEffect.clickable.getType().equals(PotionEffectType.SLOW_DIGGING)) { + getNearbyPlayers(player, false).forEach(player1 -> { + this.plugin.getEffectRestorer().setRestoreEffect(player1, bardEffect.clickable); + }); + } else if (bardEffect.clickable.getType().equals(PotionEffectType.SLOW_DIGGING)) { + Collection nearbyEntities = player.getNearbyEntities(10.0, 10.0, 10.0); + for (Entity nearby : nearbyEntities) { + if (nearby instanceof Player && !player.equals(nearby)) { + Player target = (Player) nearby; + this.plugin.getEffectRestorer().setRestoreEffect(target, bardEffect.clickable); + } + } + } + if (data != null && !bardEffect.clickable.getType().equals(PotionEffectType.SLOW)) { + getNearbyPlayers(player, true).stream().filter(player1 -> player1.getUniqueId() != player.getUniqueId()).forEach(bardPlayer -> { + this.plugin.getEffectRestorer().setRestoreEffect(bardPlayer, bardEffect.clickable); + }); + } else if (data != null && bardEffect.clickable.getType().equals(PotionEffectType.SLOW)) { + getNearbyPlayers(player, false).stream().filter(player1 -> player1.getUniqueId() != player.getUniqueId()).forEach(bardPlayer -> { + this.plugin.getEffectRestorer().setRestoreEffect(bardPlayer, bardEffect.clickable); + }); + } else if (bardEffect.clickable.getType().equals(PotionEffectType.SLOW)) { + Collection nearbyEntities = player.getNearbyEntities(15.0, 15.0, 15.0); + for (Entity nearby : nearbyEntities) { + if (nearby instanceof Player && !player.equals(nearby)) { + Player target = (Player) nearby; + this.plugin.getEffectRestorer().setRestoreEffect(target, bardEffect.clickable); + } + } + } + if (data != null && !bardEffect.clickable.getType().equals(PotionEffectType.WITHER)) { + getNearbyPlayers(player, true).stream().filter(player1 -> player1.getUniqueId() != player.getUniqueId()).forEach(bardPlayer -> { + this.plugin.getEffectRestorer().setRestoreEffect(bardPlayer, bardEffect.clickable); + }); + } else if (data != null && bardEffect.clickable.getType().equals(PotionEffectType.WITHER)) { + getNearbyPlayers(player, false).stream().filter(player1 -> player1.getUniqueId() != player.getUniqueId()).forEach(bardPlayer -> { + this.plugin.getEffectRestorer().setRestoreEffect(bardPlayer, bardEffect.clickable); + }); + } else if (bardEffect.clickable.getType().equals(PotionEffectType.WITHER)) { + Collection nearbyEntities = player.getNearbyEntities(25.0, 25.0, 25.0); + for (Entity nearby : nearbyEntities) { + if (nearby instanceof Player && !player.equals(nearby)) { + Player target = (Player) nearby; + this.plugin.getEffectRestorer().setRestoreEffect(target, bardEffect.clickable); + } + } + } + + this.plugin.getEffectRestorer().setRestoreEffect(player, bardEffect.clickable); + bardData.setBuffCooldown(buff_cooldown); + this.setEnergy(player, bardData.getEnergy() - bardEffect.energyCost); + + player.sendMessage(CC.translate("&cYou have just used a &fBard Buff &cthat cost you " + bardEffect.energyCost + " &cof your Energy.")); + } + } + } + + private boolean canUseBardEffect(Player player, BardData bardData, EffectData bardEffect, boolean sendFeedback) { + String errorFeedback = null; + double currentEnergy = bardData.getEnergy(); + if (bardEffect.energyCost > currentEnergy) { + errorFeedback = CC.translate("&cYou do not have enough energy for this! You need " + bardEffect.energyCost + " energy, but you only have " + currentEnergy); + } + + long remaining = bardData.getRemainingBuffDelay() / 1000L; + if (remaining > 0L) { + errorFeedback = CC.RED + "You cannot use this for another " + CC.BOLD + remaining + CC.RED + " seconds."; + } + if (sendFeedback && errorFeedback != null) { + player.sendMessage(errorFeedback); + } + + return errorFeedback == null; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/effects/BardData.java b/Practice/src/main/java/me/devkevin/practice/hcf/effects/BardData.java new file mode 100644 index 0000000..5e84160 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/effects/BardData.java @@ -0,0 +1,66 @@ +package me.devkevin.practice.hcf.effects; + +import com.google.common.base.Preconditions; +import org.bukkit.scheduler.BukkitTask; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:22 + * BardData / me.devkevin.practice.hcf.effects / Practice + */ +public class BardData { + public static double ENERGY_PER_MILLISECOND; + public static double MIN_ENERGY; + public static double MAX_ENERGY; + public static long MAX_ENERGY_MILLIS; + + static { + BardData.ENERGY_PER_MILLISECOND = 1.0; + BardData.MIN_ENERGY = 0.0; + BardData.MAX_ENERGY = 120 + 0.0; + BardData.MAX_ENERGY_MILLIS = (long) (BardData.MAX_ENERGY * 1000.0); + } + + public long energyStart; + public long buffCooldown; + public BukkitTask heldTask; + + public BukkitTask getHeldTask() { + return this.heldTask; + } + + public long getBuffCooldown() { + return this.buffCooldown; + } + + public void setBuffCooldown(long millis) { + this.buffCooldown = System.currentTimeMillis() + millis; + } + + public long getRemainingBuffDelay() { + return this.buffCooldown - System.currentTimeMillis(); + } + + public void startEnergyTracking() { + this.setEnergy(0.0); + } + + public long getEnergyMillis() { + if (this.energyStart == 0L) { + return 0L; + } + + return Math.min(BardData.MAX_ENERGY_MILLIS, (long) (BardData.ENERGY_PER_MILLISECOND * (System.currentTimeMillis() - this.energyStart))); + } + + public double getEnergy() { + return Math.round(this.getEnergyMillis() / 100.0) / 10.0; + } + + public void setEnergy(double energy) { + Preconditions.checkArgument(energy >= BardData.MIN_ENERGY, "Energy cannot be less than " + BardData.MIN_ENERGY); + Preconditions.checkArgument(energy <= BardData.MAX_ENERGY, "Energy cannot be more than " + BardData.MAX_ENERGY); + + this.energyStart = (long) (System.currentTimeMillis() - 1000.0 * energy); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/effects/EffectData.java b/Practice/src/main/java/me/devkevin/practice/hcf/effects/EffectData.java new file mode 100644 index 0000000..44d48f5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/effects/EffectData.java @@ -0,0 +1,15 @@ +package me.devkevin.practice.hcf.effects; + +import lombok.AllArgsConstructor; +import org.bukkit.potion.PotionEffect; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:20 + * EffectData / me.devkevin.practice.hcf.effects / Practice + */ +@AllArgsConstructor +public class EffectData { + public int energyCost; + public PotionEffect clickable, heldable; +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/effects/EffectRestorer.java b/Practice/src/main/java/me/devkevin/practice/hcf/effects/EffectRestorer.java new file mode 100644 index 0000000..81cbdd8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/effects/EffectRestorer.java @@ -0,0 +1,58 @@ +package me.devkevin.practice.hcf.effects; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; +import me.devkevin.practice.Practice; +import me.devkevin.practice.hcf.HCFClass; +import me.devkevin.practice.hcf.classes.Bard; +import me.devkevin.practice.hcf.event.ArmorClassUnequipEvent; +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.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:27 + * EffectRestorer / me.devkevin.practice.hcf.effects / Practice + */ +public class EffectRestorer implements Listener { + + private final Table restorableEffectsTable; + + public EffectRestorer() { + this.restorableEffectsTable = HashBasedTable.create(); + Bukkit.getPluginManager().registerEvents(this, Practice.getInstance()); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onArmorClassUnequip(ArmorClassUnequipEvent event) { + this.restorableEffectsTable.rowKeySet().remove(event.getPlayer().getUniqueId()); + } + + public void setRestoreEffect(Player player, PotionEffect effect) { + boolean shouldCancel = true; + + for (PotionEffect active : player.getActivePotionEffects()) { + if (!active.getType().equals(effect.getType())) continue; + if (effect.getAmplifier() < active.getAmplifier()) return; + if (effect.getAmplifier() == active.getAmplifier() && effect.getDuration() < active.getDuration()) return; + + this.restorableEffectsTable.put(player.getUniqueId(), active.getType(), active); + shouldCancel = false; + + break; + } + + Bukkit.getScheduler().runTask(Practice.getInstance(), () -> player.addPotionEffect(effect, true)); + + if (shouldCancel && effect.getDuration() > Bard.held_reapply_ticks && effect.getDuration() < HCFClass.DEFAULT_MAX_DURATION) { + this.restorableEffectsTable.remove(player.getUniqueId(), effect.getType()); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/event/ArmorClassEquipEvent.java b/Practice/src/main/java/me/devkevin/practice/hcf/event/ArmorClassEquipEvent.java new file mode 100644 index 0000000..70b1074 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/event/ArmorClassEquipEvent.java @@ -0,0 +1,33 @@ +package me.devkevin.practice.hcf.event; + +import lombok.Getter; +import me.devkevin.practice.hcf.HCFClass; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:15 + * ArmorClassEquipEvent / me.devkevin.practice.hcf.event / Practice + */ +@Getter +public class ArmorClassEquipEvent extends PlayerEvent { + + private static final HandlerList HANDLERS = new HandlerList(); + private final HCFClass hcfClass; + + public ArmorClassEquipEvent(Player player, HCFClass hcfClass) { + super(player); + this.hcfClass = hcfClass; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/event/ArmorClassUnequipEvent.java b/Practice/src/main/java/me/devkevin/practice/hcf/event/ArmorClassUnequipEvent.java new file mode 100644 index 0000000..5032158 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/event/ArmorClassUnequipEvent.java @@ -0,0 +1,34 @@ +package me.devkevin.practice.hcf.event; + +import lombok.Getter; +import me.devkevin.practice.hcf.HCFClass; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:15 + * ArmorClassUnequipEvent / me.devkevin.practice.hcf.event / Practice + */ +@Getter +public class ArmorClassUnequipEvent extends PlayerEvent { + + private static final HandlerList HANDLERS = new HandlerList(); + private final HCFClass hcfClass; + + public ArmorClassUnequipEvent(Player player, HCFClass hcfClass) { + super(player); + this.hcfClass = hcfClass; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/kit/HCFKit.java b/Practice/src/main/java/me/devkevin/practice/hcf/kit/HCFKit.java new file mode 100644 index 0000000..3d06e42 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/kit/HCFKit.java @@ -0,0 +1,130 @@ +package me.devkevin.practice.hcf.kit; + +import me.devkevin.practice.util.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:12 + * HCFKit / me.devkevin.practice.hcf.kit / Practice + */ +public class HCFKit { + + public final ItemStack fireRes = new ItemStack(Material.POTION, 1, (short) 8259); + + public void giveBardKit(Player player) { + ItemStack helmet = new ItemStack(Material.GOLD_HELMET, 1); + helmet.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + helmet.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + + ItemStack chestplate = new ItemStack(Material.GOLD_CHESTPLATE, 1); + chestplate.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + chestplate.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + + ItemStack pants = new ItemStack(Material.GOLD_LEGGINGS, 1); + pants.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + pants.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + + ItemStack boots = new ItemStack(Material.GOLD_BOOTS, 1); + boots.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + boots.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + boots.addEnchantment(Enchantment.PROTECTION_FALL, 4); + + PlayerInventory inventory = player.getInventory(); + giveSword(player, inventory); + inventory.setItem(1, new ItemStack(Material.ENDER_PEARL, 16)); + inventory.setItem(2, new ItemStack(Material.BLAZE_POWDER, 32)); + inventory.setItem(3, new ItemStack(Material.SUGAR, 32)); + //inventory.setItem(7, fireRes); + inventory.setItem(8, new ItemStack(Material.BAKED_POTATO, 64)); + inventory.setItem(9, new ItemStack(Material.IRON_INGOT, 32)); + inventory.setItem(10, new ItemStack(Material.GHAST_TEAR, 32)); + inventory.setItem(18, new ItemStack(Material.FEATHER, 32)); + inventory.setItem(19, new ItemStack(Material.MAGMA_CREAM, 32)); + giveHealing(player); + + inventory.setHelmet(helmet); + inventory.setChestplate(chestplate); + inventory.setLeggings(pants); + inventory.setBoots(boots); + + player.updateInventory(); + + player.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, Integer.MAX_VALUE, 1)); + } + + public void giveArcherKit(Player player) { + ItemStack helmet = new ItemStack(Material.LEATHER_HELMET, 1); + helmet.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + helmet.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + + ItemStack chestplate = new ItemStack(Material.LEATHER_CHESTPLATE, 1); + chestplate.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + chestplate.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + + ItemStack pants = new ItemStack(Material.LEATHER_LEGGINGS, 1); + pants.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + pants.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + + ItemStack boots = new ItemStack(Material.LEATHER_BOOTS, 1); + boots.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 2); + boots.addUnsafeEnchantment(Enchantment.DURABILITY, 5); + boots.addEnchantment(Enchantment.PROTECTION_FALL, 4); + + ItemStack bow = new ItemStack(Material.BOW, 1); + bow.addEnchantment(Enchantment.ARROW_DAMAGE, 5); + bow.addEnchantment(Enchantment.ARROW_FIRE, 1); + bow.addEnchantment(Enchantment.ARROW_INFINITE, 1); + bow.addEnchantment(Enchantment.DURABILITY, 3); + + PlayerInventory inventory = player.getInventory(); + giveSword(player, inventory); + inventory.setItem(1, new ItemStack(Material.ENDER_PEARL, 16)); + inventory.setItem(2, bow); + //inventory.setItem(3, fireRes); + inventory.setItem(7, new ItemStack(Material.SUGAR, 32)); + inventory.setItem(8, new ItemStack(Material.BAKED_POTATO, 64)); + inventory.setItem(9, new ItemStack(Material.ARROW, 1)); + giveHealing(player); + + inventory.setHelmet(helmet); + inventory.setChestplate(chestplate); + inventory.setLeggings(pants); + inventory.setBoots(boots); + + player.updateInventory(); + + // give auto potion effects + player.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, Integer.MAX_VALUE, 1)); + } + + private void giveSword(Player player, Inventory inventory) { + boolean hasSword = false; + + for (ItemStack item : player.getInventory().getContents()) { + if (item != null && item.getType() == Material.DIAMOND_SWORD) { + hasSword = true; + } + } + + if (!hasSword) { + inventory.setItem(0, new ItemBuilder(Material.DIAMOND_SWORD).enchantment(Enchantment.DAMAGE_ALL, 1).build()); + } + } + + private void giveHealing(Player player) { + final ItemStack heal = new ItemStack(Material.POTION, 1, (short) 16421); + for (ItemStack inv : player.getInventory().getContents()) { + if (inv == null) { + player.getInventory().addItem(heal); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/listener/HCFClassListener.java b/Practice/src/main/java/me/devkevin/practice/hcf/listener/HCFClassListener.java new file mode 100644 index 0000000..ec9cd30 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/listener/HCFClassListener.java @@ -0,0 +1,109 @@ +package me.devkevin.practice.hcf.listener; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.hcf.HCFClass; +import me.devkevin.practice.hcf.manager.HCFManager; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.profile.Profile; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:18 + * HCFClassListener / me.devkevin.practice.hcf.listener / Practice + */ +public class HCFClassListener implements Listener { + private final Practice plugin = Practice.getInstance(); + private final HCFManager hcfManager; + + public static List preWarmups = new ArrayList<>(); + public static Map cooldown = new HashMap<>(); + public static Map classWarmups = new HashMap<>(); + + public HCFClassListener(HCFManager hcfManager) { + this.hcfManager = hcfManager; + + new BukkitRunnable() { + @Override + public void run() { + for (Profile practicePlayerData : Practice.getInstance().getProfileManager().getAllData()) { + if (practicePlayerData.isFighting()) { + Player player = Bukkit.getPlayer(practicePlayerData.getUuid()); + Match match = Practice.getInstance().getMatchManager().getMatch(player.getUniqueId()); + + if (match.isPartyMatch()) { + if (match.getKit().getName().equalsIgnoreCase("HCF")) { + attemptEquip(player); + } + } + } + } + } + }.runTaskTimerAsynchronously(this.plugin, 20L, 20L); + + Practice.getInstance().getServer().getPluginManager().registerEvents(this, this.plugin); + } + + public static boolean isActive(Player player) { + return cooldown.containsKey(player.getUniqueId()) && System.currentTimeMillis() < cooldown.get(player.getUniqueId()); + } + + public static void applyCooldown(Player player, int seconds) { + cooldown.put(player.getUniqueId(), System.currentTimeMillis() + (seconds * 1000)); + } + + public static void clearCooldown(Player player) { + cooldown.remove(player.getUniqueId()); + } + + @EventHandler + public void onPlayerDeath(PlayerDeathEvent event) { + hcfManager.setEquippedClass(event.getEntity(), null); + } + + private void attemptEquip(Player player) { + HCFClass current = hcfManager.getHCFClass(player); + if (current != null) { + if (current.canApply(player)) { + return; + } + + hcfManager.setEquippedClass(player, null); + preWarmups.remove(player.getUniqueId()); + } else if ((current = classWarmups.get(player.getUniqueId())) != null) { + if (current.canApply(player)) { + return; + } + + clearCooldown(player); + preWarmups.remove(player.getUniqueId()); + } + + hcfManager.getClasses().forEach(hcfClass -> { + if (hcfClass.canApply(player)) { + classWarmups.put(player.getUniqueId(), hcfClass); + preWarmups.add(player.getUniqueId()); + + applyCooldown(player, 2); + + new BukkitRunnable() { + public void run() { + HCFClass pvpClass = classWarmups.remove(player.getUniqueId()); + + if (preWarmups.contains(player.getUniqueId())) { + hcfManager.setEquippedClass(player, pvpClass); + preWarmups.remove(player.getUniqueId()); + } + } + }.runTaskLater(this.plugin, 40L); + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/listener/HCFMatchListener.java b/Practice/src/main/java/me/devkevin/practice/hcf/listener/HCFMatchListener.java new file mode 100644 index 0000000..7fa7e4e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/listener/HCFMatchListener.java @@ -0,0 +1,92 @@ +package me.devkevin.practice.hcf.listener; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.profile.Profile; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:19 + * HCFMatchListener / me.devkevin.practice.hcf.listener / Practice + */ +public class HCFMatchListener implements Listener { + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onPlayerDamage(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Player)) { + return; + } + + Player player = (Player) event.getDamager(); + if (!player.hasPotionEffect(PotionEffectType.INCREASE_DAMAGE)) { + return; + } + + Profile data = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (data == null) { + return; + } + if (!data.isFighting()) { + return; + } + + Match match = this.plugin.getMatchManager().getMatch(data); + if (match == null) { + return; + } + if (!match.getKit().getName().equalsIgnoreCase("HCF")) { + return; + } + + for (PotionEffect Effect : player.getActivePotionEffects()) { + if (Effect.getType().equals(PotionEffectType.INCREASE_DAMAGE)) { + final double damageVal = (Effect.getAmplifier() + 1) * 1.3 + 1.0; + int newDamage; + if (event.getDamage() / damageVal <= 1.0) { + newDamage = (Effect.getAmplifier() + 1) * 3 + 1; + } else { + newDamage = (int) (event.getDamage() / damageVal) + (Effect.getAmplifier() + 1) * 3; + } + + event.setDamage(newDamage); + } + } + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + + Match match = this.plugin.getMatchManager().getMatch(profile); + + if (match != null) { + if (match.getKit().isHcf()) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + switch (event.getClickedBlock().getType()) { + case FENCE_GATE: + case ACACIA_FENCE_GATE: + case BIRCH_FENCE_GATE: + case DARK_OAK_FENCE_GATE: + case SPRUCE_FENCE_GATE: + case JUNGLE_FENCE_GATE: + if (match.getTeams().get(profile.getTeamID()).getTeamID() == 1) { + event.setCancelled(true); + } + break; + } + } + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/manager/HCFManager.java b/Practice/src/main/java/me/devkevin/practice/hcf/manager/HCFManager.java new file mode 100644 index 0000000..2cc0609 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/manager/HCFManager.java @@ -0,0 +1,39 @@ +package me.devkevin.practice.hcf.manager; + +import lombok.Getter; +import me.devkevin.practice.hcf.HCFClass; +import me.devkevin.practice.hcf.event.ArmorClassEquipEvent; +import me.devkevin.practice.hcf.event.ArmorClassUnequipEvent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.*; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 0:08 + * HCFManager / me.devkevin.practice.hcf.manager / Practice + */ +@Getter +public class HCFManager { + private final List classes = new ArrayList<>(); + private final Map equippedClassMap = new HashMap<>(); + + public HCFClass getHCFClass(Player player) { + return equippedClassMap.getOrDefault(player.getUniqueId(), null); + } + + public void setEquippedClass(Player player, HCFClass hcfClass) { + if (hcfClass == null) { + HCFClass equipped = equippedClassMap.remove(player.getUniqueId()); + + if (equipped != null) { + equipped.onUnEquip(player); + Bukkit.getPluginManager().callEvent(new ArmorClassUnequipEvent(player, equipped)); + } + } else if (hcfClass.onEquip(player) && hcfClass != getHCFClass(player)) { + equippedClassMap.put(player.getUniqueId(), hcfClass); + Bukkit.getPluginManager().callEvent(new ArmorClassEquipEvent(player, hcfClass)); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/menu/ClassSelectionMenu.java b/Practice/src/main/java/me/devkevin/practice/hcf/menu/ClassSelectionMenu.java new file mode 100644 index 0000000..6f3b047 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/menu/ClassSelectionMenu.java @@ -0,0 +1,54 @@ +package me.devkevin.practice.hcf.menu; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.hcf.menu.button.ClassSelectionButton; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.pagination.PaginatedMenu; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 1:14 + * ClassSelectionMenu / me.devkevin.practice.hcf.menu / Practice + */ +public class ClassSelectionMenu extends PaginatedMenu { + + @Override + public void setUpdateAfterClick(boolean updateAfterClick) { + super.setUpdateAfterClick(true); + } + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.translate("&8HCF Team"); + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttonMap = new HashMap<>(); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (party != null) { + party.getMembers().forEach(member -> buttonMap.put(buttonMap.size(), new ClassSelectionButton(member))); + } + + return buttonMap; + } + + @Override + public Map getGlobalButtons(Player player) { + Map map = new HashMap<>(); + Button button = Button.placeholder(Material.STAINED_GLASS_PANE, (byte) 7, " "); + + for (int i = 1; i < 8; i++) { + map.put(i, button); + } + + return map; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/hcf/menu/button/ClassSelectionButton.java b/Practice/src/main/java/me/devkevin/practice/hcf/menu/button/ClassSelectionButton.java new file mode 100644 index 0000000..cb99c00 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/hcf/menu/button/ClassSelectionButton.java @@ -0,0 +1,69 @@ +package me.devkevin.practice.hcf.menu.button; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Bukkit; +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; +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 25/02/2023 @ 1:14 + * ClassSelectionButton / me.devkevin.practice.hcf.menu.button / Practice + */ +public class ClassSelectionButton extends Button { + + private final UUID uuid; + + public ClassSelectionButton(UUID uuid) { + this.uuid = uuid; + } + + @Override + public ItemStack getButtonItem(Player player) { + ItemBuilder itemBuilder = new ItemBuilder(Material.SKULL_ITEM).durability(3); + List lore = new ArrayList<>(); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (party.getBards().contains(uuid)) { + lore.add("&7Diamond"); + lore.add((party.isArcherFull() ? "&c&m" : "&7") + "Archer"); + lore.add("&7\u25CF &eBard"); + } else if (party.getArchers().contains(uuid)) { + lore.add("&7Diamond"); + lore.add("&7\u25CF &eArcher"); + lore.add((party.isBardFull() ? "&c&m" : "&7") + "Bard"); + } else { + lore.add("&7\u25CF &eDiamond"); + lore.add((party.isArcherFull() ? "&c&m" : "&7") + "Archer"); + lore.add((party.isBardFull() ? "&c&m" : "&7") + "Bard"); + } + + itemBuilder.name(CC.translate(CC.BLUE + Bukkit.getPlayer(uuid).getName())); + itemBuilder.owner(Bukkit.getPlayer(uuid).getName()); + itemBuilder.lore(CC.translate(lore)); + + return itemBuilder.build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (!party.getBards().contains(uuid) && !party.getArchers().contains(uuid) || !party.getArchers().contains(uuid) && !party.getBards().contains(uuid)) { + party.addBard(uuid); + } else if (party.getBards().contains(uuid)) { + party.addArcher(uuid); + } else { + party.removeClass(uuid); + } + + playNeutral(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/Kit.java b/Practice/src/main/java/me/devkevin/practice/kit/Kit.java new file mode 100644 index 0000000..c42883f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/Kit.java @@ -0,0 +1,164 @@ +package me.devkevin.practice.kit; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ + +@Getter +@Setter +@AllArgsConstructor +@RequiredArgsConstructor +public class Kit { + private final Practice plugin = Practice.getInstance(); + + private final String name; + + private ItemStack[] contents = new ItemStack[36]; + private ItemStack[] armor = new ItemStack[4]; + private ItemStack[] kitEditContents = new ItemStack[36]; + private ItemStack icon; + + private List arenaWhiteList = new ArrayList<>(); + + private boolean enabled; + private boolean ranked; + private boolean sumo; + private boolean build; + private boolean hcf; + private boolean parkour; + private boolean spleef; + private boolean bedWars; + private boolean combo; + private boolean boxing; + + public void whitelistArena(String arena) { + if (!this.arenaWhiteList.remove(arena)) { + this.arenaWhiteList.add(arena); + } + } + + public void applyToPlayer(Player player) { + player.getInventory().setContents(contents); + player.getInventory().setArmorContents(armor); + player.updateInventory(); + player.sendMessage(CC.YELLOW + "You equipped default kit."); + } + + /*public void applyKit(Player player, Profile profile) { + ItemStack[] playerContents = this.contents; + ItemStack[] playerArmor = this.armor; + if (profile.getCurrentKitContents() != null) { + playerContents = profile.getCurrentKitContents(); + } + + Color color = profile.getTeamID() == 0 ? Color.RED : Color.BLUE; + int data = color == Color.RED ? 14 : 11; + + int i = 0; + ItemStack[] finalContents = this.getColoredItems(playerContents, data, i); + player.getInventory().setContents(finalContents); + profile.setCurrentKitContents(finalContents); + + ItemStack[] finalArmor = this.getColoredArmor(playerArmor, color, i); + player.getInventory().setArmorContents(finalArmor); + + player.updateInventory(); + } + + public ItemStack[] getColoredItems(ItemStack[] items, int color, int i) { + ItemStack[] finalItems = new ItemStack[36]; + + for (ItemStack item : items) { + if (item != null && item.getType() != Material.AIR) { + if (item.getType() == Material.STAINED_CLAY) { + finalItems[i] = new ItemBuilder(item).durability(color).build(); + } else if (item.getType() == Material.WOOL) { + finalItems[i] = new ItemBuilder(item).durability(color).build(); + } else { + finalItems[i] = item; + } + } + + i++; + } + + return finalItems; + } + + public ItemStack[] getColoredArmor(ItemStack[] armor, Color color, int i) { + ItemStack[] finalArmor = new ItemStack[4]; + + for (ItemStack item : armor) { + if (item != null && item.getType() != Material.AIR) { + if (item.getType().name().startsWith("LEATHER_")) { + finalArmor[i] = new ItemBuilder(item).color(color).build(); + } else { + finalArmor[i] = item; + } + } + + i++; + } + + return finalArmor; + }*/ + + public int getEditorSlots() { + + if (Kit.this.getName().equalsIgnoreCase("Nodebuff")) return 10; + if (Kit.this.getName().equalsIgnoreCase("Debuff")) return 11; + if (Kit.this.getName().equalsIgnoreCase("Boxing")) return 12; + if (Kit.this.getName().equalsIgnoreCase("Vanilla")) return 13; + if (Kit.this.getName().equalsIgnoreCase("Axe")) return 14; + if (Kit.this.getName().equalsIgnoreCase("Combo")) return 15; + if (Kit.this.getName().equalsIgnoreCase("Gapple")) return 16; + if (Kit.this.getName().equalsIgnoreCase("BuildUHC")) return 19; + if (Kit.this.getName().equalsIgnoreCase("Soup")) return 20; + if (Kit.this.getName().equalsIgnoreCase("Sumo")) return 21; + if (Kit.this.getName().equalsIgnoreCase("Archer")) return 22; + if (Kit.this.getName().equalsIgnoreCase("Classic")) return 23; + if (Kit.this.getName().equalsIgnoreCase("invaded")) return 24; + if (Kit.this.getName().equalsIgnoreCase("Strategy")) return 25; + if (Kit.this.getName().equalsIgnoreCase("HCF")) return 28; + if (Kit.this.getName().equalsIgnoreCase("BedFight")) return 29; + + return 10; + } + + public int getPriority() { + //TODO: implement more ladders in the future + + if (Kit.this.getName().equalsIgnoreCase("Nodebuff")) return 10; + if (Kit.this.getName().equalsIgnoreCase("Debuff")) return 11; + if (Kit.this.getName().equalsIgnoreCase("Boxing")) return 12; + if (Kit.this.getName().equalsIgnoreCase("Vanilla")) return 13; + if (Kit.this.getName().equalsIgnoreCase("Axe")) return 14; + if (Kit.this.getName().equalsIgnoreCase("Combo")) return 15; + if (Kit.this.getName().equalsIgnoreCase("Gapple")) return 16; + if (Kit.this.getName().equalsIgnoreCase("BuildUHC")) return 19; + if (Kit.this.getName().equalsIgnoreCase("Soup")) return 20; + if (Kit.this.getName().equalsIgnoreCase("Sumo")) return 21; + if (Kit.this.getName().equalsIgnoreCase("Archer")) return 22; + if (Kit.this.getName().equalsIgnoreCase("Classic")) return 23; + if (Kit.this.getName().equalsIgnoreCase("invaded")) return 24; + if (Kit.this.getName().equalsIgnoreCase("Strategy")) return 25; + if (Kit.this.getName().equalsIgnoreCase("HCF")) return 28; + if (Kit.this.getName().equalsIgnoreCase("BedFight")) return 29; + + return 10; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/kit/PlayerKit.java b/Practice/src/main/java/me/devkevin/practice/kit/PlayerKit.java new file mode 100644 index 0000000..230135a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/PlayerKit.java @@ -0,0 +1,40 @@ +package me.devkevin.practice.kit; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Data +@AllArgsConstructor +@RequiredArgsConstructor +public class PlayerKit { + + private String name; + private final int index; + + private ItemStack[] contents; + private String displayName; + + public void applyToPlayer(Player player) { + for (ItemStack itemStack : this.contents) { + if (itemStack != null) { + if (itemStack.getAmount() <= 0) { + itemStack.setAmount(1); + } + } + } + player.getInventory().setContents(this.contents); + player.getInventory().setArmorContents(Practice.getInstance().getKitManager().getKit(this.name).getArmor()); + player.updateInventory(); + player.sendMessage(CC.YELLOW + "You equipped your " + CC.GOLD + this.displayName + CC.YELLOW + " Kit"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/command/KitManageCommand.java b/Practice/src/main/java/me/devkevin/practice/kit/command/KitManageCommand.java new file mode 100644 index 0000000..84634a1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/command/KitManageCommand.java @@ -0,0 +1,272 @@ +package me.devkevin.practice.kit.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +/** + * Copyright 01/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class KitManageCommand extends PracticeCommand { + + private static final Practice plugin = Practice.getInstance(); + + private final String NO_KIT = ChatColor.RED + "That kit doesn't exist!"; + private final String NO_ARENA = ChatColor.RED + "That arena doesn't exist!"; + + @Command(name = "kit", inGameOnly = true, usage = "&cUsage: /kit [args]", permission = Rank.DEVELOPER) + public void onCommand(CommandArgs command) { + CommandSender sender = command.getSender(); + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + + if (args[0].equalsIgnoreCase("save")) { + plugin.getKitManager().reloadKits(); + player.sendMessage(ChatColor.GREEN + "Successfully saved and reloaded all kits."); + return; + } + + if (args.length < 2) { + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&7Kit Commands Help: &f/kit ")); + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&7 • &b/kit list")); + player.sendMessage(CC.translate("&7 • &b/kit info ")); + player.sendMessage(CC.translate("&7 • &b/kit create ")); + player.sendMessage(CC.translate("&7 • &b/kit delete ")); + player.sendMessage(CC.translate("&7 • &b/kit whitelistArena ")); + player.sendMessage(" "); + player.sendMessage(CC.translate("&7 • &b/kit enable ")); + player.sendMessage(CC.translate("&7 • &b/kit disable ")); + player.sendMessage(" "); + player.sendMessage(CC.translate("&7 • &b/kit setinv ")); + player.sendMessage(CC.translate("&7 • &b/kit getinv ")); + player.sendMessage(" "); + player.sendMessage(CC.translate("&7 • &b/kit seteditinv ")); + player.sendMessage(CC.translate("&7 • &b/kit geteditinv ")); + player.sendMessage(" "); + player.sendMessage(CC.translate("&7 • &b/kit priority ")); + player.sendMessage(CC.translate("&7 • &b/kit refillinv ")); + player.sendMessage(" "); + player.sendMessage(CC.translate("&7 • &b/kit ranked ")); + player.sendMessage(CC.translate("&7 • &b/kit build ")); + player.sendMessage(CC.translate("&7 • &b/kit combo ")); + player.sendMessage(CC.translate("&7 • &b/kit sumo ")); + player.sendMessage(CC.translate("&7 • &b/kit skywars ")); + player.sendMessage(CC.translate("&7 • &b/kit bridges ")); + player.sendMessage(CC.translate("&7 • &b/kit spleef ")); + player.sendMessage(CC.translate("&7 • &b/kit boxing ")); + player.sendMessage(CC.translate("&7 • &b/kit bedwars ")); + player.sendMessage(CC.translate("&7 • &b/kit mlgrush ")); + player.sendMessage(CC.translate("&7 • &b/kit battlerush ")); + player.sendMessage(CC.translate("&7 • &b/kit stickfight ")); + player.sendMessage(CC.translate("&7 • &b/kit parkour ")); + + player.sendMessage(CC.CHAT_BAR); + return; + } + + Kit kit = plugin.getKitManager().getKit(args[1]); + + switch (args[0].toLowerCase()) { + case "create": + if (kit == null) { + plugin.getKitManager().createKit(args[1]); + sender.sendMessage(ChatColor.GREEN + "Successfully created kit " + args[1] + "."); + } else { + sender.sendMessage(ChatColor.RED + "That kit already exists!"); + } + break; + case "delete": + if (kit != null) { + plugin.getKitManager().deleteKit(args[1]); + sender.sendMessage(ChatColor.GREEN + "Successfully deleted kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "disable": + case "enable": + if (kit != null) { + kit.setEnabled(!kit.isEnabled()); + sender.sendMessage(kit.isEnabled() ? ChatColor.GREEN + "Successfully enabled kit " + args[1] + "." : + ChatColor.RED + "Successfully disabled kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "combo": + if (kit != null) { + kit.setCombo(!kit.isCombo()); + sender.sendMessage( + kit.isCombo() ? ChatColor.GREEN + "Successfully enabled combo mode for kit " + args[1] + "." + : ChatColor.RED + "Successfully disabled combo mode for kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "sumo": + if (kit != null) { + kit.setSumo(!kit.isSumo()); + sender.sendMessage( + kit.isSumo() ? ChatColor.GREEN + "Successfully enabled sumo mode for kit " + args[1] + "." + : ChatColor.RED + "Successfully disabled sumo mode for kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "build": + if (kit != null) { + kit.setBuild(!kit.isBuild()); + sender.sendMessage( + kit.isBuild() ? ChatColor.GREEN + "Successfully enabled build mode for kit " + args[1] + "." + : ChatColor.RED + "Successfully disabled build mode for kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "spleef": + if (kit != null) { + kit.setSpleef(!kit.isSpleef()); + sender.sendMessage( + kit.isSpleef() ? ChatColor.GREEN + "Successfully enabled spleef mode for kit " + args[1] + "." + : ChatColor.RED + "Successfully disabled spleef mode for kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "ranked": + if (kit != null) { + kit.setRanked(!kit.isRanked()); + sender.sendMessage( + kit.isRanked() ? ChatColor.GREEN + "Successfully enabled ranked mode for kit " + args[1] + "." + : ChatColor.RED + "Successfully disabled ranked mode for kit " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "boxing": + if (kit != null) { + kit.setBoxing(!kit.isBoxing()); + sender.sendMessage(kit.isBoxing() + ? ChatColor.GREEN + "Successfully enabled boxing mode for kit " + args[1] + "." + : ChatColor.RED + "Successfully disabled boxing mode for kit " + args[1] + "." + ); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "whitelistarena": + if (args.length < 3) { + sender.sendMessage(command.getCommand().getUsage()); + return; + } + if (kit != null) { + Arena arena = plugin.getArenaManager().getArena(args[2]); + + if (arena != null) { + kit.whitelistArena(arena.getName()); + sender.sendMessage(kit.getArenaWhiteList().contains(arena.getName()) ? + ChatColor.GREEN + "Arena " + arena.getName() + " is now whitelisted to kit " + args[1] + "." + : ChatColor.GREEN + "Arena " + arena.getName() + " is no longer whitelisted to kit " + args[1] + "."); + } else { + sender.sendMessage(NO_ARENA); + } + } else { + sender.sendMessage(NO_KIT); + } + break; + case "icon": + if (kit != null) { + if (player.getItemInHand().getType() != Material.AIR) { + ItemStack icon = ItemUtil.renameItem(player.getItemInHand().clone(), ChatColor.GREEN + kit.getName()); + + kit.setIcon(icon); + + sender.sendMessage(ChatColor.GREEN + "Successfully set icon for kit " + args[1] + "."); + } else { + player.sendMessage(ChatColor.RED + "You must be holding an item to set the kit icon!"); + } + } else { + sender.sendMessage(NO_KIT); + } + break; + case "setinv": + if (kit != null) { + if (player.getGameMode() == GameMode.CREATIVE) { + sender.sendMessage(ChatColor.RED + "You can't set item contents in creative mode!"); + } else { + player.updateInventory(); + + kit.setContents(player.getInventory().getContents()); + kit.setArmor(player.getInventory().getArmorContents()); + + sender.sendMessage(ChatColor.GREEN + "Successfully set kit contents for " + args[1] + "."); + } + } else { + sender.sendMessage(NO_KIT); + } + break; + case "getinv": + if (kit != null) { + player.getInventory().setContents(kit.getContents()); + player.getInventory().setArmorContents(kit.getArmor()); + player.updateInventory(); + sender.sendMessage(ChatColor.GREEN + "Successfully retrieved kit contents from " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "seteditinv": + if (kit != null) { + if (player.getGameMode() == GameMode.CREATIVE) { + sender.sendMessage(ChatColor.RED + "You can't set item contents in creative mode!"); + } else { + player.updateInventory(); + + kit.setKitEditContents(player.getInventory().getContents()); + + sender.sendMessage(ChatColor.GREEN + "Successfully set edit kit contents for " + args[1] + "."); + } + } else { + sender.sendMessage(NO_KIT); + } + break; + case "geteditinv": + if (kit != null) { + player.getInventory().setContents(kit.getKitEditContents()); + player.updateInventory(); + sender.sendMessage(ChatColor.GREEN + "Successfully retrieved edit kit contents from " + args[1] + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + case "refillinv": + if (kit != null) { + player.getInventory().setContents(kit.getKitEditContents()); + sender.sendMessage(CC.GREEN + "Successfully retrieved editable kit inventory from " + kit.getName() + "."); + } else { + sender.sendMessage(NO_KIT); + } + break; + default: + sender.sendMessage(command.getCommand().getUsage()); + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/command/KitsCommand.java b/Practice/src/main/java/me/devkevin/practice/kit/command/KitsCommand.java new file mode 100644 index 0000000..acb9920 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/command/KitsCommand.java @@ -0,0 +1,34 @@ +package me.devkevin.practice.kit.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.command.CommandSender; + +/** + * Copyright 17/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class KitsCommand extends PracticeCommand { + + @Command(name = "kits", permission = Rank.DEVELOPER, inGameOnly = true) + public void onCommand(CommandArgs command) { + CommandSender sender = command.getSender(); + + sender.sendMessage(PracticeLang.line); + sender.sendMessage(CC.translate("&4&lKits List &7(&7" + Practice.getInstance().getKitManager().getKits().size() + "&c in total&7)")); + sender.sendMessage(""); + for (Kit kits : Practice.getInstance().getKitManager().getKits()) { + sender.sendMessage(CC.translate(" &c&l" + kits.getName() + " &7(" + (kits.isEnabled() ? "&aEnabled" : "&cDisabled") + "&7)" + + " &7(" + (kits.isRanked() ? "&aEnabled" : "&cDisabled") + "&7")); + } + + sender.sendMessage(PracticeLang.line); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/listener/KitEditorError32Listener.java b/Practice/src/main/java/me/devkevin/practice/kit/listener/KitEditorError32Listener.java new file mode 100644 index 0000000..deafb14 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/listener/KitEditorError32Listener.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.kit.listener; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +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.inventory.InventoryClickEvent; +import org.bukkit.inventory.CraftingInventory; + +/** + * Copyright 18/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class KitEditorError32Listener implements Listener { + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + public void onInventoryClickEvent(InventoryClickEvent event) { + if (event.getWhoClicked() instanceof Player) { + Player player = (Player) event.getWhoClicked(); + + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.isEditing()) { + if (event.getClickedInventory() != null && event.getClickedInventory() instanceof CraftingInventory) { + if (player.getGameMode() != GameMode.CREATIVE) { + event.setCancelled(true); + } + } + } else if (profile.isFighting()) { + if (event.getClickedInventory() != null && event.getClickedInventory() instanceof CraftingInventory) { + if (player.getGameMode() != GameMode.CREATIVE) { + event.setCancelled(true); + } + } + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/manager/EditorManager.java b/Practice/src/main/java/me/devkevin/practice/kit/manager/EditorManager.java new file mode 100644 index 0000000..bfde318 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/manager/EditorManager.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.kit.manager; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.kit.PlayerKit; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Copyright 17/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EditorManager { + + private final Practice plugin = Practice.getInstance(); + private final Map editing = new HashMap<>(); + private final Map renaming = new HashMap<>(); + + public void addEditor(Player player, Kit kit) { + this.editing.put(player.getUniqueId(), kit.getName()); + this.plugin.getKitEditorMenu().addEditingKitInventory(player, kit); + + PlayerUtil.reset(player); + player.teleport(this.plugin.getCustomLocationManager().getEditor().toBukkitLocation()); + + player.getInventory().setArmorContents(kit.getArmor()); + player.getInventory().setContents(kit.getContents()); + player.sendMessage(CC.YELLOW + "You are editing kit " + CC.GOLD + kit.getName() + CC.YELLOW + ". Armor will be applied automatically in the kit."); + } + + public void removeEditor(UUID editor) { + this.renaming.remove(editor); + this.editing.remove(editor); + this.plugin.getKitEditorMenu().removeEditingKitInventory(editor); + } + + public String getEditingKit(UUID editor) { + return this.editing.get(editor); + } + + public void addRenamingKit(UUID uuid, PlayerKit playerKit) { + this.renaming.put(uuid, playerKit); + } + + public void removeRenamingKit(UUID uuid) { + this.renaming.remove(uuid); + } + + public PlayerKit getRenamingKit(UUID uuid) { + return this.renaming.get(uuid); + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/manager/KitManager.java b/Practice/src/main/java/me/devkevin/practice/kit/manager/KitManager.java new file mode 100644 index 0000000..30d7729 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/manager/KitManager.java @@ -0,0 +1,119 @@ +package me.devkevin.practice.kit.manager; + +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.file.Config; +import me.devkevin.practice.kit.Kit; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.inventory.ItemStack; + +import java.util.*; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class KitManager { + + private final Practice plugin = Practice.getInstance(); + private final Map kits = new HashMap<>(); + private final List rankedKits = new ArrayList<>(); + private final List allKits = new ArrayList<>(); + private final Config config = new Config("ladders", this.plugin); + + public KitManager() { + this.loadKits(); + this.kits.entrySet().stream() + .filter(kit -> kit.getValue().isEnabled()) + .filter(kit -> kit.getValue().isRanked()) + .forEach(kit -> this.rankedKits.add(kit.getValue())); + this.kits.forEach((key, value) -> this.allKits.add(value)); + } + + @SuppressWarnings("unchecked") + private void loadKits() { + FileConfiguration fileConfig = this.config.getConfig(); + ConfigurationSection kitSection = fileConfig.getConfigurationSection("ladders"); + + if (kitSection != null) { + kitSection.getKeys(false).forEach((name) -> { + + ItemStack[] contents = ((List) kitSection.get(name + ".contents")).toArray(new ItemStack[0]); + ItemStack[] armor = ((List) kitSection.get(name + ".armor")).toArray(new ItemStack[0]); + ItemStack[] kitEditContents = ((List) kitSection.get(name + ".kitEditContents")).toArray(new ItemStack[0]); + + List arenaWhiteList = kitSection.getStringList(name + ".arenaWhitelist"); + + ItemStack icon = (ItemStack) kitSection.get(name + ".icon"); + + boolean enabled = kitSection.getBoolean(name + ".enabled"); + boolean ranked = kitSection.getBoolean(name + ".ranked"); + boolean sumo = kitSection.getBoolean(name + ".sumo"); + boolean build = kitSection.getBoolean(name + ".build"); + boolean hcf = kitSection.getBoolean(name + ".hcf"); + boolean parkour = kitSection.getBoolean(name + ".parkour"); + boolean spleef = kitSection.getBoolean(name + ".spleef"); + boolean bedWars = kitSection.getBoolean(name + ".bedWars"); + boolean combo = kitSection.getBoolean(name + ".combo"); + boolean boxing = kitSection.getBoolean(name + ".boxing"); + + Kit kit = new Kit(name, contents, armor, kitEditContents, icon, arenaWhiteList, enabled, ranked, sumo, build, hcf, parkour, spleef, bedWars, combo, boxing); + this.kits.put(name, kit); + }); + } + } + + public void reloadKits() { + this.saveKits(); + this.kits.clear(); + this.loadKits(); + } + + public void saveKits() { + FileConfiguration fileConfig = this.config.getConfig(); + + fileConfig.set("ladders", null); + + this.kits.forEach((kitName, kit) -> { + if (kit.getIcon() != null && kit.getContents() != null && kit.getArmor() != null) { + fileConfig.set("ladders." + kitName + ".contents", kit.getContents()); + fileConfig.set("ladders." + kitName + ".armor", kit.getArmor()); + fileConfig.set("ladders." + kitName + ".kitEditContents", kit.getKitEditContents()); + fileConfig.set("ladders." + kitName + ".icon", kit.getIcon()); + fileConfig.set("ladders." + kitName + ".arenaWhitelist", kit.getArenaWhiteList()); + fileConfig.set("ladders." + kitName + ".enabled", kit.isEnabled()); + fileConfig.set("ladders." + kitName + ".ranked", kit.isRanked()); + fileConfig.set("ladders." + kitName + ".sumo", kit.isSumo()); + fileConfig.set("ladders." + kitName + ".build", kit.isBuild()); + fileConfig.set("ladders." + kitName + ".hcf", kit.isHcf()); + fileConfig.set("ladders." + kitName + ".parkour", kit.isParkour()); + fileConfig.set("ladders." + kitName + ".spleef", kit.isSpleef()); + fileConfig.set("ladders." + kitName + ".bedWars", kit.isBedWars()); + fileConfig.set("ladders." + kitName + ".combo", kit.isCombo()); + fileConfig.set("ladders." + kitName + ".boxing", kit.isBoxing()); + } + }); + + + this.config.save(); + } + + public void deleteKit(String name) { + this.kits.remove(name); + } + + public void createKit(String name) { + this.kits.put(name, new Kit(name)); + } + + public Collection getKits() { + return this.kits.values(); + } + + public Kit getKit(String name) { + return this.kits.get(name); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/menu/KitEditorMenu.java b/Practice/src/main/java/me/devkevin/practice/kit/menu/KitEditorMenu.java new file mode 100644 index 0000000..9644d1d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/menu/KitEditorMenu.java @@ -0,0 +1,282 @@ +package me.devkevin.practice.kit.menu; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.kit.PlayerKit; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.*; + +/** + * Copyright 16/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class KitEditorMenu { + + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI kitEditor = new InventoryUI(CC.GRAY + "Kit Editor Menu", true, 4); + private final Map editorInventories = new HashMap<>(); + + public KitEditorMenu() { + this.KitEditorMenu(); + } + + public void KitEditorMenu() { + Collection kits = this.plugin.getKitManager().getKits(); + + for (Kit kit : kits) { + if (kit.isEnabled()) { + this.kitEditor.setItem(kit.getEditorSlots(), new InventoryUI.AbstractClickableItem(new ItemBuilder(kit.getIcon()).name(CC.GOLD + kit.getName()).build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + + if (kit.getName().equals("Sumo") || kit.getName().equals("Boxing")) { + player.closeInventory(); + player.sendMessage(CC.RED + "This kit is not editable."); + } else { + KitEditorMenu.this.plugin.getEditorManager().addEditor(player, kit); + KitEditorMenu.this.plugin.getProfileManager().getProfileData(player.getUniqueId()) + .setState(ProfileState.EDITING); + } + } + }); + } + } + } + + public void addEditingKitInventory(Player player, Kit kit) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + Map kitMap = profile.getPlayerKits(kit.getName()); + + InventoryUI inventory = new InventoryUI("Managing Kit Layout", true, 4); + + int maxKits = profile.getMaxCustomKits(); + + for (int i = 1; i <= 4; i++) { + + while (inventory.getItem(i) != null) { + ++i; + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile.hasDonor()) { + ItemStack save = ItemUtil + .createItem(Material.CHEST, CC.YELLOW + "Save Kit " + CC.GREEN + kit.getName() + " #" + i); + ItemStack load = ItemUtil + .createItem(Material.BOOK, CC.YELLOW + "Load Kit " + CC.GREEN + kit.getName() + " #" + i); + ItemStack rename = ItemUtil.createItem(Material.NAME_TAG, + CC.YELLOW + "Rename Kit " + CC.GREEN + kit.getName() + " #" + i); + ItemStack delete = ItemUtil + .createItem(Material.FLINT, CC.YELLOW + "Delete Kit " + CC.GREEN + kit.getName() + " #" + i); + + inventory.setItem(i, new InventoryUI.AbstractClickableItem(save) { + @Override + public void onClick(InventoryClickEvent event) { + int kitIndex = event.getSlot(); + KitEditorMenu.this.handleSavingKit(player, profile, kit, kitMap, kitIndex); + inventory.setItem(kitIndex + 1, 2, new InventoryUI.AbstractClickableItem(load) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleLoadKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 3, new InventoryUI.AbstractClickableItem(rename) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleRenamingKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 4, new InventoryUI.AbstractClickableItem(delete) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleDeleteKit(player, kitIndex, kitMap, inventory); + } + }); + } + }); + + final int kitIndex = i; + + if (kitMap != null && kitMap.containsKey(kitIndex)) { + inventory.setItem(kitIndex + 1, 2, new InventoryUI.AbstractClickableItem(load) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleLoadKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 3, new InventoryUI.AbstractClickableItem(rename) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleRenamingKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 4, new InventoryUI.AbstractClickableItem(delete) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleDeleteKit(player, kitIndex, kitMap, inventory); + } + }); + } + } else { + + ItemStack save = ItemUtil + .createItem(Material.CHEST, CC.YELLOW + "Save Kit " + CC.GREEN + kit.getName() + " #" + i); + ItemStack load = ItemUtil + .createItem(Material.BOOK, CC.YELLOW + "Load Kit " + CC.GREEN + kit.getName() + " #" + i); + ItemStack rename = ItemUtil.createItem(Material.NAME_TAG, + CC.YELLOW + "Rename Kit " + CC.GREEN + kit.getName() + " #" + i); + ItemStack delete = ItemUtil + .createItem(Material.FLINT, CC.YELLOW + "Delete Kit " + CC.GREEN + kit.getName() + " #" + i); + + + if (i == 2 || i == 3 || i == 4) { + ItemBuilder builder = new ItemBuilder(Material.REDSTONE_BLOCK); + builder.name(CC.RED + "Unavailable Kit Slot"); + builder.lore(Arrays.asList(CC.GRAY + "Your rank does not allow you", CC.GRAY + "to create more than " + maxKits + " kit" + (maxKits > 1 ? "s" : "") + ".", "", CC.GRAY + "Purchase a higher rank at:", CC.PINK + "shop." + LandCore.getInstance().getNetworkName() + ".")); + inventory.setItem(i, new InventoryUI.EmptyClickableItem(builder.build())); + continue; + } + + inventory.setItem(i, new InventoryUI.AbstractClickableItem(save) { + @Override + public void onClick(InventoryClickEvent event) { + int kitIndex = event.getSlot(); + KitEditorMenu.this.handleSavingKit(player, profile, kit, kitMap, kitIndex); + inventory.setItem(kitIndex + 1, 2, new InventoryUI.AbstractClickableItem(load) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleLoadKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 3, new InventoryUI.AbstractClickableItem(rename) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleRenamingKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 4, new InventoryUI.AbstractClickableItem(delete) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleDeleteKit(player, kitIndex, kitMap, inventory); + } + }); + } + }); + + final int kitIndex = i; + + if (kitMap != null && kitMap.containsKey(kitIndex)) { + inventory.setItem(kitIndex + 1, 2, new InventoryUI.AbstractClickableItem(load) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleLoadKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 3, new InventoryUI.AbstractClickableItem(rename) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleRenamingKit(player, kitIndex, kitMap); + } + }); + inventory.setItem(kitIndex + 1, 4, new InventoryUI.AbstractClickableItem(delete) { + @Override + public void onClick(InventoryClickEvent event) { + KitEditorMenu.this.handleDeleteKit(player, kitIndex, kitMap, inventory); + } + }); + } + } + } + this.editorInventories.put(player.getUniqueId(), inventory); + } + + public void removeEditingKitInventory(UUID uuid) { + InventoryUI inventoryUI = this.editorInventories.get(uuid); + if (inventoryUI != null) { + this.editorInventories.remove(uuid); + } + } + + public InventoryUI getEditingKitInventory(UUID uuid) { + return this.editorInventories.get(uuid); + } + + private void handleSavingKit(Player player, Profile profile, Kit kit, Map kitMap, int kitIndex) { + if (kitMap != null && kitMap.containsKey(kitIndex)) { + kitMap.get(kitIndex).setContents(player.getInventory().getContents().clone()); + player.sendMessage( + CC.YELLOW + "Successfully saved kit " + CC.PINK + kitIndex + CC.YELLOW + "."); + return; + } + + PlayerKit playerKit = new PlayerKit(kit.getName(), kitIndex, player.getInventory().getContents().clone(), + kit.getName() + " Kit " + kitIndex); + profile.addPlayerKit(kitIndex, playerKit); + + player.sendMessage(CC.YELLOW + "Successfully saved kit " + CC.PINK + kitIndex + CC.YELLOW + "."); + } + + private void handleLoadKit(Player player, int kitIndex, Map kitMap) { + if (kitMap != null && kitMap.containsKey(kitIndex)) { + ItemStack[] contents = kitMap.get(kitIndex).getContents(); + for (ItemStack itemStack : contents) { + if (itemStack != null) { + if (itemStack.getAmount() <= 0) { + itemStack.setAmount(1); + } + } + } + player.getInventory().setContents(contents); + player.updateInventory(); + } + } + + private void handleRenamingKit(Player player, int kitIndex, Map kitMap) { + if (kitMap != null && kitMap.containsKey(kitIndex)) { + this.plugin.getEditorManager().addRenamingKit(player.getUniqueId(), kitMap.get(kitIndex)); + + player.closeInventory(); + player.sendMessage(CC.YELLOW + "Enter a name for this kit (chat colors are also applicable)."); + } + } + + private void handleDeleteKit(Player player, int kitIndex, Map kitMap, InventoryUI inventory) { + if (kitMap != null && kitMap.containsKey(kitIndex)) { + this.plugin.getEditorManager().removeRenamingKit(player.getUniqueId()); + + kitMap.remove(kitIndex); + + player.sendMessage( + CC.YELLOW + "Successfully removed kit " + CC.PINK + kitIndex + CC.YELLOW + "."); + + if (LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).hasDonor()) { + inventory.setItem(kitIndex + 1, 2, null); + inventory.setItem(kitIndex + 1, 3, null); + inventory.setItem(kitIndex + 1, 4, null); + /*inventory.setItem(kitIndex + 1, 5, null); + inventory.setItem(kitIndex + 1, 6, null); + inventory.setItem(kitIndex + 1, 7, null);*/ + } else { + inventory.setItem(kitIndex + 1, 2, null); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/kit/npc/EditorNPC.java b/Practice/src/main/java/me/devkevin/practice/kit/npc/EditorNPC.java new file mode 100644 index 0000000..ecc9fe9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/kit/npc/EditorNPC.java @@ -0,0 +1,139 @@ +package me.devkevin.practice.kit.npc; + +import lombok.Setter; +import me.devkevin.npc.events.NPCInteractEvent; +import me.devkevin.npc.npcs.NPC; +import me.devkevin.practice.util.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemStack; + +/** + * Copyright 11/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EditorNPC implements Listener { + + // helmet + private final ItemStack helmetDiamond = new ItemBuilder(Material.DIAMOND_HELMET).build(); + private final ItemStack helmetIron = new ItemBuilder(Material.IRON_HELMET).build(); + private final ItemStack helmetGold = new ItemBuilder(Material.GOLD_HELMET).build(); + private final ItemStack helmetChainMail = new ItemBuilder(Material.CHAINMAIL_HELMET).build(); + private final ItemStack helmetLeather = new ItemBuilder(Material.LEATHER_HELMET).build(); + + // chest + private final ItemStack chestDiamond = new ItemBuilder(Material.DIAMOND_CHESTPLATE).build(); + private final ItemStack chestIron = new ItemBuilder(Material.IRON_CHESTPLATE).build(); + private final ItemStack chestGold = new ItemBuilder(Material.GOLD_CHESTPLATE).build(); + private final ItemStack chestChainMail = new ItemBuilder(Material.CHAINMAIL_CHESTPLATE).build(); + private final ItemStack chestLeather = new ItemBuilder(Material.LEATHER_CHESTPLATE).build(); + + // legs + private final ItemStack legsDiamond = new ItemBuilder(Material.DIAMOND_LEGGINGS).build(); + private final ItemStack legsIron = new ItemBuilder(Material.IRON_LEGGINGS).build(); + private final ItemStack legsGold = new ItemBuilder(Material.GOLD_LEGGINGS).build(); + private final ItemStack legsChainMail = new ItemBuilder(Material.CHAINMAIL_LEGGINGS).build(); + private final ItemStack legsLeather = new ItemBuilder(Material.LEATHER_LEGGINGS).build(); + + // boots + private final ItemStack bootsDiamond = new ItemBuilder(Material.DIAMOND_BOOTS).build(); + private final ItemStack bootsIron = new ItemBuilder(Material.IRON_BOOTS).build(); + private final ItemStack bootsGold = new ItemBuilder(Material.GOLD_BOOTS).build(); + private final ItemStack bootsChainMail = new ItemBuilder(Material.CHAINMAIL_BOOTS).build(); + private final ItemStack bootsLeather = new ItemBuilder(Material.LEATHER_BOOTS).build(); + + // for npc hand + private final ItemStack diamondSword = new ItemBuilder(Material.DIAMOND_SWORD).build(); + private final ItemStack ironSword = new ItemBuilder(Material.IRON_SWORD).build(); + private final ItemStack goldSword = new ItemBuilder(Material.GOLD_SWORD).build(); + private final ItemStack stoneSword = new ItemBuilder(Material.STONE_SWORD).build(); + private final ItemStack woodSword = new ItemBuilder(Material.WOOD_SWORD).build(); + + + @Setter private int index = 0; + + @EventHandler + public void onPlayerInteractWithNPC(NPCInteractEvent event) { + Player player = event.getPlayer(); + NPC npc = event.getNpc(); + + switch (npc.getName()) { + case "Profile": + break; + case "Editor": + if (event.getAction() == NPCInteractEvent.Action.RIGHT_CLICK) { + if (index == 1) { + //-------------------------------------------------------------\\ + npc.destroy(player); + npc.setHelmet(helmetDiamond); + npc.setChest(chestDiamond); + npc.setLegs(legsDiamond); + npc.setBoots(bootsDiamond); + npc.setHand(diamondSword); + npc.spawn(player); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1F, 1F); + //-------------------------------------------------------------\\ + } + if (index == 2) { + //-------------------------------------------------------------\\ + npc.destroy(player); + npc.setHelmet(helmetIron); + npc.setChest(chestIron); + npc.setLegs(legsIron); + npc.setBoots(bootsIron); + npc.setHand(ironSword); + npc.spawn(player); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1F, 1F); + //-------------------------------------------------------------\\ + } + if (index == 3) { + //-------------------------------------------------------------\\ + npc.destroy(player); + npc.setHelmet(helmetGold); + npc.setChest(chestGold); + npc.setLegs(legsGold); + npc.setBoots(bootsGold); + npc.setHand(goldSword); + npc.spawn(player); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1F, 1F); + //-------------------------------------------------------------\\ + } + if (index == 4) { + //-------------------------------------------------------------\\ + npc.destroy(player); + npc.setHelmet(helmetChainMail); + npc.setChest(chestChainMail); + npc.setLegs(legsChainMail); + npc.setBoots(bootsChainMail); + npc.setHand(stoneSword); + npc.spawn(player); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1F, 1F); + //-------------------------------------------------------------\\ + } + if (index == 5) { + //-------------------------------------------------------------\\ + npc.destroy(player); + npc.setHelmet(helmetLeather); + npc.setChest(chestLeather); + npc.setLegs(legsLeather); + npc.setBoots(bootsLeather); + npc.setHand(woodSword); + npc.spawn(player); + player.playSound(player.getLocation(), Sound.NOTE_PLING, 1F, 1F); + //-------------------------------------------------------------\\ + } + } + // when the index is equals to 6 return to 1 number by number + if (index == 5) { + setIndex(0); + } else { + index++; + } + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/Leaderboard.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/Leaderboard.java new file mode 100644 index 0000000..721a34d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/Leaderboard.java @@ -0,0 +1,22 @@ +package me.devkevin.practice.leaderboard; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.kit.Kit; + +import java.util.UUID; + +/** + * Copyright 13/05/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter @Setter @AllArgsConstructor +public class Leaderboard { + private int elo; + private int winStreak; + private UUID uuid; + private String name; + private Kit kit; +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/LeaderboardManager.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/LeaderboardManager.java new file mode 100644 index 0000000..23f900e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/LeaderboardManager.java @@ -0,0 +1,105 @@ +package me.devkevin.practice.leaderboard; + +import com.google.common.collect.Lists; +import com.mongodb.client.MongoCursor; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.profile.Profile; +import org.bson.Document; + +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Copyright 13/05/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class LeaderboardManager { + + private final Practice plugin; + @Getter private final Set leaderboards = ConcurrentHashMap.newKeySet(); + + public LeaderboardManager(Practice plugin) { + this.plugin = plugin; + updateLeaderboards(); + } + + public void createLeaderboards() { + for (Kit kit : this.plugin.getKitManager().getKits()) { + if (kit.getName().equalsIgnoreCase("HCF")) continue; + + try (MongoCursor iterator = this.plugin.getProfileManager().getPlayersSortByLadderElo(kit)) { + while (iterator.hasNext()) { + try { + Document document = iterator.next(); + UUID uuid = UUID.fromString(document.getString("uuid")); + String name = document.getString("username"); + + if (!document.containsKey("stats")) { + continue; + } + + Document statics = (Document)document.get("stats"); + int elo = Profile.DEFAULT_ELO; + int winStreak = 0; + + if (statics.containsKey(kit.getName())) { + Document ladder = (Document)statics.get(kit.getName()); + if (kit.isRanked()) { + elo = ladder.getInteger("elo"); + } + if (ladder.containsKey("currentStreak")) { + winStreak = ladder.getInteger("currentStreak"); + } + } + + Leaderboard leaderboard = new Leaderboard(elo, winStreak, uuid, name, kit); + leaderboards.add(leaderboard); + } + catch (Exception e) { + e.printStackTrace(); + } + } + } + } + } + + public void updateLeaderboards() { + this.leaderboards.clear(); + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, this::createLeaderboards); + } + + public List getKitLeaderboards(Kit kit) { + List leaderboardsKits = Lists.newArrayList(); + this.leaderboards.stream().filter(leaderboard -> leaderboard.getKit() == kit).forEach(leaderboardsKits::add); + + return leaderboardsKits; + } + public List getSortedKitLeaderboards(Kit kit, String type) { + List leaderboardsKit = Lists.newArrayList(); + + try { + for (Leaderboard leaderboard : this.leaderboards) { + if (leaderboard.getKit() == kit) { + leaderboardsKit.add(leaderboard); + } + } + + switch (type.toLowerCase()) { + case "elo": + leaderboardsKit.sort((leaderboard1, leaderboard2) -> leaderboard2.getElo() - leaderboard1.getElo()); + break; + case "winstreak": + leaderboardsKit.sort((leaderboard1, leaderboard2) -> leaderboard2.getWinStreak() - leaderboard1.getWinStreak()); + break; + } + } catch (Exception e) { + e.printStackTrace(); + } + return leaderboardsKit; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/hologram/HologramManager.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/hologram/HologramManager.java new file mode 100644 index 0000000..486ecf2 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/hologram/HologramManager.java @@ -0,0 +1,64 @@ +package me.devkevin.practice.leaderboard.hologram; + +import club.inverted.chatcolor.CC; +import com.gmail.filoghost.holographicdisplays.api.Hologram; +import com.gmail.filoghost.holographicdisplays.api.HologramsAPI; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.Leaderboard; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 13/03/2023 @ 23:04 + * HologramManager / me.devkevin.practice.leaderboard.hologram / Practice + */ +public class HologramManager { + private final Practice plugin; + private final List npcHolograms; + + public HologramManager(Practice plugin) { + this.plugin = plugin; + + npcHolograms = new ArrayList<>(); + npcHolograms.add(HologramsAPI.createHologram(plugin, plugin.getCustomLocationManager().getNpc1().toBukkitLocation().add(0, 3.5, 0))); + npcHolograms.add(HologramsAPI.createHologram(plugin, plugin.getCustomLocationManager().getNpc2().toBukkitLocation().add(0, 3.5, 0))); + npcHolograms.add(HologramsAPI.createHologram(plugin, plugin.getCustomLocationManager().getNpc3().toBukkitLocation().add(0, 3.5, 0))); + } + + public void updateHolograms(List leaderboards, Kit kit) { + plugin.getServer().getScheduler().runTask(plugin, () -> { + npcHolograms.forEach(Hologram::clearLines); + + int npcHologramCount = npcHolograms.size(); + int leaderboardCount = Math.min(npcHologramCount, leaderboards.size()); + for (int i = 0; i < leaderboardCount; i++) { + Leaderboard leaderboard = leaderboards.get(i); + + Set onlinePlayers = plugin.getServer().getOnlinePlayers().stream().map(Player::getUniqueId).collect(Collectors.toSet()); + UUID uuid = leaderboard.getUuid(); + OfflinePlayer offlinePlayer = plugin.getServer().getOfflinePlayer(uuid); + String playerName = onlinePlayers.contains(uuid) ? plugin.getServer().getPlayer(uuid).getName() : offlinePlayer.getName(); + + Hologram npcHologram = npcHolograms.get(i); + updateHologram(npcHologram, playerName, leaderboard.getElo(), kit, i); + } + }); + } + + private void updateHologram(Hologram npcHologram, String playerName, int elo, Kit kit, int position) { + npcHologram.appendTextLine(""); + npcHologram.appendTextLine(""); + npcHologram.appendTextLine(CC.AQUA + CC.BOLD + "Top #" + (position + 1)); + npcHologram.appendTextLine(CC.GOLD + CC.BOLD + kit.getName()); + npcHologram.appendTextLine(CC.translate("")); + npcHologram.appendTextLine(CC.YELLOW + playerName + CC.GRAY + " (" + elo + ")"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/LeaderboardsMenu.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/LeaderboardsMenu.java new file mode 100644 index 0000000..3fe7eae --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/LeaderboardsMenu.java @@ -0,0 +1,54 @@ +package me.devkevin.practice.leaderboard.menu; + +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.menu.button.*; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 14:46 + * LeaderboardsMenu / me.devkevin.practice.leaderboard.menu / Practice + */ +public class LeaderboardsMenu extends Menu { + @Override + public String getTitle(Player player) { + return "Leaderboards Menu"; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(4, new LeaderboardGlobalButton(Material.SUGAR, "globalElo", "GLOBAL")); + + buttons.put(57, new LeaderboardButton()); + buttons.put(58, new PlayerStatsButton()); + buttons.put(59, new WinstreakButton()); + + AtomicInteger value = new AtomicInteger(19); + plugin.getKitManager().getKits().stream().filter(Kit::isRanked).sorted(Comparator.comparingInt(Kit::getPriority)).forEach(kit -> { + buttons.put(value.getAndIncrement(), new KitStatsButton(kit)); + if (value.get() == 26) { + value.set(28); + } + if (value.get() == 35) { + value.set(37); + } + }); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 7; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/WinstreaksMenu.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/WinstreaksMenu.java new file mode 100644 index 0000000..62ed9bf --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/WinstreaksMenu.java @@ -0,0 +1,54 @@ +package me.devkevin.practice.leaderboard.menu; + +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.menu.button.*; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:54 + * WinstreaksMenu / me.devkevin.practice.leaderboard.menu / Practice + */ +public class WinstreaksMenu extends Menu { + @Override + public String getTitle(Player player) { + return "Winstreaks Menu"; + } + + @Override + public Map getButtons(Player player) { + Map buttons = new HashMap<>(); + + buttons.put(4, new WinstreakGlobalButton(Material.SUGAR, "globalWinStreak")); + + buttons.put(57, new LeaderboardButton()); + buttons.put(58, new PlayerStatsButton()); + buttons.put(59, new WinstreakButton()); + + AtomicInteger value = new AtomicInteger(19); + plugin.getKitManager().getKits().stream().sorted(Comparator.comparingInt(Kit::getPriority)).forEach(kit -> { + buttons.put(value.getAndIncrement(), new WinstreakKitButton(kit)); + if (value.get() == 26) { + value.set(28); + } + if (value.get() == 35) { + value.set(37); + } + }); + + return buttons; + } + + @Override + public int getSize() { + return 9 * 7; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/KitStatsButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/KitStatsButton.java new file mode 100644 index 0000000..58273db --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/KitStatsButton.java @@ -0,0 +1,43 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import lombok.AllArgsConstructor; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.Leaderboard; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:06 + * KitStatsButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +@AllArgsConstructor +public class KitStatsButton extends Button { + private final Kit kit; + + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + AtomicInteger lineNum = new AtomicInteger(); + + lore.add(CC.MENU_BAR); + + List leaderboards = new ArrayList<>(plugin.getLeaderboardManager().getSortedKitLeaderboards(kit, "elo")); + for (Leaderboard leaderboard : leaderboards) { + lineNum.getAndIncrement(); + + lore.add(CC.YELLOW + "#" + lineNum + " " + CC.GOLD + leaderboard.getName() + CC.GRAY + " (" + leaderboard.getElo() + ")"); + } + + lore.add(CC.MENU_BAR); + + return new ItemBuilder(kit.getIcon().getType()).name(CC.GOLD + kit.getName() + CC.GRAY + " (Top 10)").lore(lore).durability(kit.getIcon().getDurability()).hideFlags().build(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/LeaderboardButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/LeaderboardButton.java new file mode 100644 index 0000000..4863f3c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/LeaderboardButton.java @@ -0,0 +1,43 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import me.devkevin.practice.leaderboard.menu.LeaderboardsMenu; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:12 + * LeaderboardButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +public class LeaderboardButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + List lore = Lists.newArrayList(); + + lore.add(CC.MENU_BAR); + lore.add(CC.GRAY + "Click here to open the"); + lore.add(CC.GRAY + "ELO leaderboards!"); + lore.add(CC.MENU_BAR); + + return new ItemBuilder(Material.CARPET) + .name(CC.GOLD + "ELO Leaderboards") + .lore(lore) + .durability(11) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + new LeaderboardsMenu().openMenu(player); + playSuccess(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/LeaderboardGlobalButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/LeaderboardGlobalButton.java new file mode 100644 index 0000000..8f9ae6c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/LeaderboardGlobalButton.java @@ -0,0 +1,60 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import com.mongodb.client.MongoCursor; +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bson.Document; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:19 + * LeaderboardGlobalButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +@RequiredArgsConstructor +public class LeaderboardGlobalButton extends Button { + private final Material material; + private final String document; + private final String type; + + @Override + public ItemStack getButtonItem(Player player) { + List lore = Lists.newArrayList(); + AtomicInteger lineNum = new AtomicInteger(); + + lore.add(CC.MENU_BAR); + + try (MongoCursor iterator = plugin.getProfileManager().getPlayersSortedByDocumentElo(this.document)) { + while (iterator.hasNext()) { + lineNum.getAndIncrement(); + try { + Document document = iterator.next(); + if (document.getString("uuid") == null) { + continue; + } + + UUID uuid = UUID.fromString(document.getString("uuid")); + Document stat = (Document) document.get("global"); + int statElo = stat.getInteger(this.document); + + lore.add(CC.YELLOW + "#" + lineNum + " " + CC.GOLD + (Bukkit.getOfflinePlayer(uuid).getName() != null ? Bukkit.getOfflinePlayer(uuid).getName() : "???") + CC.GRAY + " (" + statElo + ")"); + } catch (Exception ignored) { + } + } + } + + lore.add(CC.MENU_BAR); + + return new ItemBuilder(material).name(CC.GOLD + "Global ELO " + CC.GRAY + "(Top 10)").lore(lore).durability(0).build(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/PlayerStatsButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/PlayerStatsButton.java new file mode 100644 index 0000000..6ed974d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/PlayerStatsButton.java @@ -0,0 +1,44 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 14:53 + * PlayerStatsButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +@AllArgsConstructor +public class PlayerStatsButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + List lore = Lists.newArrayList(); + + lore.add(CC.MENU_BAR); + lore.add(CC.GRAY + "Click here to open your"); + lore.add(CC.GRAY + "personal stats profile!"); + lore.add(CC.MENU_BAR); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + return new ItemBuilder(Material.SKULL_ITEM).name(coreProfile.getGrant().getRank().getColor() + player.getName()).owner(player.getName()).lore(lore).durability(3).build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.openInventory(plugin.getStatsMenu().getStatsMenu(player).getCurrentPage()); + playNeutral(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakButton.java new file mode 100644 index 0000000..e6fe3f1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakButton.java @@ -0,0 +1,43 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import me.devkevin.practice.leaderboard.menu.WinstreaksMenu; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:52 + * WinstreakButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +public class WinstreakButton extends Button { + + @Override + public ItemStack getButtonItem(Player player) { + List lore = Lists.newArrayList(); + + lore.add(CC.MENU_BAR); + lore.add(CC.GRAY + "Click here to open the"); + lore.add(CC.GRAY + "winstreak leaderboards!"); + lore.add(CC.MENU_BAR); + + return new ItemBuilder(Material.CARPET) + .name(CC.GOLD + "Winstreak Leaderboards") + .lore(lore) + .durability(14) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + new WinstreaksMenu().openMenu(player); + playNeutral(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakGlobalButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakGlobalButton.java new file mode 100644 index 0000000..990634e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakGlobalButton.java @@ -0,0 +1,60 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import com.mongodb.client.MongoCursor; +import lombok.AllArgsConstructor; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bson.Document; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:56 + * WinstreakGlobalButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +@AllArgsConstructor +public class WinstreakGlobalButton extends Button { + + private final Material material; + private final String document; + + @Override + public ItemStack getButtonItem(Player player) { + List lore = Lists.newArrayList(); + AtomicInteger lineNum = new AtomicInteger(); + + lore.add(CC.MENU_BAR); + + try (MongoCursor iterator = plugin.getProfileManager().getPlayersSortedByDocumentElo(this.document)) { + while (iterator.hasNext()) { + lineNum.getAndIncrement(); + try { + Document document = iterator.next(); + if (document.getString("uuid") == null) { + continue; + } + + UUID uuid = UUID.fromString(document.getString("uuid")); + Document winstreak = (Document) document.get("global"); + int winstreakInt = winstreak.getInteger(this.document); + + lore.add(CC.YELLOW + "#" + lineNum + " " + CC.GOLD + (Bukkit.getOfflinePlayer(uuid).getName() != null ? Bukkit.getOfflinePlayer(uuid).getName() : "???") + CC.GRAY + " (" + winstreakInt + ")"); + } catch (Exception ignored) { + } + } + } + + lore.add(CC.MENU_BAR); + + return new ItemBuilder(material).name(CC.GOLD + "Global Winstreak " + CC.GRAY + "(Top 10)").lore(lore).durability(0).build(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakKitButton.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakKitButton.java new file mode 100644 index 0000000..5c6578a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/menu/button/WinstreakKitButton.java @@ -0,0 +1,45 @@ +package me.devkevin.practice.leaderboard.menu.button; + +import club.inverted.chatcolor.CC; +import lombok.AllArgsConstructor; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.Leaderboard; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 10/03/2023 @ 15:56 + * WinstreakKitButton / me.devkevin.practice.leaderboard.menu.button / Practice + */ +@AllArgsConstructor +public class WinstreakKitButton extends Button { + + private Kit kit; + + @Override + public ItemStack getButtonItem(Player player) { + + List lore = new ArrayList<>(); + AtomicInteger lineNum = new AtomicInteger(); + + lore.add(CC.MENU_BAR); + + List winStreaks = new ArrayList<>(plugin.getLeaderboardManager().getSortedKitLeaderboards(kit, "winstreak")); + for (Leaderboard winStreak : winStreaks) { + lineNum.getAndIncrement(); + + lore.add(CC.YELLOW + "#" + lineNum + " " + CC.GOLD + winStreak.getName() + CC.GRAY + " (" + winStreak.getWinStreak() + ")"); + } + + lore.add(CC.MENU_BAR); + + return new ItemBuilder(kit.getIcon().getType()).name(CC.translate(CC.GOLD + kit.getName() + CC.GRAY + " (Top 10)")).lore(lore).durability(kit.getIcon().getDurability()).hideFlags().build(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/leaderboard/npc/NPCRunnable.java b/Practice/src/main/java/me/devkevin/practice/leaderboard/npc/NPCRunnable.java new file mode 100644 index 0000000..a535f14 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/leaderboard/npc/NPCRunnable.java @@ -0,0 +1,97 @@ +package me.devkevin.practice.leaderboard.npc; + +import me.devkevin.npc.npcs.NPC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.Leaderboard; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.util.NPCUtil; +import me.devkevin.practice.util.TaskUtil; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 07/03/2023 @ 21:18 + * NPCRunnable / me.devkevin.practice.leaderboard.npc / Practice + */ +public class NPCRunnable implements Runnable { + private final Map npcLocations = new HashMap<>(); + private final Practice plugin; + private int currentKitIndex = 0; + + public NPCRunnable(Practice plugin) { + this.plugin = plugin; + + npcLocations.put(0, plugin.getCustomLocationManager().getNpc1()); + npcLocations.put(1, plugin.getCustomLocationManager().getNpc2()); + npcLocations.put(2, plugin.getCustomLocationManager().getNpc3()); + } + + @Override + public void run() { + List kits = this.plugin.getKitManager().getRankedKits(); + Kit kit = kits.get(currentKitIndex); + + // increment the kit index and wrap around to the start of the list if necessary + currentKitIndex = (currentKitIndex + 1) % kits.size(); + + List leaderboards = this.plugin.getLeaderboardManager() + .getSortedKitLeaderboards(kit, "elo") + .stream().limit(3).collect(Collectors.toList()); + + if (leaderboards.isEmpty()) { + return; + } + + plugin.getHologramManager().updateHolograms(leaderboards, kit); + + List onlinePlayers = new ArrayList<>(Bukkit.getOnlinePlayers()); + + for (int i = 0; i < leaderboards.size(); i++) { + Leaderboard leaderboard = leaderboards.get(i); + NPC npc = NPC.getByName("top" + (i + 1)); + if (npc == null) { + continue; + } + + CustomLocation npcLocation = npcLocations.get(i); + + if (npcLocation == null) { + continue; + } + + Location location = npcLocation.toBukkitLocation(); + npc.setLocation(location); + npc.setYaw(location.getYaw()); + npc.setPitch(location.getPitch()); + npc.setHeadYaw(location.getYaw()); + + Optional player = Optional.ofNullable(plugin.getServer().getOfflinePlayer(leaderboard.getUuid())); + player.ifPresent(p -> { + String[] skin = NPCUtil.getSkinFromMojang(p.getUniqueId()); + + npc.setDisplayName(p.getName()); + + if (skin != null && skin.length >= 2) { + npc.setTexture(skin[0]); + npc.setSignature(skin[1]); + } + }); + + npc.setHand(kit.getIcon()); + + if (npc.getDisplayName() != null) { + onlinePlayers.forEach(npc::destroy); + onlinePlayers.forEach(npc::spawn); + } + + TaskUtil.runAsync(npc::save); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/location/CustomLocation.java b/Practice/src/main/java/me/devkevin/practice/location/CustomLocation.java new file mode 100644 index 0000000..b865d05 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/location/CustomLocation.java @@ -0,0 +1,136 @@ +package me.devkevin.practice.location; + +import java.util.StringJoiner; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + + +@Getter +@Setter +@AllArgsConstructor +public class CustomLocation { + + private final long timestamp = System.currentTimeMillis(); + + private String world; + + private double x; + private double y; + private double z; + + private float yaw; + private float pitch; + + public CustomLocation(double x, double y, double z) { + this(x, y, z, 0.0F, 0.0F); + } + + public CustomLocation(String world, double x, double y, double z) { + this(world, x, y, z, 0.0F, 0.0F); + } + + public CustomLocation(double x, double y, double z, float yaw, float pitch) { + this("world", x, y, z, yaw, pitch); + } + + public static CustomLocation fromBukkitLocation(Location location) { + return new CustomLocation(location.getWorld().getName(), location.getX(), location.getY(), location.getZ(), + location.getYaw(), location.getPitch()); + } + + public static CustomLocation stringToLocation(String string) { + String[] split = string.split(", "); + + double x = Double.parseDouble(split[0]); + double y = Double.parseDouble(split[1]); + double z = Double.parseDouble(split[2]); + + CustomLocation customLocation = new CustomLocation(x, y, z); + + if (split.length == 4) { + customLocation.setWorld(split[3]); + } else if (split.length >= 5) { + customLocation.setYaw(Float.parseFloat(split[3])); + customLocation.setPitch(Float.parseFloat(split[4])); + + if (split.length >= 6) { + customLocation.setWorld(split[5]); + } + } + return customLocation; + } + + public static String locationToString(CustomLocation loc) { + StringJoiner joiner = new StringJoiner(", "); + joiner.add(Double.toString(loc.getX())); + joiner.add(Double.toString(loc.getY())); + joiner.add(Double.toString(loc.getZ())); + if (loc.getYaw() == 0.0f && loc.getPitch() == 0.0f) { + if (loc.getWorld().equals("world")) { + return joiner.toString(); + } else { + joiner.add(loc.getWorld()); + return joiner.toString(); + } + } else { + joiner.add(Float.toString(loc.getYaw())); + joiner.add(Float.toString(loc.getPitch())); + if (loc.getWorld().equals("world")) { + return joiner.toString(); + } else { + joiner.add(loc.getWorld()); + return joiner.toString(); + } + } + } + + public Location toBukkitLocation() { + return new Location(this.toBukkitWorld(), this.x, this.y, this.z, this.yaw, this.pitch); + } + + public double getGroundDistanceTo(CustomLocation location) { + return Math.sqrt(Math.pow(this.x - location.x, 2) + Math.pow(this.z - location.z, 2)); + } + + public double getDistanceTo(CustomLocation location) { + return Math.sqrt(Math.pow(this.x - location.x, 2) + Math.pow(this.y - location.y, 2) + Math.pow(this.z - location.z, 2)); + } + + public World toBukkitWorld() { + if (this.world == null) { + return Bukkit.getServer().getWorlds().get(0); + } else { + return Bukkit.getServer().getWorld(this.world); + } + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof CustomLocation)) { + return false; + } + + CustomLocation location = (CustomLocation) obj; + return location.x == this.x && location.y == this.y && location.z == this.z + && location.pitch == this.pitch && location.yaw == this.yaw; + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .append("x", this.x) + .append("y", this.y) + .append("z", this.z) + .append("yaw", this.yaw) + .append("pitch", this.pitch) + .append("world", this.world) + .append("timestamp", this.timestamp) + .toString(); + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/location/manager/CustomLocationManager.java b/Practice/src/main/java/me/devkevin/practice/location/manager/CustomLocationManager.java new file mode 100644 index 0000000..bc64455 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/location/manager/CustomLocationManager.java @@ -0,0 +1,261 @@ +package me.devkevin.practice.location.manager; + +import lombok.Data; +import me.devkevin.practice.Practice; +import me.devkevin.practice.location.CustomLocation; +import org.bukkit.configuration.file.FileConfiguration; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Data +public class CustomLocationManager { + + private static Practice plugin = Practice.getInstance(); + + // spawns related + private CustomLocation spawn; + private CustomLocation spawnMin; + private CustomLocation spawnMax; + + private CustomLocation editor; + + // Sumo spawns related + private CustomLocation sumoLocation; + private CustomLocation sumoFirst; + private CustomLocation sumoSecond; + private CustomLocation sumoMin; + private CustomLocation sumoMax; + + private CustomLocation oitcLocation; + private List oitcSpawnpoints; + private CustomLocation oitcMin; + private CustomLocation oitcMax; + + private CustomLocation tnttagLocation; + private CustomLocation tnttagGameLocation; + private CustomLocation tnttagMin; + private CustomLocation tnttagMax; + + private CustomLocation tntLocation; + private CustomLocation tntMin; + private CustomLocation tntMax; + + private CustomLocation lmsLocation; + + private CustomLocation npc1; + private CustomLocation npc2; + private CustomLocation npc3; + + private CustomLocation npc1Name; + private CustomLocation npc2Name; + private CustomLocation npc3Name; + + private CustomLocation holoLeaderboardsLocation, holoWinstreakLocation; + + private List lmsLocations = new ArrayList<>(); + + public CustomLocationManager() { + this.oitcSpawnpoints = new ArrayList<>(); + loadConfig(); + } + + private void loadConfig() { + FileConfiguration file = plugin.getMainConfig().getConfig(); + + if (file.contains("spawn")) { + spawn = CustomLocation.stringToLocation(file.getString("spawn")); + } + + if (file.contains("spawnMax")) { + spawnMax = CustomLocation.stringToLocation(file.getString("spawnMax")); + } + + if (file.contains("spawnMin")) { + spawnMin = CustomLocation.stringToLocation(file.getString("spawnMin")); + } + + if (file.contains("npc1")) { + npc1 = CustomLocation.stringToLocation(file.getString("npc1")); + } + + if (file.contains("npc1Name")) + npc1Name = CustomLocation.stringToLocation(file.getString("npc1Name")); + + if (file.contains("npc2Name")) + npc2Name = CustomLocation.stringToLocation(file.getString("npc2Name")); + + if (file.contains("npc3Name")) + npc3Name = CustomLocation.stringToLocation(file.getString("npc3Name")); + + if (file.contains("npc2")) { + npc2 = CustomLocation.stringToLocation(file.getString("npc2")); + } + + if (file.contains("npc3")) { + npc3 = CustomLocation.stringToLocation(file.getString("npc3")); + } + + if (file.contains("holoLeaderboardsLocation")) { + this.holoLeaderboardsLocation = CustomLocation.stringToLocation(file.getString("holoLeaderboardsLocation")); + } + + if (file.contains("winstreakHoloLocation")) { + this.holoWinstreakLocation = CustomLocation.stringToLocation(file.getString("winstreakHoloLocation")); + } + + if (file.contains("editor")) { + editor = CustomLocation.stringToLocation(file.getString("editor")); + } + + if (file.contains("sumoLocation")) { + sumoLocation = CustomLocation.stringToLocation(file.getString("sumoLocation")); + sumoMin = CustomLocation.stringToLocation(file.getString("sumoMin")); + sumoMax = CustomLocation.stringToLocation(file.getString("sumoMax")); + sumoFirst = CustomLocation.stringToLocation(file.getString("sumoFirst")); + sumoSecond = CustomLocation.stringToLocation(file.getString("sumoSecond")); + } + + if (file.contains("oitcLocation")) { + oitcLocation = CustomLocation.stringToLocation(file.getString("oitcLocation")); + oitcMin = CustomLocation.stringToLocation(file.getString("oitcMin")); + oitcMax = CustomLocation.stringToLocation(file.getString("oitcMax")); + + for (String spawnpoint : file.getStringList("oitcSpawnpoints")) { + oitcSpawnpoints.add(CustomLocation.stringToLocation(spawnpoint)); + } + } + + if (file.contains("lmsLocation")) { + this.lmsLocation = CustomLocation.stringToLocation(file.getString("lmsLocation")); + + + file.getStringList("lmsSpawnpoints").forEach(point -> + lmsLocations.add(CustomLocation.stringToLocation(point))); + } + + if (file.contains("tntrunlocation")) { + tntLocation = CustomLocation.stringToLocation(file.getString("tntrunlocation")); + } + + if (file.contains("tntrunMin")) { + tntMin = CustomLocation.stringToLocation(file.getString("tntrunMin")); + } + + if (file.contains("tntrunMax")) { + tntMax = CustomLocation.stringToLocation(file.getString("tntrunMax")); + } + + if (file.contains("taglocation")) { + tnttagLocation = CustomLocation.stringToLocation(file.getString("taglocation")); + } + if (file.contains("tagGameLocation")) { + tnttagGameLocation = CustomLocation.stringToLocation(file.getString("tagGameLocation")); + } + if (file.contains("tagmin")){ + tnttagMin = CustomLocation.stringToLocation(file.getString("tagmin")); + } + if (file.contains("tagmax")){ + tnttagMax = CustomLocation.stringToLocation(file.getString("tagmax")); + } + } + + public void saveConfig() { + FileConfiguration file = plugin.getMainConfig().getConfig(); + + // Main spawn location + if (spawn != null) + file.set("spawn", CustomLocation.locationToString(spawn)); + if (spawnMin != null) + file.set("spawnMin", CustomLocation.locationToString(spawnMin)); + if (spawnMax != null) + file.set("spawnMax", CustomLocation.locationToString(spawnMax)); + + if (npc1 != null) + file.set("npc1", CustomLocation.locationToString(npc1)); + + if (npc2 != null) + file.set("npc2", CustomLocation.locationToString(npc2)); + + if (npc3 != null) + file.set("npc3", CustomLocation.locationToString(npc3)); + + if (npc1Name != null) + file.set("npc1Name", CustomLocation.locationToString(npc1Name)); + + if (npc2Name != null) + file.set("npc2Name", CustomLocation.locationToString(npc2Name)); + + if (npc3Name != null) + file.set("npc3Name", CustomLocation.locationToString(npc3Name)); + + if (holoLeaderboardsLocation != null) + file.set("holoLeaderboardsLocation", CustomLocation.locationToString(holoLeaderboardsLocation)); + + if (holoWinstreakLocation != null) + file.set("winstreakHoloLocation", CustomLocation.locationToString(holoWinstreakLocation)); + + // Editor spawn location + if (editor != null) + file.set("editor", CustomLocation.locationToString(editor)); + + if (sumoLocation != null) + file.set("sumoLocation", CustomLocation.locationToString(sumoLocation)); + if (sumoMin != null) + file.set("sumoMin", CustomLocation.locationToString(sumoMin)); + if (sumoMax != null) + file.set("sumoMax", CustomLocation.locationToString(sumoMax)); + if (sumoFirst != null) + file.set("sumoFirst", CustomLocation.locationToString(sumoFirst)); + if (sumoSecond != null) + file.set("sumoSecond", CustomLocation.locationToString(sumoSecond)); + + if (oitcLocation != null) + file.set("oitcLocation", CustomLocation.locationToString(oitcLocation)); + if (oitcMin != null) + file.set("oitcMin", CustomLocation.locationToString(oitcMin)); + if (oitcMax != null) + file.set("oitcMax", CustomLocation.locationToString(oitcMax)); + if (oitcSpawnpoints != null) + file.set("oitcSpawnpoints", this.fromLocations(oitcSpawnpoints)); + + if (tnttagLocation != null) + file.set("taglocation", CustomLocation.locationToString(tnttagLocation)); + if (tnttagGameLocation != null) + file.set("tagGameLocation", CustomLocation.locationToString(tnttagGameLocation)); + if (tnttagMax != null) + file.set("tagmax", CustomLocation.locationToString(tnttagMax)); + if (tnttagMin != null) + file.set("tagmin", CustomLocation.locationToString(tnttagMin)); + + if (tntLocation != null) + file.set("tntrunlocation", CustomLocation.locationToString(tntLocation)); + if (tntMin != null) + file.set("tntrunMin", CustomLocation.locationToString(tntMin)); + if (tntMax != null) + file.set("tntrunMax", CustomLocation.locationToString(tntMax)); + + if(lmsLocation != null) + file.set("lmsLocation", CustomLocation.locationToString(this.lmsLocation)); + if(lmsLocations.size() > 0) + file.set("lmsSpawnpoints", fromLocations(lmsLocations)); + + // save the config + plugin.getMainConfig().save(); + } + + private List fromLocations(List locations) { + + List toReturn = new ArrayList<>(); + for(CustomLocation location : locations) { + toReturn.add(CustomLocation.locationToString(location)); + } + + return toReturn; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/Match.java b/Practice/src/main/java/me/devkevin/practice/match/Match.java new file mode 100644 index 0000000..3710387 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/Match.java @@ -0,0 +1,291 @@ +package me.devkevin.practice.match; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import io.netty.util.internal.ConcurrentSet; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.match.menu.MatchDetailsMenu; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.TimeUtils; +import net.md_5.bungee.api.chat.BaseComponent; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.github.paperspigot.Title; + +import java.util.*; +import java.util.stream.Stream; + +/** + * Copyright 27/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@Setter +public class Match { + + private final Practice plugin = Practice.getInstance(); + + @Getter private final Map snapshots = new HashMap<>(); + + private static List matches = new ArrayList<>(); + + private final Set entitiesToRemove = new HashSet<>(); + private final LinkedList originalBlockChanges = Lists.newLinkedList(); + private final Set placedBlockLocations = Sets.newConcurrentHashSet(); + private final Set spectators = new ConcurrentSet<>(); + private final Set runnables = new HashSet<>(); + private final Set haveSpectated = new HashSet<>(); + + private final List teams; + + private final UUID matchId = UUID.randomUUID(); + private final QueueType type; + private final Kit kit; + private final Arena arena; + + private StandaloneArena standaloneArena; + private MatchState matchState = MatchState.STARTING; + private int countdown = 6; + private int winningTeamId; + + private long startTimestamp = -1; + + private boolean redrover; + private boolean canContinue = true; + + private String info = "info"; + + private int durationTimer; + + public Match(Arena arena, Kit kit, QueueType type, MatchTeam... teams) { + this.arena = arena; + this.kit = kit; + this.type = type; + this.teams = Arrays.asList(teams); + } + + public boolean isStarting() { + return matchState == MatchState.STARTING; + } + + public boolean isFighting() { + return matchState == MatchState.FIGHTING; + } + + public boolean isEnding() { + return matchState == MatchState.ENDING; + } + + public String getDuration() { + if (this.isStarting()) { + return CC.R + "0:00"; + } + if (this.isEnding()) { + return CC.R + TimeUtils.formatIntoMMSS(durationTimer); + } + if (isFighting()) { + return CC.R + TimeUtils.formatIntoMMSS(durationTimer); + } + return null; + } + + public String getInfoAnimation() { + switch (info) { + case "info": + info = "info."; + break; + case "info.": + info = "info.."; + break; + case "info..": + info = "info..."; + break; + default: + info = "info"; + break; + } + return info; + } + + public long getElapsedDuration() { + return System.currentTimeMillis() - startTimestamp; + } + + public void broadcastWithSound(String message, Sound sound) { + this.teams.forEach(team -> team.alivePlayers().forEach(player -> { + player.sendMessage(message); + player.playSound(player.getLocation(), sound, 10, 1); + })); + this.spectatorPlayers().forEach(spectator -> { + spectator.sendMessage(message); + spectator.playSound(spectator.getLocation(), sound, 10, 1); + }); + } + + public void broadcastTitle(String message, String subMessage) { + Title title = new Title(message, subMessage, 1, 20, 0); + + this.teams.forEach(team -> team.alivePlayers().forEach(player -> player.sendTitle(title))); + this.spectatorPlayers().forEach(spectator -> spectator.sendTitle(title)); + } + + public void broadcastSound(Sound sound) { + this.teams.forEach(team -> team.alivePlayers().forEach(player -> player.playSound(player.getLocation(), sound, 10, 1))); + this.spectatorPlayers().forEach(spectator -> spectator.playSound(spectator.getLocation(), sound, 10, 1)); + } + + public void broadcastMessage(String message) { + teams.forEach(team -> team.alivePlayers().forEach(player -> player.sendMessage(message))); + spectatorPlayers().forEach(spectator -> spectator.sendMessage(message)); + } + + public void broadcastMessage(Clickable message) { + teams.forEach(team -> team.alivePlayers().forEach(message::sendToPlayer)); + spectatorPlayers().forEach(message::sendToPlayer); + } + + public void playSound(Sound sound, Location location, float idk2) { + this.teams.forEach(team -> team.alivePlayers().forEach(player -> { + player.playSound(player.getLocation(), sound, 10, 1); + })); + + this.spectatorPlayers().forEach(spectator -> spectator.playSound(location, sound, 10.0F, idk2)); + } + + public MatchTeam getTeamById(int id) { + return this.getTeams().stream().filter(matchTeam -> matchTeam.getTeamID() == id).findFirst().orElse(null); + } + + public void addSpectator(UUID uuid) { + this.spectators.add(uuid); + } + + public void removeSpectator(UUID uuid) { + this.spectators.remove(uuid); + } + + public void addHaveSpectated(UUID uuid) { + this.haveSpectated.add(uuid); + } + + public boolean haveSpectated(UUID uuid) { + return this.haveSpectated.contains(uuid); + } + + public void addSnapshot(Player player) { + this.snapshots.put(player.getUniqueId(), new MatchDetailsMenu(player, this)); + } + + public boolean hasSnapshot(UUID uuid) { + return this.snapshots.containsKey(uuid); + } + + public MatchDetailsMenu getSnapshot(UUID uuid) { + return this.snapshots.get(uuid); + } + + public void addEntityToRemove(Entity entity) { + this.entitiesToRemove.add(entity); + } + + public void removeEntityToRemove(Entity entity) { + this.entitiesToRemove.remove(entity); + } + + public void clearEntitiesToRemove() { + this.entitiesToRemove.clear(); + } + + public void addRunnable(int id) { + this.runnables.add(id); + } + + public void addOriginalBlockChange(BlockState blockState) { + this.originalBlockChanges.add(blockState); + } + + public void removeOriginalBlockChange(BlockState blockState) { + this.originalBlockChanges.remove(blockState); + } + + public void addPlacedBlockLocation(Location location) { + this.placedBlockLocations.add(location); + } + + public void removePlacedBlockLocation(Location location) { + this.placedBlockLocations.remove(location); + } + + public Stream spectatorPlayers() { + return this.spectators.stream().map(this.plugin.getServer()::getPlayer).filter(Objects::nonNull); + } + + public int decrementCountdown() { + return --this.countdown; + } + + public void incrementDuration() { + ++this.durationTimer; + } + + public boolean isFFA() { + return this.teams.size() == 1; + } + + public boolean isParty() { + return this.isFFA() || this.teams.get(0).getPlayers().size() != 1 && this.teams.get(1).getPlayers().size() != 1; + } + + public boolean isPartyMatch() { + return this.isFFA() || (this.teams.get(0).getPlayers().size() >= 2 || this.teams.get(1).getPlayers().size() >= 2); + } + + public MatchTeam getMatchTeam(int id) { + for (MatchTeam matchTeam : this.getTeams()) { + if (matchTeam.getTeamID() == id) { + return matchTeam; + } + } + return null; + } + + public MatchTeam getMatchTeam(Player player) { + for (MatchTeam matchTeam : this.getTeams()) { + if (matchTeam.getPlayers().contains(player.getUniqueId())) { + return matchTeam; + } + } + return null; + } + + public List getOtherTeam(Player player) { + + List otherTeams = new ArrayList<>(); + + for(MatchTeam matchTeam : this.teams) { + if(matchTeam.getPlayers().contains(player.getUniqueId())) { + continue; + } + otherTeams.add(matchTeam); + } + return otherTeams; + + } + + public void broadcastMessage(BaseComponent[] message) { + this.teams.forEach(team -> team.alivePlayers().forEach(player -> player.spigot().sendMessage(message))); + this.spectatorPlayers().forEach(spectator -> spectator.spigot().sendMessage(message)); + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/MatchRequest.java b/Practice/src/main/java/me/devkevin/practice/match/MatchRequest.java new file mode 100644 index 0000000..1ed1810 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/MatchRequest.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.match; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.arena.Arena; + +import java.util.UUID; + +/** + * Copyright 29/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@RequiredArgsConstructor +public class MatchRequest { + + private final UUID requester; + private final UUID requested; + + private final Arena arena; + private final String kitName; + private final boolean party; +} + diff --git a/Practice/src/main/java/me/devkevin/practice/match/MatchState.java b/Practice/src/main/java/me/devkevin/practice/match/MatchState.java new file mode 100644 index 0000000..06ccdfb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/MatchState.java @@ -0,0 +1,14 @@ +package me.devkevin.practice.match; + +/** + * Copyright 27/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public enum MatchState { + + STARTING, + FIGHTING, + SWITCHING, + ENDING +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/MatchTeam.java b/Practice/src/main/java/me/devkevin/practice/match/MatchTeam.java new file mode 100644 index 0000000..1df57c8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/MatchTeam.java @@ -0,0 +1,57 @@ +package me.devkevin.practice.match; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.team.KillableTeam; +import org.bukkit.Bukkit; +import org.bukkit.Location; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class MatchTeam extends KillableTeam { + + private final int teamID; + private int bridgesPoints; + @Setter private int lives; + @Setter private Location bridgeSpawnLocation; + + private boolean hasBed = true; + private boolean ableToScore = true; + @Setter int matchWins = 0; + + /** + * All players who are currently alive. + */ + private final Set aliveMembers = Collections.newSetFromMap(new ConcurrentHashMap<>()); + + public MatchTeam(UUID leader, List players, int teamID) { + super(leader, players); + this.teamID = teamID; + } + + + public void addPoint() { + this.ableToScore = false; + bridgesPoints = bridgesPoints + 1; + Bukkit.getServer().getScheduler().runTaskLater(Practice.getInstance(), () -> this.ableToScore = true, 100L); + } + + public void destroyBed() { + this.hasBed = false; + } + + public void removeLife() { + lives = lives - 1; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/duel/command/AcceptCommand.java b/Practice/src/main/java/me/devkevin/practice/match/duel/command/AcceptCommand.java new file mode 100644 index 0000000..e268919 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/duel/command/AcceptCommand.java @@ -0,0 +1,141 @@ +package me.devkevin.practice.match.duel.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchRequest; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.party.manager.PartyManager; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class AcceptCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "accept", inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "/accept "); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.getState() != ProfileState.SPAWN && profile.getState() != ProfileState.PARTY) { + player.sendMessage(CC.RED + "Unable to accept a duel within your duel."); + return; + } + + Player target = this.plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + if (player.getName().equals(target.getName())) { + player.sendMessage(CC.RED + "You can't duel yourself."); + return; + } + + Profile targetProfile = this.plugin.getProfileManager().getProfileData(target.getUniqueId()); + + if (targetProfile.isBusy()) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + + if (targetProfile.isBusy()) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + + if (this.plugin.getTournamentManager().isInTournament(target.getUniqueId())) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + if (this.plugin.getTournamentManager().isInTournament(player.getUniqueId())) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + + + MatchRequest request = this.plugin.getMatchManager().getMatchRequest(target.getUniqueId(), player.getUniqueId()); + + if (args.length > 1) { + Kit kit = this.plugin.getKitManager().getKit(args[1]); + + if (kit != null) { + request = this.plugin.getMatchManager().getMatchRequest(target.getUniqueId(), player.getUniqueId(), kit.getName()); + } + } + if (request == null) { + player.sendMessage(CC.RED + "You do not have any pending requests."); + return; + } + if (request.getRequester().equals(target.getUniqueId())) { + List playersA = new ArrayList<>(); + List playersB = new ArrayList<>(); + + PartyManager partyManager = this.plugin.getPartyManager(); + + Party party = partyManager.getParty(player.getUniqueId()); + Party targetParty = partyManager.getParty(target.getUniqueId()); + + if (request.isParty()) { + if (party != null && targetParty != null && partyManager.isLeader(target.getUniqueId()) && partyManager.isLeader(target.getUniqueId())) { + playersA.addAll(party.getMembers()); + playersB.addAll(targetParty.getMembers()); + } else { + player.sendMessage(CC.RED + "That player is not a party leader."); + return; + } + } else { + if (party == null && targetParty == null) { + playersA.add(player.getUniqueId()); + playersB.add(target.getUniqueId()); + } else { + player.sendMessage(CC.RED + "That player is already in a party."); + return; + } + } + + Kit kit = this.plugin.getKitManager().getKit(request.getKitName()); + + MatchTeam teamA = new MatchTeam(target.getUniqueId(), playersB, 0); + MatchTeam teamB = new MatchTeam(player.getUniqueId(), playersA, 1); + + Match match = new Match(request.getArena(), kit, QueueType.UN_RANKED, teamA, teamB); + + Player leaderA = this.plugin.getServer().getPlayer(teamA.getLeader()); + Player leaderB = this.plugin.getServer().getPlayer(teamB.getLeader()); + + match.broadcastMessage(CC.YELLOW + "Starting duel. " + + CC.GRAY + "(" + LandCore.getInstance().getProfileManager().getProfile(leaderA.getUniqueId()).getGrant().getRank().getColor() + leaderA.getName() + CC.GRAY + " vs " + LandCore.getInstance().getProfileManager().getProfile(leaderB.getUniqueId()).getGrant().getRank().getColor() + leaderB.getName() + CC.GRAY + ") in " + CC.GOLD + match.getArena().getName()); + + this.plugin.getMatchManager().createMatch(match); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/duel/command/DuelCommand.java b/Practice/src/main/java/me/devkevin/practice/match/duel/command/DuelCommand.java new file mode 100644 index 0000000..0cb5c24 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/duel/command/DuelCommand.java @@ -0,0 +1,98 @@ +package me.devkevin.practice.match.duel.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DuelCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "duel", inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 1) { + player.sendMessage(CC.RED + "/duel "); + return; + } + + if (this.plugin.getTournamentManager().getTournament(player.getUniqueId()) != null) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Profile targetProfile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.getState() != ProfileState.SPAWN && profile.getState() != ProfileState.PARTY) { + player.sendMessage(CC.RED + "You can't execute that command in your current state."); + return; + } + + Player target = this.plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + if (this.plugin.getTournamentManager().getTournament(target.getUniqueId()) != null) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + if (this.plugin.getTournamentManager().isInTournament(target.getUniqueId())) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if ((party != null && this.plugin.getPartyManager().isInParty(target.getUniqueId(), party)) || player.getName().equals(target.getName())) { + player.sendMessage(CC.RED + "You can't duel yourself."); + return; + } + + if (party != null && !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the leader of the party."); + return; + } + + if (targetProfile.isInQueue() || targetProfile.isFighting()) { + player.sendMessage(CC.RED + "That player is busy."); + return; + } + + if (!targetProfile.getOptions().isDuelRequests()) { + player.sendMessage(CC.RED + "That player is not accepting duel request."); + return; + } + + Party targetParty = this.plugin.getPartyManager().getParty(target.getUniqueId()); + if (party == null && targetParty != null) { + player.sendMessage(CC.RED + "That player is already in a party."); + return; + } + + if (party != null && targetParty == null) { + player.sendMessage(CC.RED + "You are already in a party."); + return; + } + + profile.setDuelSelecting(target.getUniqueId()); + player.openInventory(plugin.getDuelMenu().getDuelMenu().getCurrentPage()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/duel/menu/DuelMenu.java b/Practice/src/main/java/me/devkevin/practice/match/duel/menu/DuelMenu.java new file mode 100644 index 0000000..15859d1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/duel/menu/DuelMenu.java @@ -0,0 +1,227 @@ +package me.devkevin.practice.match.duel.menu; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DuelMenu { + + private final Practice plugin = Practice.getInstance(); + + @Getter private final InventoryUI duelMenu = new InventoryUI(CC.BLUE + "Select a Duel Ladder", true, 2); + @Getter + private final InventoryUI bestOfThreeInventory = new InventoryUI(CC.DARK_RED + "Select Match Type", true, 1); + + private final Map duelMapInventories = new HashMap<>(); + + public DuelMenu() { + menu(); + } + + private void menu() { + Collection kits = this.plugin.getKitManager().getKits(); + + for (Kit kit : kits) { + if (kit.isEnabled()) { + if (!kit.getName().contains("HCF TeamFight")) { + this.duelMenu.addItem(new InventoryUI.AbstractClickableItem(ItemUtil.createItem(kit.getIcon().getType(), CC.PINK + kit.getName(), 1, kit.getIcon().getDurability())) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + DuelClick(player, kit); + } + }); + + this.bestOfThreeInventory.addItem(new InventoryUI.AbstractClickableItem(ItemUtil.createItem(kit.getIcon().getType(), CC.PINK + kit.getName(), 1, kit.getIcon().getDurability())) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + + DuelClick(player, kit); + } + }); + } + } + } + + + for (Kit kit : this.plugin.getKitManager().getKits()) { + InventoryUI duelInventory = new InventoryUI(CC.GOLD + "Select maps", true, 2); + InventoryUI botInventory = new InventoryUI(CC.GOLD + "Select Bot Difficulty", true, 1); + + for (Arena arena : this.plugin.getArenaManager().getArenas().values()) { + if (!arena.isEnabled()) { + continue; + } + if (kit.getArenaWhiteList().size() > 0 && !kit.getArenaWhiteList().contains(arena.getName())) { + continue; + } + + + ItemStack map = new ItemBuilder(Material.valueOf(arena.getIcon())).name(CC.GREEN + arena.getName()) + .durability(arena.getIconData()) + .lore(CC.GOLD + "Authors:") + .lore(CC.GRAY + "LOL Builder Team") + .build(); + + ItemStack random = ItemUtil.createItem(Material.PAPER, CC.YELLOW + "Select random map"); + + duelInventory.setItem(17, new InventoryUI.AbstractClickableItem(random) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + DuelMapClick(player, arena, kit); + } + }); + + duelInventory.addItem(new InventoryUI.AbstractClickableItem(map) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + DuelMapClick(player, arena, kit); + } + }); + } + + this.duelMapInventories.put(kit.getName(), duelInventory); + } + } + + public void DuelClick(Player player, Kit kit) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + Player selected = this.plugin.getServer().getPlayer(profile.getDuelSelecting()); + if (selected == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, profile.getDuelSelecting())); + return; + } + + Profile targetProfile = this.plugin.getProfileManager().getProfileData(selected.getUniqueId()); + if (targetProfile.isBusy()) { + player.sendMessage(CC.RED + "That player is currently busy."); + return; + } + + Party targetParty = this.plugin.getPartyManager().getParty(selected.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + boolean partyDuel = party != null; + if (partyDuel) { + if (targetParty == null) { + player.sendMessage(CC.RED + "That player isn't in a party."); + return; + } + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile.hasDonor() && !kit.getName().contains("HCF TeamFight")) { + player.closeInventory(); + player.openInventory(this.duelMapInventories.get(kit.getName()).getCurrentPage()); + return; + } + + if (coreProfile.hasDonor()) { + player.closeInventory(); + player.openInventory(this.duelMapInventories.get(kit.getName()).getCurrentPage()); + return; + } + + if (this.plugin.getMatchManager().getMatchRequest(player.getUniqueId(), selected.getUniqueId()) != null) { + player.sendMessage(CC.RED + "You have already sent a duel request to this player, please wait."); + return; + } + + Arena arena = this.plugin.getArenaManager().getRandomArena(kit, profile.getLastArenaPlayed()); + if (arena == null) { + player.sendMessage(CC.RED + "There are no arenas available at this moment."); + return; + } + + this.sendDuel(player, selected, kit, partyDuel, party, targetParty, arena); + } + + public void DuelMapClick(Player player, Arena arena, Kit kit) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + Player selected = this.plugin.getServer().getPlayer(profile.getDuelSelecting()); + if (selected == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, profile.getDuelSelecting())); + return; + } + + Profile targetProfile = this.plugin.getProfileManager().getProfileData(selected.getUniqueId()); + if (targetProfile.isBusy()) { + player.sendMessage(CC.RED + "That player is currently busy."); + return; + } + + Party targetParty = this.plugin.getPartyManager().getParty(selected.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + boolean partyDuel = party != null; + if (partyDuel && targetParty == null) { + player.sendMessage(CC.RED + "That player isn't in a party."); + return; + } + + if (this.plugin.getMatchManager().getMatchRequest(player.getUniqueId(), selected.getUniqueId()) != null) { + player.sendMessage(CC.RED + "You have already sent a duel request to this player, please wait."); + return; + } + + this.sendDuel(player, selected, kit, partyDuel, party, targetParty, arena); + } + + + private void sendDuel(Player player, Player selected, Kit kit, boolean partyDuel, Party party, Party targetParty, Arena arena) { + this.plugin.getMatchManager().createMatchRequest(player, selected, arena, kit.getName(), partyDuel); + + player.closeInventory(); + + String requestGetString = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + (partyDuel ? (CC.YELLOW + "'s party " + CC.GREEN + "(" + (party.getMembers().size()) + ")") : "") + CC.YELLOW + " has requested a duel with the kit " + CC.GOLD + kit.getName() + + CC.YELLOW + " on " + CC.GOLD + arena.getName() + CC.YELLOW + ". " + CC.GRAY + "[Click to Accept]"; + String requestSendString = CC.YELLOW + "Sent a duel request to " + CC.GREEN + selected.getName() + (partyDuel ? (CC.YELLOW + "'s party " + CC.GREEN + "(" + (party.getMembers().size()) + ")") : "") + CC.YELLOW + " with the kit " + CC.GREEN + kit.getName() + CC.YELLOW + "."; + + Clickable requestMessage = new Clickable( + requestGetString, + CC.GRAY + "Click to accept duel", + "/accept " + player.getName() + " " + kit.getName()); + + if (partyDuel) { + targetParty.members().forEach(requestMessage::sendToPlayer); + party.broadcast(requestSendString); + } else { + requestMessage.sendToPlayer(selected); + player.sendMessage(requestSendString); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/event/MatchEvent.java b/Practice/src/main/java/me/devkevin/practice/match/event/MatchEvent.java new file mode 100644 index 0000000..756b85b --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/event/MatchEvent.java @@ -0,0 +1,29 @@ +package me.devkevin.practice.match.event; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import me.devkevin.practice.match.Match; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@AllArgsConstructor +public class MatchEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + private final Match match; + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/event/impl/MatchEndEvent.java b/Practice/src/main/java/me/devkevin/practice/match/event/impl/MatchEndEvent.java new file mode 100644 index 0000000..5f0a57a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/event/impl/MatchEndEvent.java @@ -0,0 +1,24 @@ +package me.devkevin.practice.match.event.impl; + +import lombok.Getter; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.match.event.MatchEvent; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class MatchEndEvent extends MatchEvent { + + private final MatchTeam winningTeam; + private final MatchTeam losingTeam; + + public MatchEndEvent(Match match, MatchTeam winningTeam, MatchTeam losingTeam) { + super(match); + this.winningTeam = winningTeam; + this.losingTeam = losingTeam; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/match/event/impl/MatchStartEvent.java b/Practice/src/main/java/me/devkevin/practice/match/event/impl/MatchStartEvent.java new file mode 100644 index 0000000..ae399dc --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/event/impl/MatchStartEvent.java @@ -0,0 +1,16 @@ +package me.devkevin.practice.match.event.impl; + +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.event.MatchEvent; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchStartEvent extends MatchEvent { + + public MatchStartEvent(Match match) { + super(match); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/freeze/FreezeListener.java b/Practice/src/main/java/me/devkevin/practice/match/freeze/FreezeListener.java new file mode 100644 index 0000000..fedb9d1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/freeze/FreezeListener.java @@ -0,0 +1,68 @@ +package me.devkevin.practice.match.freeze; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.event.player.PlayerFreezeEvent; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.match.event.impl.MatchEndEvent; +import me.devkevin.practice.profile.Profile; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +/** + * Copyright 19/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class FreezeListener implements Listener { + + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onPlayerFrozenWhileInMatchEvent(PlayerFreezeEvent event) { + Player player = event.getPlayer(); + + // Get the Practice Profile.class info + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + // Get the Core PlayerData.class info + CoreProfile playerData = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + // check when player's move is frozen + if (playerData.isFrozen()) { + + // if player is not in a match continue + if (profile.getCurrentMatchID() == null) { + return; + } + + // Get the match info by profile player + Match match = this.plugin.getMatchManager().getMatch(profile); + + if (match != null) { + MatchTeam opposingTeam = match.isFFA() ? match.getTeams().get(0) : ((profile.getTeamID() == 0) ? match.getTeams().get(1) : match.getTeams().get(0)); + MatchTeam playerTeam = match.getTeams().get(profile.getTeamID()); + + if (match.isParty()) { + // Remove match and send to spawn is player is in party + this.plugin.getMatchManager().removeFighter(player, profile, false); + this.plugin.getProfileManager().sendToSpawn(player); + } else { + // if player is frozen remove both players from the match, the + // frozen and the opponent, Remove and cancel the match and no winning/losing neither + this.plugin.getServer().getPluginManager().callEvent(new MatchEndEvent(match, opposingTeam, playerTeam)); + match.broadcastMessage(CC.translate("&cThe match as been canceled due to a player being frozen.")); + } + } + // Remove player from the party, don't let frozen player get party + // invites and request match from other users + this.plugin.getPartyManager().removePartyInvites(player.getUniqueId()); + this.plugin.getMatchManager().removeMatchRequests(player.getUniqueId()); + this.plugin.getPartyManager().leaveParty(player); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/history/MatchHistoryInvSnap.java b/Practice/src/main/java/me/devkevin/practice/match/history/MatchHistoryInvSnap.java new file mode 100644 index 0000000..88b0eb0 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/history/MatchHistoryInvSnap.java @@ -0,0 +1,143 @@ +package me.devkevin.practice.match.history; + +import lombok.Getter; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.history.menu.MatchHistoryMenu; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +/** + * Copyright 04/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class MatchHistoryInvSnap { + + private InventoryUI winnerInventory; + private InventoryUI loserInventory; + + public MatchHistoryInvSnap(MatchLocatedData locatedData) { + winnerInv(locatedData); + loserInv(locatedData); + } + + private void winnerInv(MatchLocatedData locatedData) { + ItemStack[] contents = locatedData.getWinnerContents(); + ItemStack[] armor = locatedData.getWinnerArmor(); + this.winnerInventory = new InventoryUI(Bukkit.getOfflinePlayer(locatedData.getWinnerUUID()).getName() + "'s Inventory", true, 6); + + for (int i = 0; i < 9; i++) { + this.winnerInventory.setItem(i + 27, new InventoryUI.EmptyClickableItem(contents[i])); + this.winnerInventory.setItem(i + 18, new InventoryUI.EmptyClickableItem(contents[i + 27])); + this.winnerInventory.setItem(i + 9, new InventoryUI.EmptyClickableItem(contents[i + 18])); + this.winnerInventory.setItem(i, new InventoryUI.EmptyClickableItem(contents[i + 9])); + } + + for (int i = 36; i < 40; i++) { + this.winnerInventory.setItem(i, new InventoryUI.EmptyClickableItem(armor[39 - i])); + } + + this.winnerInventory.setItem(45, new InventoryUI.AbstractClickableItem(ItemUtil.reloreItem(ItemUtil.createItem(Material.BED, CC.RED + "Go back"))) { + @Override + public void onClick(InventoryClickEvent inventoryClickEvent) { + Player clicker = (Player) inventoryClickEvent.getWhoClicked(); + + List matchHistory = Practice.getInstance().getMatchLocatedData().getMatchesByUser(clicker.getUniqueId()); + new MatchHistoryMenu(clicker.getUniqueId(), matchHistory).openMenu(clicker); + } + }); + this.winnerInventory.setItem(49, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.GREEN + "Damage Dealt") + .lore(CC.GRAY + "Hits: " + CC.R + locatedData.getHitsWinner()) + .lore(CC.GRAY + "Longest Combo: " + CC.R + locatedData.getLongestComboWinner()) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + + } + }); + this.winnerInventory.setItem(50, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.POTION).durability(16421) + .name(CC.GREEN + "Potion dealt") + .lore(CC.GRAY + "Potions Thrown: " + CC.R + locatedData.getThrownPotsWinner()) + .lore(CC.GRAY + "Missed Pots: " + CC.R + locatedData.getMissedPotsWinner()) + .lore(CC.GRAY + "Potion Accuracy: " + CC.R + locatedData.getPotionAccuracyWinner()) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + + } + }); + + this.winnerInventory.setItem(53, new InventoryUI.AbstractClickableItem(ItemUtil.reloreItem(ItemUtil.createItem(Material.CHEST, CC.translate("&6View " + Bukkit.getOfflinePlayer(locatedData.getLoserUUID()).getName() + " inventory")), CC.translate("&a swap player"))) { + @Override + public void onClick(InventoryClickEvent inventoryClickEvent) { + Player clicker = (Player) inventoryClickEvent.getWhoClicked(); + clicker.openInventory(loserInventory.getCurrentPage()); + } + }); + } + + private void loserInv(MatchLocatedData locatedData) { + ItemStack[] contents = locatedData.getLoserContents(); + ItemStack[] armor = locatedData.getLoserArmor(); + this.loserInventory = new InventoryUI(Bukkit.getOfflinePlayer(locatedData.getLoserUUID()).getName() + "'s Inventory", true, 6); + + for (int i = 0; i < 9; i++) { + this.loserInventory.setItem(i + 27, new InventoryUI.EmptyClickableItem(contents[i])); + this.loserInventory.setItem(i + 18, new InventoryUI.EmptyClickableItem(contents[i + 27])); + this.loserInventory.setItem(i + 9, new InventoryUI.EmptyClickableItem(contents[i + 18])); + this.loserInventory.setItem(i, new InventoryUI.EmptyClickableItem(contents[i + 9])); + } + for (int i = 36; i < 40; i++) { + this.loserInventory.setItem(i, new InventoryUI.EmptyClickableItem(armor[39 - i])); + } + + this.loserInventory.setItem(45, new InventoryUI.AbstractClickableItem(ItemUtil.reloreItem(ItemUtil.createItem(Material.BED, CC.RED + "Go back"))) { + @Override + public void onClick(InventoryClickEvent inventoryClickEvent) { + Player clicker = (Player) inventoryClickEvent.getWhoClicked(); + + List matchHistory = Practice.getInstance().getMatchLocatedData().getMatchesByUser(clicker.getUniqueId()); + new MatchHistoryMenu(clicker.getUniqueId(), matchHistory).openMenu(clicker); + } + }); + this.loserInventory.setItem(49, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.GREEN + "Damage Dealt") + .lore(CC.GRAY + "Hits: " + CC.R + locatedData.getHitsLoser()) + .lore(CC.GRAY + "Longest Combo: " + CC.R + locatedData.getLongestComboLoser()) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + + } + }); + this.loserInventory.setItem(50, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.POTION).durability(16421) + .name(CC.GREEN + "Potion dealt") + .lore(CC.GRAY + "Potions Thrown: " + CC.R + locatedData.getThrownPotsLoser()) + .lore(CC.GRAY + "Missed Pots: " + CC.R + locatedData.getMissedPotsLoser()) + .lore(CC.GRAY + "Potion Accuracy: " + CC.R + locatedData.getPotionAccuracyLoser()) + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + + } + }); + this.loserInventory.setItem(53, new InventoryUI.AbstractClickableItem(ItemUtil.reloreItem(ItemUtil.createItem(Material.CHEST, CC.translate("&6View " + Bukkit.getOfflinePlayer(locatedData.getWinnerUUID()).getName() + " inventory")), CC.translate("&a swap player"))) { + @Override + public void onClick(InventoryClickEvent inventoryClickEvent) { + Player clicker = (Player) inventoryClickEvent.getWhoClicked(); + clicker.openInventory(winnerInventory.getCurrentPage()); + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/history/MatchLocatedData.java b/Practice/src/main/java/me/devkevin/practice/match/history/MatchLocatedData.java new file mode 100644 index 0000000..2899133 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/history/MatchLocatedData.java @@ -0,0 +1,165 @@ +package me.devkevin.practice.match.history; + +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.UpdateOptions; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.InventoryUtil; +import org.bson.Document; +import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +/** + * Copyright 02/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter @Setter @NoArgsConstructor +public class MatchLocatedData { + + private final Practice plugin = Practice.getInstance(); + + private String id; + + private UUID winnerUUID; + private UUID loserUUID; + + private int winnerEloModifier; + private int loserEloModifier; + + private int winnerElo; + private int loserElo; + + private String date; + private String kit; + + private ItemStack[] winnerArmor; + private ItemStack[] winnerContents; + + private ItemStack[] loserArmor; + private ItemStack[] loserContents; + + // new + private int missedPotsWinner, missedPotsLoser; + private int thrownPotsWinner, thrownPotsLoser; + private int longestComboWinner, longestComboLoser; + private int comboWinner, comboLoser; + private int hitsWinner, hitsLoser; + private double potionAccuracyWinner, potionAccuracyLoser; + + private String matchDuration; + private String arenaName; + + private MatchHistoryInvSnap matchHistoryInvSnap; + + public MatchLocatedData(Document document) { + this.id = document.getString("id"); + + this.winnerUUID = UUID.fromString(document.getString("winnerUuid")); + this.loserUUID = UUID.fromString(document.getString("loserUuid")); + + this.winnerEloModifier = document.getInteger("winnerEloModifier"); + this.loserEloModifier = document.getInteger("loserEloModifier"); + + this.winnerElo = document.getInteger("winnerElo"); + this.loserElo = document.getInteger("loserElo"); + + this.date = document.getString("date"); + this.kit = document.getString("kit"); + + this.winnerArmor = InventoryUtil.deserializeInventory(document.getString("winnerArmor")); + this.winnerContents = InventoryUtil.deserializeInventory(document.getString("winnerContents")); + + this.loserArmor = InventoryUtil.deserializeInventory(document.getString("loserArmor")); + this.loserContents = InventoryUtil.deserializeInventory(document.getString("loserContents")); + + this.missedPotsWinner = document.getInteger("missedPotsWinner"); + this.missedPotsLoser = document.getInteger("missedPotsLoser"); + + this.thrownPotsWinner = document.getInteger("thrownPotsWinner"); + this.thrownPotsLoser = document.getInteger("thrownPotsLoser"); + + this.longestComboWinner = document.getInteger("longestComboWinner"); + this.longestComboLoser = document.getInteger("longestComboLoser"); + + this.comboWinner = document.getInteger("comboWinner"); + this.comboLoser = document.getInteger("comboLoser"); + + this.hitsWinner = document.getInteger("hitsWinner"); + this.hitsLoser = document.getInteger("hitsLoser"); + + this.potionAccuracyWinner = document.getDouble("potionAccuracyWinner"); + this.potionAccuracyLoser = document.getDouble("potionAccuracyLoser"); + + this.matchDuration = document.getString("matchDuration"); + this.arenaName = document.getString("arenaName"); + + this.matchHistoryInvSnap = new MatchHistoryInvSnap(this); + } + + public void save() { + Document document = new Document(); + document.put("id", this.id); + + document.put("winnerUuid", this.winnerUUID.toString()); + document.put("loserUuid", this.loserUUID.toString()); + + document.put("winnerEloModifier", this.winnerEloModifier); + document.put("loserEloModifier", this.loserEloModifier); + + document.put("winnerElo", this.winnerElo); + document.put("loserElo", this.loserElo); + + document.put("date", this.date); + document.put("kit", this.kit); + + document.put("winnerArmor", InventoryUtil.serializeInventory(this.winnerArmor)); + document.put("winnerContents", InventoryUtil.serializeInventory(this.winnerContents)); + + document.put("loserArmor", InventoryUtil.serializeInventory(this.loserArmor)); + document.put("loserContents", InventoryUtil.serializeInventory(this.loserContents)); + + // new + document.put("missedPotsWinner", this.missedPotsWinner); + document.put("missedPotsLoser", this.missedPotsLoser); + + document.put("thrownPotsWinner", this.thrownPotsWinner); + document.put("thrownPotsLoser", this.thrownPotsLoser); + + document.put("longestComboWinner", this.longestComboWinner); + document.put("longestComboLoser", this.longestComboLoser); + + document.put("comboWinner", this.comboWinner); + document.put("comboLoser", this.comboLoser); + + document.put("hitsWinner", this.hitsWinner); + document.put("hitsLoser", this.hitsLoser); + + document.put("potionAccuracyWinner", this.potionAccuracyWinner); + document.put("potionAccuracyLoser", this.potionAccuracyLoser); + + document.put("matchDuration", this.matchDuration); + document.put("arenaName", this.arenaName); + + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> { + plugin.getPracticeDatabase().getMatchHistory().replaceOne(Filters.eq("id", this.id), document, (new UpdateOptions()).upsert(true)); + }); + } + + public List getMatchesByUser(UUID uuid) { + List locatedData = new ArrayList<>(); + List documents = this.plugin.getPracticeDatabase().getMatchHistory().find().into(new ArrayList<>()); + + for (Document document : documents) { + if (document.getString("winnerUuid").equalsIgnoreCase(uuid.toString()) || document.getString("loserUuid").equalsIgnoreCase(uuid.toString())) { + locatedData.add(new MatchLocatedData(document)); + } + } + + return locatedData; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/history/command/MatchHistoryCommand.java b/Practice/src/main/java/me/devkevin/practice/match/history/command/MatchHistoryCommand.java new file mode 100644 index 0000000..4769371 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/history/command/MatchHistoryCommand.java @@ -0,0 +1,61 @@ +package me.devkevin.practice.match.history.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.history.MatchLocatedData; +import me.devkevin.practice.match.history.menu.MatchHistoryMenu; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.Cooldown; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.List; + +/** + * Copyright 03/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchHistoryCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Override @Command(name = "matchhistory", aliases = {"matchhist"}, inGameOnly = true, description = "match history command.", usage = "&cUsage: /matchhistory ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (!profile.getPlayerCommandCooldown().hasExpired()) { + player.sendMessage("&cYou must wait &l"+ + profile.getPlayerCommandCooldown().getTimeMilisLeft() + + " " + + profile.getPlayerCommandCooldown().getContextLeft() + + " &cbefore using that command again."); + + return; + } + + profile.setPlayerCommandCooldown(new Cooldown(5)); + List matchHistory = this.plugin.getMatchLocatedData().getMatchesByUser(target.getUniqueId()); + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> { + new MatchHistoryMenu(target.getUniqueId(), matchHistory).openMenu(player); + }); + + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/history/menu/MatchHistoryMenu.java b/Practice/src/main/java/me/devkevin/practice/match/history/menu/MatchHistoryMenu.java new file mode 100644 index 0000000..3657d7f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/history/menu/MatchHistoryMenu.java @@ -0,0 +1,63 @@ +package me.devkevin.practice.match.history.menu; + +import lombok.AllArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.match.history.MatchLocatedData; +import me.devkevin.practice.match.history.menu.button.MatchHistoryButton; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.pagination.PaginatedMenu; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +import java.util.*; + +/** + * Copyright 02/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class MatchHistoryMenu extends PaginatedMenu { + + private final UUID uuid; + private final List matchLocatedData; + + @Override + public String getTitle(Player player) { + return CC.GREEN + Bukkit.getOfflinePlayer(uuid).getName() + "'s Matches | " + getPage() + "/" + getPages(player); + } + + @Override + public String getPrePaginatedTitle(Player player) { + return "null"; + } + + @Override + public Map getGlobalButtons(Player player) { + Map map = new HashMap<>(); + + Button button = Button.placeholder(Material.STAINED_GLASS_PANE, (byte) 15, ""); + for (int i = 1; i < 8; i++) { + map.put(i, button); + } + + return map; + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttonMap = new HashMap<>(); + + this.matchLocatedData.stream().sorted(Comparator.comparing(MatchLocatedData::getDate).reversed()).forEach(matchData -> { + buttonMap.put(buttonMap.size(), new MatchHistoryButton(matchData)); + }); + + return buttonMap; + } + + @Override + public int getMaxItemsPerPage(Player player) { + return 18; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/history/menu/button/MatchHistoryButton.java b/Practice/src/main/java/me/devkevin/practice/match/history/menu/button/MatchHistoryButton.java new file mode 100644 index 0000000..fabb387 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/history/menu/button/MatchHistoryButton.java @@ -0,0 +1,62 @@ +package me.devkevin.practice.match.history.menu.button; + +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.match.history.MatchLocatedData; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +/** + * Copyright 03/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class MatchHistoryButton extends Button { + + private final MatchLocatedData locatedData; + + @Override + public ItemStack getButtonItem(Player player) { + OfflinePlayer winner = Bukkit.getOfflinePlayer(locatedData.getWinnerUUID()); + OfflinePlayer loser = Bukkit.getOfflinePlayer(locatedData.getLoserUUID()); + + List lore = Lists.newArrayList(); + + lore.add(CC.translate("&8" + locatedData.getDate())); + lore.add(CC.STRIKETHROUGH); + lore.add(CC.translate("&7Kit: &6" + locatedData.getKit())); + lore.add(CC.translate("&7Duration: " + CC.R + locatedData.getMatchDuration())); + lore.add(CC.translate("&7Arena: " + CC.R + locatedData.getArenaName())); + lore.add(CC.STRIKETHROUGH); + lore.add(CC.translate("&7Elo changes:")); + lore.add(CC.translate("&8 • &fWinner Elo: &a " + locatedData.getWinnerElo() + " (+" + locatedData.getWinnerEloModifier() + ")")); + lore.add(CC.translate("&8 • &fLoser Elo: &a " + locatedData.getLoserElo() + " (" + locatedData.getLoserEloModifier() + ")")); + lore.add(CC.STRIKETHROUGH); + lore.add(CC.translate("&aClick to view!")); + + + return new ItemBuilder(Material.SKULL_ITEM) + .name(CC.GREEN + winner.getName() + CC.R + " vs. " + CC.RED + loser.getName()) + .owner(winner.getName()) + .durability(3) + .lore(CC.translate(lore)) + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + playNeutral(player); + player.openInventory(locatedData.getMatchHistoryInvSnap().getWinnerInventory().getCurrentPage()); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/entity/BowBoostingListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/BowBoostingListener.java new file mode 100644 index 0000000..869832e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/BowBoostingListener.java @@ -0,0 +1,67 @@ +package me.devkevin.practice.match.listener.entity; + +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityShootBowEvent; +import org.bukkit.event.player.PlayerVelocityEvent; +import org.bukkit.util.Vector; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 23/02/2023 @ 2:04 + * BowBoostingListener / me.devkevin.practice.match.listener.entity / Practice + */ +public class BowBoostingListener implements Listener { + + @EventHandler + public void onEntityShoot(EntityShootBowEvent event) { + LivingEntity entity = event.getEntity(); + Vector direction = entity.getLocation().getDirection(); + Arrow arrow = (Arrow) event.getProjectile(); + + double speed = arrow.getVelocity().length(); + Vector velocity = direction.multiply(speed); + arrow.setVelocity(velocity); + } + + @EventHandler + public void onPlayerVelocity(PlayerVelocityEvent event) { + Arrow arrow; + Entity damager; + Player player = event.getPlayer(); + Vector velocity = event.getVelocity(); + + EntityDamageEvent eventDamage = player.getLastDamageCause(); + + if (eventDamage != null && !eventDamage.isCancelled() && eventDamage instanceof EntityDamageByEntityEvent && + (damager = ((EntityDamageByEntityEvent) eventDamage).getDamager()) instanceof Arrow && + (arrow = (Arrow) damager).getShooter().equals(player)) { + + double speed = Math.sqrt(velocity.getX() * velocity.getX() + velocity.getZ() * velocity.getZ()); + Vector dir = arrow.getLocation().getDirection().normalize(); + double xVelocity = 1.2; + double zVelocity = 1.2; + Vector newVelocity = new Vector((dir.getX() * speed * -1.0) * xVelocity, velocity.getY(), dir.getZ() * speed * zVelocity); + + event.setVelocity(newVelocity); + } + } + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player && event.getDamager() instanceof Arrow) { + Player entity = (Player) event.getEntity(); + Player damager = (Player) ((Arrow) event.getDamager()).getShooter(); + + if (entity == damager) { + event.setDamage(0); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/entity/EnderpearlListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/EnderpearlListener.java new file mode 100644 index 0000000..1a261bb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/EnderpearlListener.java @@ -0,0 +1,102 @@ +package me.devkevin.practice.match.listener.entity; + +import me.devkevin.practice.Practice; +import net.minecraft.server.v1_8_R3.EntityEnderPearl; +import net.minecraft.server.v1_8_R3.World; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEnderPearl; +import org.bukkit.entity.EnderPearl; +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.ProjectileLaunchEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 04/02/2023 @ 18:52 + * EnderpearlListener / me.devkevin.practice.match.listener.entity / Practice + */ +public class EnderpearlListener implements Listener { + + + private Map validLocations; + private Practice plugin; + + public EnderpearlListener(Practice plugin) { + this.plugin = plugin; + this.validLocations = new HashMap<>(); + this.runCheck(); + this.plugin.getServer().getPluginManager().registerEvents(this, this.plugin); + } + + + @EventHandler + public void onLaunch(final ProjectileLaunchEvent event) { + if (event.getEntity() instanceof EnderPearl) { + this.validLocations.put((EnderPearl)event.getEntity(), event.getEntity().getLocation()); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerTeleport(final PlayerTeleportEvent event) { + if (event.getCause() == PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { + final EnderPearl pearl = this.lookupPearl(event.getPlayer(), event.getTo()); + if (pearl != null) { + final Location validLocation = this.validLocations.get(pearl); + if (validLocation != null) { + validLocation.setX(event.getPlayer().getLocation().getBlockX() + 0.5D); + validLocation.setY(event.getPlayer().getLocation().getBlockY()); + validLocation.setZ(event.getPlayer().getLocation().getBlockZ() + 0.5D); + + validLocation.setPitch(event.getPlayer().getLocation().getPitch()); + validLocation.setYaw(event.getPlayer().getLocation().getYaw()); + event.setTo(validLocation); + } + } + } + } + + private void runCheck() { + new BukkitRunnable() { + public void run() { + final Iterator> iterator = validLocations.entrySet().iterator(); + while (iterator.hasNext()) { + final Map.Entry entry = iterator.next(); + final EnderPearl pearlEntity = entry.getKey(); + if (pearlEntity.isDead()) { + iterator.remove(); + } + else { + final EntityEnderPearl entityEnderPearl = ((CraftEnderPearl)pearlEntity).getHandle(); + final World worldServer = entityEnderPearl.world; + if (!worldServer.getCubes(entityEnderPearl, entityEnderPearl.getBoundingBox().grow(0.25, 0.25, 0.25)).isEmpty()) { + continue; + } + entry.setValue(pearlEntity.getLocation()); + } + } + } + }.runTaskTimerAsynchronously(this.plugin, 1L, 1L); + } + + private EnderPearl lookupPearl(final Player player, final Location to) { + double distance = Double.MAX_VALUE; + EnderPearl canidate = null; + for (final EnderPearl enderpearl : this.validLocations.keySet()) { + final double sqrt = to.distanceSquared(enderpearl.getLocation()); + if (enderpearl.getShooter() == player && sqrt < distance) { + distance = sqrt; + canidate = enderpearl; + } + } + return canidate; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/entity/EntityListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/EntityListener.java new file mode 100644 index 0000000..1898614 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/EntityListener.java @@ -0,0 +1,179 @@ +package me.devkevin.practice.match.listener.entity; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.profile.Profile; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Arrow; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.potion.PotionEffectType; + +/** + * Copyright 03/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EntityListener implements Listener { + + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onEntityDamage(EntityDamageEvent e) { + if (e.getEntity().hasMetadata("NPC")) { + e.setCancelled(true); + return; + } + if (e.getEntity() instanceof Player) { + Player player = (Player) e.getEntity(); + if (player == null) { + return; + } + + Profile practicePlayerData = plugin.getProfileManager().getProfileData(player.getUniqueId()); + switch (practicePlayerData.getState()) { + case FIGHTING: + Match match = plugin.getMatchManager().getMatch(practicePlayerData); + if (match.getMatchState() != MatchState.FIGHTING) { + e.setCancelled(true); + } + if ((match.getKit().isSumo() && e.getCause() == EntityDamageEvent.DamageCause.FALL) || (player.getFallDistance() >= 50 && e.getCause() == EntityDamageEvent.DamageCause.FALL) || match.getKit().isBoxing() && e.getCause() == EntityDamageEvent.DamageCause.FALL) { + e.setCancelled(true); + } + break; + case SPECTATING: + if (e.getCause() == EntityDamageEvent.DamageCause.FIRE || e.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK) { + player.setFireTicks(0); + e.setCancelled(true); + return; + } + + Match spectatedMatch = plugin.getMatchManager().getSpectatingMatch(player.getUniqueId()); + Location locationA = spectatedMatch.getStandaloneArena() != null ? spectatedMatch.getStandaloneArena().getA().toBukkitLocation() : spectatedMatch.getArena().getA().toBukkitLocation(); + + if (e.getCause() == EntityDamageEvent.DamageCause.VOID) { + player.setHealth(player.getMaxHealth()); + if (locationA != null) { + player.teleport(locationA); + } else { + player.teleport(plugin.getCustomLocationManager().getSpawn().toBukkitLocation()); + } + } + e.setCancelled(true); + break; + default: + if (e.getCause() == EntityDamageEvent.DamageCause.VOID) { + e.getEntity().teleport(plugin.getCustomLocationManager().getSpawn().toBukkitLocation()); + } + e.setCancelled(true); + break; + } + } + } + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (!(event.getEntity() instanceof Player)) { + event.setCancelled(true); + return; + } + + Player entity = (Player) event.getEntity(); + Player damager; + + if (event.getDamager() instanceof Player) { + damager = (Player) event.getDamager(); + } else if (event.getDamager() instanceof Arrow && ((Projectile) event.getDamager()).getShooter() != ((Player) event.getEntity()).getPlayer() && event.getDamager() != null) { + damager = (Player) ((Projectile) event.getDamager()).getShooter(); + } else { + return; + } + + Profile entityData = plugin.getProfileManager().getProfileData(entity.getUniqueId()); + Profile damagerData = plugin.getProfileManager().getProfileData(damager.getUniqueId()); + + if (!entity.canSee(damager) && damager.canSee(entity)) { + event.setCancelled(true); + return; + } + + if (entityData == null || damagerData == null) { + event.setCancelled(true); + return; + } + + Match match = plugin.getMatchManager().getMatch(entityData); + if (match == null) { + event.setDamage(0.0D); + return; + } + if (match.getMatchState() != MatchState.FIGHTING) { + return; + } + if (damagerData.getTeamID() == entityData.getTeamID() && !match.isFFA()) { + event.setCancelled(true); + return; + } + if (match.getKit().isSpleef() || match.getKit().isSumo() || match.getKit().isBoxing()) { + event.setDamage(0.0D); + } + if (event.getEntity() instanceof Player && event.getDamager() instanceof Player) { + damagerData.setCombo(damagerData.getCombo() + 1); + damagerData.setHits(damagerData.getHits() + 1); + if (damagerData.getCombo() > damagerData.getLongestCombo()) { + damagerData.setLongestCombo(damagerData.getCombo()); + } + entityData.setCombo(0); + + if (isCritical(damager)) { + damagerData.incrementCriticalHits(); + } + + if (entity.isBlocking()) { + entityData.incrementBlockedHits(); + } + + if (match.getKit().isSpleef()) { + event.setCancelled(true); + } + if (match.getKit().isBoxing()) { + if (damagerData.getHits() >= 100) { + plugin.getMatchManager().removeFighter(entity, entityData, true); + } + } + } else if (event.getDamager() instanceof Arrow) { + Arrow arrow = (Arrow) event.getDamager(); + + if (arrow.getShooter() instanceof Player) { + Player shooter = (Player) arrow.getShooter(); + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(shooter.getUniqueId()); + + if (!entity.getName().equals(shooter.getName())) { + double health = Math.ceil(entity.getHealth() - event.getFinalDamage()) / 2.0D; + + if (health > 0.0D) { + shooter.sendMessage(coreProfile.getGrant().getRank().getColor() + entity.getDisplayName() + CC.GOLD + " has been shot " + CC.GRAY + " (" + CC.RED + health + "\u2764" + CC.GRAY + ")"); + } + } + } + } + } + + private boolean isCritical(Player attacker) { + return attacker.getFallDistance() > 0.0F && + !attacker.isOnGround() && + !attacker.isInsideVehicle() && + !attacker.hasPotionEffect(PotionEffectType.BLINDNESS) && + attacker.getLocation().getBlock().getType() != Material.LADDER && + attacker.getLocation().getBlock().getType() != Material.VINE; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/entity/MatchRodListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/MatchRodListener.java new file mode 100644 index 0000000..c587d05 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/MatchRodListener.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.match.listener.entity; + +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.FishHook; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.player.PlayerItemDamageEvent; + +/** + * Copyright 13/06/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchRodListener implements Listener { + + // Makes sure fishing rods don't do any damage to armor. + + @EventHandler + public void onItemDamage(PlayerItemDamageEvent event) { + Player player = event.getPlayer(); + + // dirty armor check + if (!Enchantment.PROTECTION_ENVIRONMENTAL.canEnchantItem(event.getItem())) { + return; + } + + // if their last damage cause is by a fishing hook, don't allow any damage. + if (player.getLastDamageCause() != null && player.getLastDamageCause() instanceof EntityDamageByEntityEvent) { + if (((EntityDamageByEntityEvent) player.getLastDamageCause()).getDamager() instanceof FishHook) { + event.setCancelled(true); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/entity/PotionMatchListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/PotionMatchListener.java new file mode 100644 index 0000000..f482b59 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/PotionMatchListener.java @@ -0,0 +1,67 @@ +package me.devkevin.practice.match.listener.entity; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.profile.Profile; +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.PotionSplashEvent; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +/** + * Copyright 15/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PotionMatchListener implements Listener { + + private final Practice plugin = Practice.getInstance(); + + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPotionSplash(PotionSplashEvent event) { + if (!(event.getEntity().getShooter() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity().getShooter(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) return; + + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + + if (match == null) return; + + if (match.isFighting()) { + for (PotionEffect effect : event.getEntity().getEffects()) { + if (!effect.getType().equals(PotionEffectType.INVISIBILITY)) { + Player shooter = (Player) event.getEntity().getShooter(); + if (shooter == null) { + return; + } + + Profile shooterData = this.plugin.getProfileManager().getProfileData(shooter.getUniqueId()); + shooterData.setPotionsThrown(shooterData.getPotionsThrown() + 1); + + /*if (event.getIntensity(shooter) <= 0.5D) { + shooterData.setPotionsMissed(shooterData.getPotionsMissed() + 1); + }*/ + + break; + } + } + for (PotionEffect effect : event.getEntity().getEffects()) { + if (effect.getType().equals(PotionEffectType.HEAL)) { + profile.getPotions().add(event.getPotion().getLocation()); + if (event.getIntensity(player) <= 0.5D) { + profile.incrementPotionsMissed(); + } + } + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/entity/SwordBlockDetector.java b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/SwordBlockDetector.java new file mode 100644 index 0000000..df32172 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/entity/SwordBlockDetector.java @@ -0,0 +1,46 @@ +package me.devkevin.practice.match.listener.entity; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 03/02/2023 @ 14:42 + * SwordBlockDetector / me.devkevin.practice.match.listener.entity / Practice + */ +public class SwordBlockDetector implements Listener { + private int counter = 0; + + @EventHandler + public void onEntityDamage(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player && event.getDamager() instanceof Player) { + Player defender = (Player) event.getEntity(); + Player attacker = (Player) event.getDamager(); + + Profile defenderProfile = Practice.getInstance().getProfileManager().getProfileData(defender.getUniqueId()); + Profile attackerProfile = Practice.getInstance().getProfileManager().getProfileData(attacker.getUniqueId()); + + + if (attackerProfile.isFighting() && defenderProfile.isFighting()) { + if (defender.isBlocking() && defender.getInventory().getItemInHand().getType().toString().contains("SWORD")) { + new BukkitRunnable() { + @Override + public void run() { + if (defender.isBlocking() && counter >= 20) { + defender.setHealth(defender.getHealth() - 1.0); + cancel(); + } else if (defender.isBlocking()) { + counter++; + } + } + }.runTaskAsynchronously(Practice.getInstance()); + } + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/game/MatchEndListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/game/MatchEndListener.java new file mode 100644 index 0000000..56bac38 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/game/MatchEndListener.java @@ -0,0 +1,426 @@ +package me.devkevin.practice.match.listener.game; + +import club.inverted.chatcolor.CC; +import com.google.common.base.Joiner; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.elo.EloCalculator; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.match.event.impl.MatchEndEvent; +import me.devkevin.practice.match.history.MatchLocatedData; +import me.devkevin.practice.match.menu.MatchDetailsMenu; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.TaskUtil; +import me.devkevin.practice.util.TimeUtils; +import net.md_5.bungee.api.chat.*; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.potion.PotionEffect; + +import java.util.*; + +/** + * Copyright 12/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchEndListener implements Listener { + + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onMatchEnd(MatchEndEvent event) { + Match match = event.getMatch(); + Clickable inventories = new Clickable(); + + + match.setMatchState(MatchState.ENDING); + match.setWinningTeamId(event.getWinningTeam().getTeamID()); + match.setCountdown(4); + + List spectators = new ArrayList<>(match.getSpectators()); + spectators.stream() + .filter(spec -> !Practice.getInstance().getProfileManager().getProfileData(spec).getCachedPlayer().isEmpty()) + .forEach(spec -> Practice.getInstance().getProfileManager().getProfileData(spec).getCachedPlayer().clear() + ); + + match.getTeams().forEach(team -> team.players().forEach(player -> { + if (!match.hasSnapshot(player.getUniqueId())) { + match.addSnapshot(player); + } + + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.getActivePotionEffects().stream().map(PotionEffect::getType).forEach(player::removePotionEffect); + player.setHealth(20.0D); + player.setFoodLevel(20); + player.setSaturation(12.8F); + player.setFireTicks(0); + player.setMaximumNoDamageTicks(20); + })); + + Optional winnerPlayer = Optional.ofNullable(this.plugin.getServer().getPlayer(event.getWinningTeam().getLeader())); + Optional loserPlayer = Optional.ofNullable(this.plugin.getServer().getPlayer(event.getLosingTeam().getLeader())); + + // Implement Data practice for winner & losser + Player winnerLeader = this.plugin.getServer().getPlayer(event.getWinningTeam().getPlayers().get(0)); + Profile winnerLeaderData = this.plugin.getProfileManager() + .getProfileData(winnerLeader.getUniqueId()); + + Player loserLeader = this.plugin.getServer().getPlayer(event.getLosingTeam().getPlayers().get(0)); + Profile loserLeaderData = this.plugin.getProfileManager() + .getProfileData(loserLeader.getUniqueId()); + + MatchTeam winnerTeam = event.getWinningTeam(); + MatchTeam losingTeam = event.getLosingTeam(); + + + if (match.isPartyMatch() && !match.isFFA() && match.getKit().getName().equalsIgnoreCase("HCF")) { + Party partyOne = plugin.getPartyManager().getParty(match.getTeams().get(0).getLeader()), + partyTwo = plugin.getPartyManager().getParty(match.getTeams().get(1).getLeader()); + + partyOne.getBards().parallelStream().forEach(bardUuid -> plugin.getProfileManager().getProfileData(bardUuid).incrementPlayedBard()); + partyTwo.getBards().parallelStream().forEach(bardUuid -> plugin.getProfileManager().getProfileData(bardUuid).incrementPlayedBard()); + + partyOne.getArchers().parallelStream().forEach(archerUuid -> plugin.getProfileManager().getProfileData(archerUuid).incrementPlayedArcher()); + partyTwo.getArchers().parallelStream().forEach(archerUuid -> plugin.getProfileManager().getProfileData(archerUuid).incrementPlayedArcher()); + + } + + if (match.isFFA()) { + Player winner = this.plugin.getServer().getPlayer(event.getWinningTeam().getAlivePlayers().get(0)); + match.broadcastMessage(PracticeLang.line); + String winnerMessage = ChatColor.DARK_PURPLE + "Winner: " + CC.PINK + winner.getName(); + + event.getWinningTeam().players().forEach(player -> { + + if (!match.hasSnapshot(player.getUniqueId())) { + match.addSnapshot(player); + } + + inventories.add((player.getUniqueId() == winner.getUniqueId() ? ChatColor.GREEN : ChatColor.RED) + + player.getName() + " ", + ChatColor.RED + "View Inventory", + "/inventory " + match.getSnapshot(player.getUniqueId()).getSnapshotId()); + + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.getActivePotionEffects().stream().map(PotionEffect::getType).forEach(player::removePotionEffect); + player.setHealth(20.0D); + player.setFoodLevel(20); + player.setSaturation(12.8F); + player.setFireTicks(0); + }); + + for (MatchDetailsMenu snapshot : match.getSnapshots().values()) { + this.plugin.getMatchDetailSnapshot().addSnapshot(snapshot); + } + + match.broadcastMessage(winnerMessage); + match.broadcastMessage(inventories); + match.broadcastMessage(PracticeLang.line); + } else if (match.isParty()) { + match.getTeams().forEach(team -> team.players().forEach(player -> { + if (!match.hasSnapshot(player.getUniqueId())) { + match.addSpectator(player.getUniqueId()); + } + + boolean winningTeam = this.plugin.getProfileManager().getProfileData(player.getUniqueId()).getTeamID() == event.getWinningTeam().getTeamID(); + + inventories.add((winningTeam ? CC.GREEN : CC.RED) + + player.getName() + " ", + ChatColor.DARK_PURPLE + "View menus", + "/inventory " + match.getSnapshot(player.getUniqueId()).getSnapshotId()); + + })); + + for (MatchDetailsMenu snapshot : match.getSnapshots().values()) { + this.plugin.getMatchDetailSnapshot().addSnapshot(snapshot); + } + + String winnerMessage = ChatColor.DARK_PURPLE + "Winning Team: " + + CC.PINK + event.getWinningTeam().getLeaderName(); + + match.broadcastMessage(""); + match.broadcastMessage(winnerMessage); + match.broadcastMessage(inventories); + } + else if (match.getKit().isBedWars()) { + match.broadcastMessage(PracticeLang.line); + match.broadcastMessage(CC.GOLD + "Match Results"); + match.broadcastMessage(""); + + match.broadcastMessage(CC.translate( + String.valueOf(winnerTeam.getTeamID() == 1 ? "&9Blue" : "&cRed" + " &ahas won!") + )); + + match.broadcastMessage(CC.translate( + String.valueOf(losingTeam.getTeamID() == 1 ? "&9Blue" : "&cRed" + " &ahas won!") + )); + + match.broadcastMessage(CC.translate( + String.valueOf(winnerTeam.getTeamID() == 1 ? "&9" : "&c") + + String.valueOf(winnerTeam.getBridgesPoints()) + " &7- " + + String.valueOf(losingTeam.getTeamID() == 1 ? "&9" : "&c") + + String.valueOf(losingTeam.getBridgesPoints()) + )); + + match.broadcastMessage(""); + match.broadcastMessage(CC.GOLD + "Inventories"); + + Map inventorySnapshotMap = new LinkedHashMap<>(); + + match.getTeams().forEach(team -> team.players().forEach(player -> { + if (!match.hasSnapshot(player.getUniqueId())) { + match.addSnapshot(player); + } + + inventorySnapshotMap.put(player.getUniqueId(), match.getSnapshot(player.getUniqueId())); + + boolean onWinningTeam = this.plugin.getProfileManager().getProfileData(player.getUniqueId()).getTeamID() == event.getWinningTeam().getTeamID(); + + inventories.add((onWinningTeam ? ChatColor.GREEN : ChatColor.RED) + + player.getName() + " ", + ChatColor.AQUA + "View menus", + "/inventory " + match.getSnapshot(player.getUniqueId()).getSnapshotId()); + + player.setMaximumNoDamageTicks(20); // Double setting the damage ticks. + })); + + for (MatchDetailsMenu snapshot : match.getSnapshots().values()) { + this.plugin.getMatchDetailSnapshot().addSnapshot(snapshot); + } + + match.broadcastMessage(inventories); + match.broadcastMessage(PracticeLang.line); + } + else if (match.isRedrover()) { + match.broadcastMessage(CC.GREEN + event.getWinningTeam().getLeaderName() + CC.GRAY + " has won the redrover!"); + } + else { + match.broadcastMessage(""); + match.broadcastMessage(CC.YELLOW + CC.BOLD + "Match Results: " + CC.GRAY + "(Click player to view):"); + + Map inventorySnapshotMap = new LinkedHashMap<>(); + + match.getTeams().forEach(team -> team.players().forEach(player -> { + if (!match.hasSnapshot(player.getUniqueId())) { + match.addSnapshot(player); + } + + inventorySnapshotMap.put(player.getUniqueId(), match.getSnapshot(player.getUniqueId())); + + boolean onWinningTeam = this.plugin.getProfileManager().getProfileData(player.getUniqueId()).getTeamID() == event.getWinningTeam().getTeamID(); + + inventories.add(CC.YELLOW + "Click to view " + (onWinningTeam ? ChatColor.GREEN : ChatColor.RED) + player.getName(), CC.YELLOW + "'s inventory", + "/inventory " + match.getSnapshot(player.getUniqueId()).getSnapshotId()); + + + // Pvplounge death animation + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.getActivePotionEffects().stream().map(PotionEffect::getType).forEach(player::removePotionEffect); + player.setHealth(20.0D); + player.setFoodLevel(20); + player.setSaturation(12.8F); + player.setFireTicks(0); + + player.setMaximumNoDamageTicks(20); // Double setting the damage ticks. + + MatchTeam otherTeam = team == match.getTeams().get(0) ? match.getTeams().get(1) : match.getTeams().get(0); + })); + + for (MatchDetailsMenu snapshot : match.getSnapshots().values()) { + this.plugin.getMatchDetailSnapshot().addSnapshot(snapshot); + } + + TextComponent first = new TextComponent(); + first.setText(ChatColor.translateAlternateColorCodes('&', "&aWinner: &e")); + + + TextComponent winner = new TextComponent(); + winner.setText(ChatColor.translateAlternateColorCodes('&', "&e" + winnerLeader.getName())); + winner.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/inventory " + match.getSnapshot(winnerLeader.getUniqueId()).getSnapshotId())); + winner.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(ChatColor.translateAlternateColorCodes('&', "&eClick to see the &6" + winnerLeader.getName() + "&e's menus")).create())); + + TextComponent second = new TextComponent(); + second.setText(ChatColor.translateAlternateColorCodes('&', " &7\u239c ")); + TextComponent third = new TextComponent(); + third.setText(ChatColor.translateAlternateColorCodes('&', "&cLoser: &e")); + TextComponent loser = new TextComponent(); + loser.setText(ChatColor.translateAlternateColorCodes('&', "&e" + loserLeader.getName())); + loser.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/inventory " + match.getSnapshot(loserLeader.getUniqueId()).getSnapshotId())); + loser.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(ChatColor.translateAlternateColorCodes('&', "&eClick to see the &6" + loserLeader.getName() + "&e's menus")).create())); + + BaseComponent[] bases = { + first, + winner, + second, + third, + loser + }; + + match.broadcastMessage(bases); + match.broadcastMessage(""); + + /*Player winnerLeader = this.plugin.getServer().getPlayer(event.getWinningTeam().getPlayers().get(0)); + Profile winnerLeaderData = this.plugin.getProfileManager() + .getProfileData(winnerLeader.getUniqueId()); + Player loserLeader = this.plugin.getServer().getPlayer(event.getLosingTeam().getPlayers().get(0)); + Profile loserLeaderData = this.plugin.getProfileManager() + .getProfileData(loserLeader.getUniqueId());*/ + + + winnerLeaderData.setMatchesPlayed(winnerLeaderData.getMatchesPlayed() + 1); + loserLeaderData.setMatchesPlayed(loserLeaderData.getMatchesPlayed() + 1); + + String kitName = match.getKit().getName(); + + winnerLeaderData.setCurrentWinstreak(kitName, winnerLeaderData.getCurrentWinstreak(kitName) + 1); + loserLeaderData.setCurrentWinstreak(kitName, 0); + if (winnerLeaderData.getCurrentWinstreak(kitName) > winnerLeaderData.getHighestWinStreak(kitName)) { + winnerLeaderData.setHighestWinStreak(kitName, winnerLeaderData.getCurrentWinstreak(kitName)); + } + + winnerLeaderData.setGlobalWinStreak(winnerLeaderData.getGlobalWinStreak() + 1); + loserLeaderData.setGlobalWinStreak(0); + if (winnerLeaderData.getGlobalWinStreak() > winnerLeaderData.getGlobalHighestWinStreak()) { + winnerLeaderData.setGlobalHighestWinStreak(winnerLeaderData.getGlobalWinStreak()); + } + + /*//TODO: + if (match.getType().isBoth()) { + return; + }*/ + + if (match.getType().isRanked()) { + + UUID loserUuid = loserPlayer.map(Player::getUniqueId).orElse(UUID.randomUUID()); + UUID winnerUuid = winnerPlayer.map(Player::getUniqueId).orElse(UUID.randomUUID()); + + String eloMessage; + + int winnerElo; + int loserElo; + + winnerElo = winnerLeaderData.getElo(kitName); + loserElo = loserLeaderData.getElo(kitName); + + int[] rankings = EloCalculator.getNewRankings(winnerElo, loserElo, true); + + + eloMessage = + CC.DARK_PURPLE + "Elo changes: " + CC.PINK + winnerLeader.getName() + " +" + (rankings[0] - winnerElo) + " (" + rankings[0] + ")" + + + CC.DARK_PURPLE + " / " + + + CC.RED + loserLeader.getName() + " " + (rankings[1] - loserElo) + " (" + rankings[1] + ")"; + + if (match.getType() == QueueType.RANKED) { + winnerLeaderData.setElo(kitName, rankings[0]); + loserLeaderData.setElo(kitName, rankings[1]); + + winnerLeaderData.setWins(kitName, winnerLeaderData.getWins(kitName) + 1); + loserLeaderData.setLosses(kitName, loserLeaderData.getLosses(kitName) + 1); + + winnerLeaderData.setWins(kitName, winnerLeaderData.getRankedWins().size() + 1); + loserLeaderData.setLosses(kitName, loserLeaderData.getRankedLosses().size() + 1); + + match.broadcastMessage(eloMessage); + + MatchLocatedData matchLocatedData = new MatchLocatedData(); + matchLocatedData.setId(UUID.randomUUID().toString().split("-")[0]); + + matchLocatedData.setWinnerUUID(winnerUuid); + matchLocatedData.setLoserUUID(loserUuid); + + matchLocatedData.setWinnerEloModifier(rankings[0] - winnerElo); + matchLocatedData.setLoserEloModifier(rankings[1] - loserElo); + + matchLocatedData.setWinnerElo(rankings[0]); + matchLocatedData.setLoserElo(rankings[1]); + + matchLocatedData.setDate(TimeUtils.nowDate()); + matchLocatedData.setKit(match.getKit().getName()); + + matchLocatedData.setWinnerArmor(event.getMatch().getSnapshot(winnerUuid).getArmor()); + matchLocatedData.setWinnerContents(event.getMatch().getSnapshot(winnerUuid).getInventory()); + + matchLocatedData.setLoserArmor(event.getMatch().getSnapshot(loserUuid).getArmor()); + matchLocatedData.setLoserContents(event.getMatch().getSnapshot(loserUuid).getInventory()); + // new + matchLocatedData.setMissedPotsWinner(winnerLeaderData.getPotionsMissed()); + matchLocatedData.setMissedPotsLoser(loserLeaderData.getPotionsMissed()); + + matchLocatedData.setThrownPotsWinner(winnerLeaderData.getPotionsThrown()); + matchLocatedData.setThrownPotsLoser(loserLeaderData.getPotionsThrown()); + + matchLocatedData.setLongestComboWinner(winnerLeaderData.getLongestCombo()); + matchLocatedData.setLongestComboLoser(loserLeaderData.getLongestCombo()); + + matchLocatedData.setComboWinner(winnerLeaderData.getCombo()); + matchLocatedData.setComboLoser(loserLeaderData.getCombo()); + + matchLocatedData.setHitsWinner(winnerLeaderData.getHits()); + matchLocatedData.setHitsLoser(loserLeaderData.getHits()); + + matchLocatedData.setPotionAccuracyWinner(winnerLeaderData.getPotionAccuracy()); + matchLocatedData.setPotionAccuracyLoser(loserLeaderData.getPotionAccuracy()); + + matchLocatedData.setMatchDuration(event.getMatch().getDuration()); + matchLocatedData.setArenaName(event.getMatch().getArena().getName()); + matchLocatedData.save(); + } + } + plugin.getMatchManager().processRequeue(loserLeader, match); + plugin.getMatchManager().processRequeue(winnerLeader, match); + plugin.getMatchManager().saveRematches(match); + } + if (spectators.size() > 1) { + List spectatorNames = new ArrayList<>(); + for (UUID uuid : spectators) { + spectatorNames.add(Bukkit.getPlayer(uuid).getName()); + spectatorNames.remove(Bukkit.getPlayer(event.getLosingTeam().getLeader()).getName()); + } + + spectatorNames.sort(String::compareToIgnoreCase); + + String firstFourNames = Joiner.on(", ").join( + spectatorNames.subList( + 0, + Math.min(spectatorNames.size(), 4) + ) + ); + + if (spectatorNames.size() > 4) { + firstFourNames += " (+" + (spectatorNames.size() - 4) + " more)"; + } + + String spectators2 = ChatColor.YELLOW + "Spectators (" + spectatorNames.size() + "): " + ChatColor.LIGHT_PURPLE + firstFourNames; + String space = " "; + + match.broadcastMessage(space); + match.broadcastMessage(spectators2); + } + + match.getTeams().forEach(matchTeam -> matchTeam.players().forEach(player -> { + Profile data = plugin.getProfileManager().getProfileData(player.getUniqueId()); + data.getPotions().clear(); + data.getPackets().clear(); + + data.setLastArenaPlayed(match.getArena()); + + TaskUtil.runAsync(() -> this.plugin.getVoteManager().sendVoteMessage(player, match.getArena())); + })); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/game/MatchStartListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/game/MatchStartListener.java new file mode 100644 index 0000000..da747af --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/game/MatchStartListener.java @@ -0,0 +1,157 @@ +package me.devkevin.practice.match.listener.game; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.location.CustomLocation; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.event.impl.MatchStartEvent; +import me.devkevin.practice.match.task.MatchLogicTask; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.HashSet; +import java.util.Set; + +/** + * Copyright 02/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchStartListener implements Listener { + + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onMatchStart(MatchStartEvent event) { + Match match = event.getMatch(); + Kit kit = match.getKit(); + + if (!kit.isEnabled()) { + match.broadcastMessage(CC.RED + "This kit is currently disabled."); + this.plugin.getMatchManager().removeMatch(match); + return; + } + + if (kit.isBuild() || kit.isSpleef()) { + if (match.getArena().getAvailableArenas().size() > 0) { + match.setStandaloneArena(match.getArena().getAvailableArena()); + plugin.getArenaManager().setArenaMatchUUID(match.getStandaloneArena(), match.getMatchId()); + } else { + match.broadcastMessage(CC.RED + "There are no arenas available at this moment."); + plugin.getMatchManager().removeMatch(match); + return; + } + } + + Set matchPlayers = new HashSet<>(); + match.getTeams().forEach(team -> team.alivePlayers().forEach(player -> { + matchPlayers.add(player); + + this.plugin.getMatchManager().removeMatchRequests(player.getUniqueId()); + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + /*profile.getCachedPlayer().clear(); + profile.setFollowingId(null); + profile.setFollowing(false);*/ + + player.setAllowFlight(false); + player.setFlying(false); + + profile.setCurrentMatchID(match.getMatchId()); + profile.setTeamID(team.getTeamID()); + + profile.setPotionsMissed(0); + profile.setPotionsThrown(0); + profile.setLongestCombo(0); + profile.setCombo(0); + profile.setHits(0); + + PlayerUtil.reset(player); + + CustomLocation locationA = match.getStandaloneArena() != null ? match.getStandaloneArena().getA() : match.getArena().getA(); + CustomLocation locationB = match.getStandaloneArena() != null ? match.getStandaloneArena().getB() : match.getArena().getB(); + + if (player.getWorld().isChunkLoaded(player.getLocation().getChunk())) { + player.getWorld().refreshChunk(player.getLocation().getChunk().getX(), player.getLocation().getChunk().getZ()); + } + + /*// As we've added a new entire bundle pack of practice arenas and im so fucking lazy that i won't separate it in different chunks and alone positions + // so what I do here is to set the center of the visible area at the midpoint between the minimum and maximum limits in X and Z, and the size of the + // visible area as the distance between the maximum limit and the minimum limit in the longest direction. + // + // Any chunks outside the set limits will not be loaded for the player, which means that the player will only see the blocks and entities within the limited area. + int minX = match.getStandaloneArena() != null ? match.getStandaloneArena().getMin().toBukkitLocation().getBlockX() : match.getArena().getMin().toBukkitLocation().getBlockX(); + int minZ = match.getStandaloneArena() != null ? match.getStandaloneArena().getMin().toBukkitLocation().getBlockZ() : match.getArena().getMin().toBukkitLocation().getBlockZ(); + + int maxX = match.getStandaloneArena() != null ? match.getStandaloneArena().getMax().toBukkitLocation().getBlockX() : match.getArena().getMax().toBukkitLocation().getBlockX(); + int maxZ = match.getStandaloneArena() != null ? match.getStandaloneArena().getMax().toBukkitLocation().getBlockZ() : match.getArena().getMax().toBukkitLocation().getBlockZ(); + + WorldBorder worldBorder = player.getWorld().getWorldBorder(); + + worldBorder.setCenter((minX + maxX) / 2.0, (minZ + maxZ) / 2.0); + worldBorder.setSize(Math.max(maxX - minX, maxZ - minZ));*/ + + player.teleport(team.getTeamID() == 1 ? locationA.toBukkitLocation() : locationB.toBukkitLocation()); + + if (kit.isBoxing()) { + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile.hasDonor()) { + player.getInventory().setContents(this.plugin.getHotbarItem().getBoxingSwordDonor()); + } else { + player.getInventory().setContents(this.plugin.getHotbarItem().getBoxingSword()); + } + + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1)); + + player.sendMessage(CC.YELLOW + "First to 100 hits wins the match!"); + } + + if (kit.isCombo()) { + player.setMaximumNoDamageTicks(3); + } + + if (kit.getName().equalsIgnoreCase("Axe")) { + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1)); + } + + if (kit.getName().equalsIgnoreCase("Strategy")) { + player.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, Integer.MAX_VALUE, 1)); + } + + if (kit.getName().equalsIgnoreCase("Bard") && kit.getName().equalsIgnoreCase("ArcherHCF")) { + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, 1)); + player.addPotionEffect(new PotionEffect(PotionEffectType.FIRE_RESISTANCE, Integer.MAX_VALUE, 1)); + } + + plugin.getMatchManager().giveKits(player, kit); + + profile.setState(ProfileState.FIGHTING); + })); + + for (Player player : matchPlayers) { + for (Player online : this.plugin.getServer().getOnlinePlayers()) { + online.hidePlayer(player); + player.hidePlayer(online); + } + } + + for (Player player : matchPlayers) { + for (Player other : matchPlayers) { + player.showPlayer(other); + } + } + + new MatchLogicTask(match).runTaskTimer(this.plugin, 20L, 20L); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/listener/time/MatchDurationLimitListener.java b/Practice/src/main/java/me/devkevin/practice/match/listener/time/MatchDurationLimitListener.java new file mode 100644 index 0000000..97b8a60 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/listener/time/MatchDurationLimitListener.java @@ -0,0 +1,74 @@ +package me.devkevin.practice.match.listener.time; + +import lombok.Getter; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.match.event.impl.MatchStartEvent; +import me.devkevin.practice.util.TimeUtil; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +/** + * Copyright 13/06/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchDurationLimitListener implements Listener { + + @Getter private final Practice plugin = Practice.getInstance(); + + @Getter private final int DURATION_LIMIT_SECONDS = (int) TimeUnit.MINUTES.toSeconds(20); + + private static final String TIME_WARNING_MESSAGE = CC.RED + "The match will forcefully end in %s"; + private static final String TIME_EXCEEDED_MESSAGE = CC.RED + CC.BOLD + "Match time exceeded %s. Ending match..."; + + @EventHandler + public void onMatchCountdownEnd(MatchStartEvent event) { + Match match = event.getMatch(); + + new BukkitRunnable() { + + int secondsRemaining = DURATION_LIMIT_SECONDS; + + @Override + public void run() { + if (match.getMatchState() != MatchState.FIGHTING) { + cancel(); + return; + } + + // Very ugly to do it here, but I don't want to put another runnable per match + if (match.getKit().isSumo() || match.getKit().isBoxing()) { + match.getTeams().forEach(t -> t.getAlivePlayers().stream().map(Bukkit::getPlayer).filter(Objects::nonNull).forEach(p -> { + p.setHealth(20); + p.setFoodLevel(20); + p.setSaturation(20); + })); + } + + switch (secondsRemaining) { + case 120: + case 60: + case 30: + case 15: + case 10: + case 5: + match.broadcastMessage(String.format(TIME_WARNING_MESSAGE, TimeUtil.formatTime(secondsRemaining))); + case 0: + match.broadcastMessage(String.format(TIME_EXCEEDED_MESSAGE, TimeUtil.formatTime(DURATION_LIMIT_SECONDS))); + plugin.getMatchManager().removeMatch(match); + default: + break; + } + secondsRemaining--; + } + }.runTaskTimer(plugin, 20L, 20L); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/manager/MatchManager.java b/Practice/src/main/java/me/devkevin/practice/match/manager/MatchManager.java new file mode 100644 index 0000000..30f0ceb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/manager/MatchManager.java @@ -0,0 +1,493 @@ +package me.devkevin.practice.match.manager; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.hcf.kit.HCFKit; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.kit.PlayerKit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchRequest; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.match.event.impl.MatchEndEvent; +import me.devkevin.practice.match.event.impl.MatchStartEvent; +import me.devkevin.practice.match.menu.MatchDetailsMenu; +import me.devkevin.practice.match.task.RematchRunnable; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.PlayerUtil; +import me.devkevin.practice.util.TtlHashMap; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchManager { + + private final Practice plugin = Practice.getInstance(); + + private final Map> matchRequests = new TtlHashMap<>(TimeUnit.SECONDS, 30); + private final Map rematchUUIDs = new TtlHashMap<>(TimeUnit.SECONDS, 30); + private final Map rematchInventories = new TtlHashMap<>(TimeUnit.SECONDS, 30); + private final Map spectators = new ConcurrentHashMap<>(); + + private final Map matches = new HashMap<>(); + + private final Map playAgainKit = new TtlHashMap<>(TimeUnit.SECONDS, 30); + + public int getFighters() { + int i = 0; + for (Match match : this.matches.values()) { + for (MatchTeam matchTeam : match.getTeams()) { + i += matchTeam.getAlivePlayers().size(); + } + } + + return i; + } + + public int getFighters(String ladder, QueueType type) { + int i = 0; + for (Match match : this.matches.values()) { + if (match.getKit().getName().equalsIgnoreCase(ladder)) { + if (match.getType() == type) { + for (MatchTeam matchTeam : match.getTeams()) { + i += matchTeam.getAlivePlayers().size(); + } + } + } + } + + return i; + } + + public int getFighters(QueueType type) { + int i = 0; + for (Match match : this.matches.values()) { + if (match.getType() == type) { + for (MatchTeam team : match.getTeams()) { + i += team.getAlivePlayers().size(); + } + } + } + + return i; + } + + public Map getMatches() { + return matches; + } + + public void createMatchRequest(Player requester, Player requested, Arena arena, String kitName, boolean party) { + MatchRequest request = new MatchRequest(requester.getUniqueId(), requested.getUniqueId(), arena, kitName, party); + this.matchRequests.computeIfAbsent(requested.getUniqueId(), k -> new HashSet<>()).add(request); + } + + public MatchRequest getMatchRequest(UUID requester, UUID requested) { + Set requests = this.matchRequests.get(requested); + if (requests == null) { + return null; + } + + return requests.stream().filter(req -> req.getRequester().equals(requester)).findAny().orElse(null); + } + + public MatchRequest getMatchRequest(UUID requester, UUID requested, String kitName) { + Set requests = this.matchRequests.get(requested); + if (requests == null) { + return null; + } + + return requests.stream().filter(req -> req.getRequester().equals(requester) && req.getKitName().equals(kitName)).findAny().orElse(null); + } + + public Match getMatch(Profile profile) { + return this.matches.get(profile.getCurrentMatchID()); + } + + public Match getMatch(UUID uuid) { + Profile profile = this.plugin.getProfileManager().getProfileData(uuid); + return this.getMatch(profile); + } + + public void removeMatch(Match match) { + this.matches.remove(match.getMatchId()); + } + + public Match getMatchFromUUID(UUID uuid) { + return this.matches.get(uuid); + } + + public Match getSpectatingMatch(UUID uuid) { + return this.matches.get(this.spectators.get(uuid)); + } + + public void removeMatchRequests(UUID uuid) { + this.matchRequests.remove(uuid); + } + + public void createMatch(Match match) { + this.matches.put(match.getMatchId(), match); + this.plugin.getServer().getPluginManager().callEvent(new MatchStartEvent(match)); + } + + public void removeSpectator(Player player) { + Match match = this.matches.get(this.spectators.get(player.getUniqueId())); + + match.removeSpectator(player.getUniqueId()); + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (match.getTeams().size() > profile.getTeamID() && profile.getTeamID() >= 0) { + MatchTeam entityTeam = match.getTeams().get(profile.getTeamID()); + //Kill the player if they are in a redrover. + if (entityTeam != null) { + entityTeam.killPlayer(player.getUniqueId()); + } + } + + if (match.getMatchState() != MatchState.ENDING) { + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile != null) { + if (!coreProfile.hasStaff()) { + if (!match.haveSpectated(player.getUniqueId())) { + match.broadcastMessage(coreProfile.getGrant().getRank().getColor() + player.getName() + CC.RED + " is no longer spectating."); + match.addHaveSpectated(player.getUniqueId()); + } + } + } + } + + this.spectators.remove(player.getUniqueId()); + this.plugin.getProfileManager().sendToSpawn(player); + } + + public void giveKits(Player player, Kit kit) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Collection playerKits = profile.getPlayerKits(kit.getName()).values(); + + if (kit.getName().equalsIgnoreCase("HCF")) { + UUID uniqueId = player.getUniqueId(); + Party party = this.plugin.getPartyManager().getParty(uniqueId); + HCFKit clazz = new HCFKit(); + if (party.getBards().contains(uniqueId)) { + clazz.giveBardKit(player); + } else if (party.getArchers().contains(uniqueId)) { + clazz.giveArcherKit(player); + } else { + this.plugin.getKitManager().getKit("HCF").applyToPlayer(player); + } + + return; + } + + if (kit.isBoxing()) { + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile.hasDonor()) { + player.getInventory().setContents(this.plugin.getHotbarItem().getBoxingSwordDonor()); + } else { + player.getInventory().setContents(this.plugin.getHotbarItem().getBoxingSword()); + } + return; + } + + if (playerKits.size() == 0) { + kit.applyToPlayer(player); + } else { + player.getInventory().setItem(8, this.plugin.getHotbarItem().getDEFAULT_KIT()); + int slot = -1; + for (PlayerKit playerKit : playerKits) { + player.getInventory().setItem(++slot, + ItemUtil.createItem(Material.ENCHANTED_BOOK, ChatColor.YELLOW.toString() + ChatColor.BOLD + playerKit.getDisplayName())); + } + player.updateInventory(); + } + } + + public void removeFighter(Player player, Profile profile, boolean spectateDeath) { + Match match = this.matches.get(profile.getCurrentMatchID()); + + Player killer = player.getKiller(); + + if (player.isOnline() && killer != null) { + killer.hidePlayer(player); + } + + //PlayerUtil.playDeathAnimation(player); + + MatchTeam entityTeam = match.getTeams().get(profile.getTeamID()); + MatchTeam winningTeam = match.isFFA() ? entityTeam : match.getTeams().get(entityTeam.getTeamID() == 0 ? 1 : 0); + if (match.getMatchState() == MatchState.ENDING) { + return; + } + + if (killer != null) { + match.broadcastMessage(CC.GOLD + player.getName() + CC.YELLOW + " was slain by " + CC.GOLD + killer.getName() + CC.YELLOW + "!"); + } else { + match.broadcastMessage(CC.GOLD + player.getName() + CC.YELLOW + " has disconnected."); + } + + match.broadcastMessage(""); + + match.addSnapshot(player); + entityTeam.killPlayer(player.getUniqueId()); + + int remaining = entityTeam.getAlivePlayers().size(); + if (remaining != 0) { + Set items = new HashSet<>(); + for (ItemStack inventory : player.getInventory().getContents()) { + if (inventory != null && inventory.getType() != Material.AIR) { + items.add(player.getWorld().dropItemNaturally(player.getLocation(), inventory)); + } + } + for (ItemStack armor : player.getInventory().getArmorContents()) { + if (armor != null && armor.getType() != Material.AIR) { + items.add(player.getWorld().dropItemNaturally(player.getLocation(), armor)); + } + } + + plugin.getMatchManager().addDroppedItems(match, items); + } + + if (spectateDeath) { + this.addDeathSpectator(player, profile, match); + } + + if (match.isFFA() && remaining == 1 || match.isFFA() && remaining == 0 || remaining == 0) { + this.plugin.getServer().getPluginManager().callEvent(new MatchEndEvent(match, winningTeam, entityTeam)); + } + } + + private void addDeathSpectator(Player player, Profile profile, Match match) { + this.spectators.put(player.getUniqueId(), match.getMatchId()); + + profile.setState(ProfileState.SPECTATING); + + PlayerUtil.reset(player); + + //playerEp.getDataWatcher().watch(6, 0.0F); // Spawn a player in a STANDING position. This packet is broken as fuck, dont use + + match.addSpectator(player.getUniqueId()); + match.addRunnable(this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, () -> { + match.getTeams().forEach(team -> team.alivePlayers().forEach(member -> member.hidePlayer(player))); + + match.spectatorPlayers().forEach(member -> member.hidePlayer(player)); + + player.getActivePotionEffects().stream().map(PotionEffect::getType).forEach(player::removePotionEffect); + player.setWalkSpeed(0.2F); + player.setFlySpeed(0.4F); + player.setAllowFlight(true); + }, 20L)); + + if (match.isRedrover()) { + for (MatchTeam team : match.getTeams()) { + for (UUID alivePlayerUUID : team.getAlivePlayers()) { + Player alivePlayer = this.plugin.getServer().getPlayer(alivePlayerUUID); + + if (alivePlayer != null) { + player.showPlayer(alivePlayer); + } + } + } + } + + player.setWalkSpeed(0.0F); + player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 10000, -5)); + + if (match.isParty() || match.isFFA()) { + player.getInventory().clear(); + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> + player.getInventory().setContents(this.plugin.getHotbarItem().getSpecPartyItems()), 1L); + } + + player.updateInventory(); + } + + public void addDroppedItem(Match match, Item item) { + match.addEntityToRemove(item); + match.addRunnable(plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + match.removeEntityToRemove(item); + item.remove(); + }, 100L).getTaskId()); + } + + public void addDroppedItems(Match match, Set items) { + for (Item item : items) { + match.addEntityToRemove(item); + } + + match.addRunnable(plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + for (Item item : items) { + match.removeEntityToRemove(item); + item.remove(); + } + }, 100L).getTaskId()); + } + + public void addRedroverSpectator(Player player, Match match) { + this.spectators.put(player.getUniqueId(), match.getMatchId()); + + player.setAllowFlight(true); + player.setFlying(true); + player.getInventory().setContents(this.plugin.getHotbarItem().getSpecPartyItems()); + player.updateInventory(); + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + profile.setState(ProfileState.SPECTATING); + } + + public void addSpectator(Player player, Profile profile, Player target, Match targetMatch) { + this.spectators.put(player.getUniqueId(), targetMatch.getMatchId()); + + if (targetMatch.getMatchState() != MatchState.ENDING) { + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (!coreProfile.hasStaff()) { + if (!targetMatch.haveSpectated(player.getUniqueId())) { + + String spectatorMessage = coreProfile.getGrant().getRank().getColor() + player.getName() + ChatColor.YELLOW + " is spectating your match."; + + targetMatch.broadcastMessage(spectatorMessage); + } + } + } + + targetMatch.addSpectator(player.getUniqueId()); + + profile.setState(ProfileState.SPECTATING); + + player.teleport(target); + player.setAllowFlight(true); + player.setFlying(true); + + player.getInventory().clear(); + player.getInventory().setContents(this.plugin.getHotbarItem().getSpecItems()); + player.updateInventory(); + + plugin.getServer().getOnlinePlayers().forEach(online -> { + PlayerUtil.hideOrShowPlayer(player, online, true); + PlayerUtil.hideOrShowPlayer(online, player, true); + }); + + targetMatch.getTeams().forEach(team -> team.alivePlayers().forEach(player::showPlayer)); + } + + public void saveRematches(Match match) { + if (match.isParty() || match.isFFA()) { + return; + } + UUID playerOne = match.getTeams().get(0).getLeader(); + UUID playerTwo = match.getTeams().get(1).getLeader(); + + Profile dataOne = this.plugin.getProfileManager().getProfileData(playerOne); + Profile dataTwo = this.plugin.getProfileManager().getProfileData(playerTwo); + + if (dataOne != null) { + this.rematchUUIDs.put(playerOne, playerTwo); + MatchDetailsMenu snapshot = match.getSnapshot(playerTwo); + if (snapshot != null) { + dataOne.setLastSnapshot(snapshot); + this.rematchInventories.put(playerOne, snapshot.getSnapshotId()); + } + if (dataOne.getRematchID() > -1) { + this.plugin.getServer().getScheduler().cancelTask(dataOne.getRematchID()); + } + dataOne.setRematchID( + this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new RematchRunnable(playerOne), 20L * 30L)); + } + if (dataTwo != null) { + this.rematchUUIDs.put(playerTwo, playerOne); + MatchDetailsMenu snapshot = match.getSnapshot(playerOne); + if (snapshot != null) { + dataTwo.setLastSnapshot(snapshot); + this.rematchInventories.put(playerTwo, snapshot.getSnapshotId()); + } + if (dataTwo.getRematchID() > -1) { + this.plugin.getServer().getScheduler().cancelTask(dataTwo.getRematchID()); + } + dataTwo.setRematchID( + this.plugin.getServer().getScheduler().scheduleSyncDelayedTask(this.plugin, new RematchRunnable(playerTwo), 20L * 30L)); + } + } + + public void removeRematch(UUID uuid) { + this.rematchUUIDs.remove(uuid); + this.rematchInventories.remove(uuid); + } + + public UUID getRematcher(UUID uuid) { + return this.rematchUUIDs.get(uuid); + } + + public UUID getRematcherInventory(UUID uuid) { + return this.rematchInventories.get(uuid); + } + + public boolean isRematching(UUID uuid) { + return this.rematchUUIDs.containsKey(uuid); + } + + public void processRequeue(Player player, Match match) { + if (match.isParty() || match.isFFA() || match.isPartyMatch() || plugin.getTournamentManager().isInTournament(player.getUniqueId()) || plugin.getPartyManager().getParty(player.getUniqueId()) != null) { + return; + } + + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + this.playAgainKit.put(profile.getUuid(), match.getKit()); + + Clickable clickable = new Clickable(CC.YELLOW + CC.BOLD + "want to play again? " + CC.GREEN + "(Click here)", + CC.GRAY + "Click to play again", + "/playagain"); + + clickable.sendToPlayer(player); + + plugin.getServer().getScheduler().runTaskLaterAsynchronously(plugin, () -> { + if (player.isOnline()) { + player.getInventory().setItem(3, plugin.getHotbarItem().getPlayAgain()); + } + }, 10L); + + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { + if (profile.getState() == ProfileState.SPAWN && hasPlayAgainRequest(player.getUniqueId()) && plugin.getPartyManager().getParty(player.getUniqueId()) == null) { + player.getInventory().setItem(3, new ItemStack(Material.AIR)); + player.updateInventory(); + } + }, 20L * 30L); + } + + public void removePlayAgainRequest(UUID uuid) { + this.playAgainKit.remove(uuid); + } + + public Kit getPlayAgainRequestKit(UUID uuid) { + return this.playAgainKit.getOrDefault(uuid, null); + } + + public boolean hasPlayAgainRequest(UUID uuid) { + return this.playAgainKit.containsKey(uuid); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/matches/OngoingMatchesMenu.java b/Practice/src/main/java/me/devkevin/practice/match/matches/OngoingMatchesMenu.java new file mode 100644 index 0000000..f515243 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/matches/OngoingMatchesMenu.java @@ -0,0 +1,72 @@ +package me.devkevin.practice.match.matches; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.matches.buttons.OngoingMatchButton; +import me.devkevin.practice.match.matches.buttons.RefreshButton; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.pagination.PageButton; +import me.devkevin.practice.util.menu.pagination.PaginatedMenu; +import org.bukkit.entity.Player; + +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +import static me.devkevin.practice.util.PlayerUtil.PLACEHOLDER_ITEM; + +/** + * Copyright 14/04/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class OngoingMatchesMenu extends PaginatedMenu { + + @Override + public String getPrePaginatedTitle(Player player) { + return CC.translate("&8Current matches &7(" + this.plugin.getMatchManager().getMatches().values().size() + ")"); + } + + @Override + public Map getAllPagesButtons(Player player) { + Map buttons = new ConcurrentHashMap<>(); + + int slot = 0; + + for (Map.Entry entry : this.plugin.getMatchManager().getMatches().entrySet()) { + Match match = entry.getValue(); + if (!match.isParty() || !match.isPartyMatch() || !match.isFFA()) { + buttons.put(slot, new OngoingMatchButton(match)); + slot++; + } + } + + return buttons; + } + + @Override + public Map getGlobalButtons(Player player) { + Map buttons = new ConcurrentHashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + + buttons.put(4, new RefreshButton(this)); + buttons.put(8, new PageButton(1, this)); + + bottomTopButtons(false, buttons, PLACEHOLDER_ITEM); + + return buttons; + } + + @Override + public int getSize() { + return 9 * (3 + 1); + } + + @Override + public int getMaxItemsPerPage(Player player) { + return 9 * 3; + } + + +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/matches/buttons/OngoingMatchButton.java b/Practice/src/main/java/me/devkevin/practice/match/matches/buttons/OngoingMatchButton.java new file mode 100644 index 0000000..71c0500 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/matches/buttons/OngoingMatchButton.java @@ -0,0 +1,50 @@ +package me.devkevin.practice.match.matches.buttons; + +import club.inverted.chatcolor.CC; +import lombok.AllArgsConstructor; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 14/04/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class OngoingMatchButton extends Button { + private final Match match; + + @Override + public ItemStack getButtonItem(Player player) { + List lore = new ArrayList<>(); + + lore.add(CC.MENU_BAR); + lore.add("&a" + this.match.getType().getName()); + lore.add(""); + lore.add("&eKit -> &a" + this.match.getKit().getName()); + lore.add("&eArena -> &a" + this.match.getArena().getName()); + lore.add("&eDuration -> &a" + this.match.getDuration()); + lore.add("&eSpectators -> &a" + this.match.getSpectators().size()); + lore.add(""); + lore.add("&a» Click to spectate «"); + lore.add(CC.MENU_BAR); + + return new ItemBuilder(this.match.getKit().getIcon()) + .name("&a" + this.match.getTeams().get(0).getLeaderName() + " &7vs " + "&c" + this.match.getTeams().get(1).getLeaderName()) + .lore(lore) + .hideFlags() + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + player.performCommand("spec " + this.match.getTeams().get(0).getLeaderName()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/matches/buttons/RefreshButton.java b/Practice/src/main/java/me/devkevin/practice/match/matches/buttons/RefreshButton.java new file mode 100644 index 0000000..3b4012d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/matches/buttons/RefreshButton.java @@ -0,0 +1,38 @@ +package me.devkevin.practice.match.matches.buttons; + +import lombok.AllArgsConstructor; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.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; + +/** + * Copyright 14/04/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public class RefreshButton extends Button { + private final Menu menu; + + @Override + public ItemStack getButtonItem(Player player) { + return new ItemBuilder(Material.CARPET) + .name("&aRefresh") + .lore(Arrays.asList("", "&7Click here to update the fights!")) + .durability(5) + .hideFlags() + .build(); + } + + @Override + public void clicked(Player player, int slot, ClickType clickType, int hotbarButton) { + playNeutral(player); + this.menu.updateInventory(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/menu/MatchDetailSnapshot.java b/Practice/src/main/java/me/devkevin/practice/match/menu/MatchDetailSnapshot.java new file mode 100644 index 0000000..786202b --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/menu/MatchDetailSnapshot.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.match.menu; + +import me.devkevin.practice.Practice; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchDetailSnapshot { + + private final Practice plugin = Practice.getInstance(); + + private final Map snapshots = new HashMap<>(); + + public void addSnapshot(MatchDetailsMenu snapshot) { + this.snapshots.put(snapshot.getSnapshotId(), snapshot); + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, () -> MatchDetailSnapshot.this.removeSnapshot(snapshot.getSnapshotId()), 3200L); + } + + public void removeSnapshot(UUID snapshotId) { + MatchDetailsMenu snapshot = this.snapshots.get(snapshotId); + if (snapshot != null) { + this.snapshots.remove(snapshotId); + } + } + + public MatchDetailsMenu getSnapshot(UUID snapshotId) { + return this.snapshots.get(snapshotId); + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/menu/MatchDetailsMenu.java b/Practice/src/main/java/me/devkevin/practice/match/menu/MatchDetailsMenu.java new file mode 100644 index 0000000..294351c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/menu/MatchDetailsMenu.java @@ -0,0 +1,194 @@ +package me.devkevin.practice.match.menu; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.MathUtil; +import me.devkevin.practice.util.PlayerUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.apache.commons.lang.StringEscapeUtils; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.json.simple.JSONObject; + +import java.util.*; + +/** + * Copyright 07/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class MatchDetailsMenu { + + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI inventoryUI; + private final ItemStack[] inventory; + private final ItemStack[] armor; + + @Getter private final UUID snapshotId = UUID.randomUUID(); + + public MatchDetailsMenu(Player player, Match match) { + ItemStack[] contents = player.getInventory().getContents(); + ItemStack[] armor = player.getInventory().getArmorContents(); + + this.inventory = contents; + this.armor = armor; + + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + double health = player.getHealth(); + double food = player.getFoodLevel(); + + List potionEffectStrings = new ArrayList<>(); + + for (PotionEffect potionEffect : player.getActivePotionEffects()) { + String romanNumeral = MathUtil.convertToRomanNumeral(potionEffect.getAmplifier() + 1); + String effectName = PlayerUtil.toNiceString(potionEffect.getType().getName().toLowerCase()); + String duration = MathUtil.convertTicksToMinutes(potionEffect.getDuration()); + + effectName = effectName.replace('_', ' '); + effectName = effectName.substring(0, 1).toUpperCase() + effectName.substring(1); + + potionEffectStrings.add(CC.YELLOW + effectName + " " + romanNumeral + CC.GRAY + " (" + duration + ")"); + } + + this.inventoryUI = new InventoryUI("Inventory of " + player.getName(), true, 6); + + for (int i = 0; i < 9; i++) { + this.inventoryUI.setItem(i + 27, new InventoryUI.EmptyClickableItem(contents[i])); + this.inventoryUI.setItem(i + 18, new InventoryUI.EmptyClickableItem(contents[i + 27])); + this.inventoryUI.setItem(i + 9, new InventoryUI.EmptyClickableItem(contents[i + 18])); + this.inventoryUI.setItem(i, new InventoryUI.EmptyClickableItem(contents[i + 9])); + } + + boolean potionMatch = false; + boolean soupMatch = false; + + for (ItemStack item : match.getKit().getContents()) { + if (item == null) { + continue; + } + if (item.getType() == Material.MUSHROOM_SOUP) { + soupMatch = true; + break; + } else if (item.getType() == Material.POTION && item.getDurability() == (short) 16421) { + potionMatch = true; + break; + } + } + + if (potionMatch) { + int potCount = (int) Arrays.stream(contents).filter(Objects::nonNull).map(ItemStack::getDurability).filter(d -> d == 16421).count(); + + this.inventoryUI.setItem(49, new InventoryUI.EmptyClickableItem( + new ItemBuilder(Material.POTION) + .name(CC.YELLOW + "Health Potins: " + CC.GOLD + potCount) + .amount(potCount).durability(16421) + .lore(CC.YELLOW + "Potions Thrown: " + CC.GOLD + profile.getPotionsThrown()) + .lore(CC.YELLOW + "Missed Potions: " + CC.GOLD + profile.getPotionsMissed()) + .lore(CC.YELLOW + "Potions Wasted: " + CC.GOLD + profile.getWastedHP()) + .lore(CC.YELLOW + "Potion Accuracy: " + CC.GOLD + (profile.getPotionsMissed() > 0 ? (int) ((( 28.0 - (double) profile.getPotionsMissed()) / 28.0) * 100.0) + "%" : "100%")) + .build())); + + } else if (soupMatch) { + int soupCount = (int) Arrays.stream(contents).filter(Objects::nonNull).map(ItemStack::getType).filter(d -> d == Material.MUSHROOM_SOUP).count(); + + this.inventoryUI.setItem(49, new InventoryUI.EmptyClickableItem(ItemUtil.createItem( + Material.MUSHROOM_SOUP,CC.YELLOW + "Soups Left: " + CC.GOLD + soupCount, soupCount, (short) 16421))); + } + + final double roundedHealth = Math.round(health / 2.0 * 2.0) / 2.0; + + this.inventoryUI.setItem(45, + new InventoryUI.EmptyClickableItem(ItemUtil.createItem(Material.SKULL_ITEM, CC.YELLOW + "Health: " + CC.GOLD + roundedHealth + "/10.0 " + StringEscapeUtils.unescapeJava("\u2764"), (int) Math.round(health / 2.0D)))); + + final double roundedFood = Math.round(health / 2.0 * 2.0) / 2.0; + + this.inventoryUI.setItem(46, + new InventoryUI.EmptyClickableItem(ItemUtil.createItem(Material.COOKED_BEEF, CC.YELLOW + "Hunger: " + CC.GOLD + roundedFood + "/10.0", (int) Math.round(food / 2.0D)))); + + this.inventoryUI.setItem(47, + new InventoryUI.EmptyClickableItem(ItemUtil.reloreItem( + ItemUtil.createItem(Material.BREWING_STAND_ITEM, CC.YELLOW + "Potion Effects", potionEffectStrings.size()) + , potionEffectStrings.toArray(new String[]{})))); + + this.inventoryUI.setItem(48, new InventoryUI.EmptyClickableItem( + new ItemBuilder(Material.DIAMOND_SWORD).name(CC.YELLOW + "Statistics"). + lore(CC.YELLOW + "Longest Combo: " + CC.GOLD + profile.getLongestCombo() + " Hit" + (profile.getLongestCombo() > 1 ? "s" : "")). + lore(CC.YELLOW + "Total Hits: " + CC.GOLD + profile.getHits() + " Hit" + (profile.getHits() > 1 ? "s" : "")). + lore(CC.YELLOW + "Critical Hits: " + CC.GOLD + profile.getCriticalHits()). + lore(CC.YELLOW + "Blocked Hits: " + CC.GOLD + profile.getBlockedHits()) + .build())); + + if (!match.isParty()) { + this.inventoryUI.setItem(53, new InventoryUI.AbstractClickableItem( + ItemUtil.reloreItem(ItemUtil.createItem(Material.PAPER, CC.YELLOW + "Opponent's Inventory"), CC.GRAY + "See your opponent's inventory", CC.GRAY + "and combat details.")) { + @Override + public void onClick(InventoryClickEvent inventoryClickEvent) { + Player clicker = (Player) inventoryClickEvent.getWhoClicked(); + + final UUID uuid = plugin.getMatchManager().getRematcherInventory(player.getUniqueId()); + + if (uuid == null) { + clicker.sendMessage(CC.RED + "The inventory you're currently viewing has expired."); + clicker.closeInventory(); + return; + } + + clicker.performCommand("inventory " + uuid); + } + }); + } + + for (int i = 36; i < 40; i++) { + this.inventoryUI.setItem(i, new InventoryUI.EmptyClickableItem(armor[39 - i])); + } + } + + public JSONObject toJson() { + JSONObject object = new JSONObject(); + + JSONObject inventoryObject = new JSONObject(); + for (int i = 0; i < this.inventory.length; i++) { + inventoryObject.put(i, this.encodeItem(this.inventory[i])); + } + object.put("inventory", inventoryObject); + + JSONObject armourObject = new JSONObject(); + for (int i = 0; i < this.armor.length; i++) { + armourObject.put(i, this.encodeItem(this.armor[i])); + } + object.put("armour", armourObject); + + return object; + } + + private JSONObject encodeItem(ItemStack itemStack) { + if (itemStack == null || itemStack.getType() == Material.AIR) { + return null; + } + + JSONObject object = new JSONObject(); + object.put("material", itemStack.getType().name()); + object.put("durability", itemStack.getDurability()); + object.put("amount", itemStack.getAmount()); + + JSONObject enchants = new JSONObject(); + for (Enchantment enchantment : itemStack.getEnchantments().keySet()) { + enchants.put(enchantment.getName(), itemStack.getEnchantments().get(enchantment)); + } + object.put("enchants", enchants); + + return object; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/menu/command/InvCommand.java b/Practice/src/main/java/me/devkevin/practice/match/menu/command/InvCommand.java new file mode 100644 index 0000000..4d0eee1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/menu/command/InvCommand.java @@ -0,0 +1,47 @@ +package me.devkevin.practice.match.menu.command; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.menu.MatchDetailsMenu; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +import java.util.UUID; +import java.util.regex.Pattern; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class InvCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + private final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"); + + @Command(name = "inventory", inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + + if (args.length == 0) { + return; + } + + if (!args[0].matches(UUID_PATTERN.pattern())) { + player.sendMessage(PracticeLang.INV_NOT_FOUND); + return; + } + + MatchDetailsMenu menu = this.plugin.getMatchDetailSnapshot().getSnapshot(UUID.fromString(args[0])); + if (menu == null) { + player.sendMessage(PracticeLang.INV_NOT_FOUND); + } else { + player.openInventory(menu.getInventoryUI().getCurrentPage()); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/spec/SpectateCommand.java b/Practice/src/main/java/me/devkevin/practice/match/spec/SpectateCommand.java new file mode 100644 index 0000000..e42ed10 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/spec/SpectateCommand.java @@ -0,0 +1,110 @@ +package me.devkevin.practice.match.spec; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.events.lms.LMSEvent; +import me.devkevin.practice.events.sumo.SumoEvent; +import me.devkevin.practice.events.tntrun.TntRunEvent; +import me.devkevin.practice.events.tnttag.TNTTagEvent; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 10/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SpectateCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "spectate", aliases = "spec", inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 1) { + player.sendMessage(CC.RED + "/spectate "); + return; + } + me.devkevin.practice.profile.Profile profileData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(profileData.getUuid()); + + if (party != null || (profileData.getState() != ProfileState.SPAWN && profileData.getState() != ProfileState.SPECTATING)) { + player.sendMessage(CC.RED + "You can't execute that command in your current state."); + return; + } + + Player target = this.plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + me.devkevin.practice.profile.Profile targetData = this.plugin.getProfileManager().getProfileData(target.getUniqueId()); + + if (targetData.getState() == ProfileState.EVENT) { + PracticeEvent event = this.plugin.getEventManager().getEventPlaying(target); + + if(event == null) { + player.sendMessage(CC.RED + "That player is currently not in an event."); + return; + } + + if (event instanceof SumoEvent) { + player.performCommand("eventspectate Sumo"); + } else if(event instanceof TNTTagEvent) { + player.performCommand("eventspectate TNTTag"); + } else if(event instanceof TntRunEvent) { + player.performCommand("eventspectate TNTRun"); + } else if (event instanceof LMSEvent) { + player.performCommand("eventspectate LMS"); + } + return; + } + + if (targetData.getState() != ProfileState.FIGHTING) { + player.sendMessage(CC.RED + "That player is not fighting."); + return; + } + + Match targetMatch = this.plugin.getMatchManager().getMatch(targetData); + + if (!targetMatch.isParty()) { + if (!targetData.getOptions().isSpectators() && !player.hasPermission("practice.staff")) { + player.sendMessage(CC.RED + "That player has ignored spectators."); + return; + } + + MatchTeam team = targetMatch.getTeams().get(0); + MatchTeam team2 = targetMatch.getTeams().get(1); + + me.devkevin.practice.profile.Profile otherPlayerData = this.plugin.getProfileManager().getProfileData(team.getPlayers().get(0) == target.getUniqueId() ? team2.getPlayers().get(0) : team.getPlayers().get(0)); + + if (otherPlayerData == null && !otherPlayerData.getOptions().isSpectators() && !player.hasPermission("practice.staff")) { + player.sendMessage(CC.RED + "That player has ignored spectators."); + return; + } + } + if (profileData.getState() == ProfileState.SPECTATING) { + Match match = this.plugin.getMatchManager().getSpectatingMatch(player.getUniqueId()); + + if (match.equals(targetMatch)) { + player.sendMessage(CC.RED + "You are already spectating this player."); + return; + } + match.removeSpectator(player.getUniqueId()); + } + player.sendMessage(CC.GREEN + "You are spectating " + LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + CC.GREEN + "."); + this.plugin.getMatchManager().addSpectator(player, profileData, target, targetMatch); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/task/MatchLogicTask.java b/Practice/src/main/java/me/devkevin/practice/match/task/MatchLogicTask.java new file mode 100644 index 0000000..db816ad --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/task/MatchLogicTask.java @@ -0,0 +1,125 @@ +package me.devkevin.practice.match.task; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.chunk.manager.ChunkRestorationManager; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.block.BlockState; +import org.bukkit.entity.Entity; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 29/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MatchLogicTask extends BukkitRunnable { + + private final Practice plugin = Practice.getInstance(); + private Match match; + + public MatchLogicTask(Match match) { + this.match = match; + } + + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + @Override + public void run() { + switch (match.getMatchState()) { + case STARTING: + if (this.match.decrementCountdown() == 0) { + this.match.setMatchState(MatchState.FIGHTING); + this.match.broadcastWithSound(CC.GOLD + "The match has started!", Sound.FIREWORK_BLAST); + + if (this.match.getKit().isSumo()) { + match.broadcastMessage(""); + match.broadcastMessage(CC.YELLOW + CC.BOLD + "Sumo"); + match.broadcastMessage(CC.YELLOW + " Knock your opponents off the platform!"); + match.broadcastMessage(""); + return; + } + + if (this.match.getKit().isBoxing()) { + match.broadcastMessage(""); + match.broadcastMessage(CC.YELLOW + CC.BOLD + "Boxing"); + match.broadcastMessage(CC.YELLOW + " First to 100 hits wins!"); + match.broadcastMessage(""); + return; + } + + if (this.match.getKit().getName().equals("BuildUHC")) { + match.broadcastMessage(""); + match.broadcastMessage(CC.YELLOW + CC.BOLD + "Build UHC"); + match.broadcastMessage(CC.YELLOW + " Eliminate your opponents! (Diamond"); + match.broadcastMessage(CC.YELLOW + "Gear, Bow, Blocks, Gapples)"); + match.broadcastMessage(""); + return; + } + + if (this.match.getKit().getName().equals("NoDebuff")) { + match.broadcastMessage(""); + match.broadcastMessage(CC.YELLOW + CC.BOLD + "NoDebuff"); + match.broadcastMessage(CC.YELLOW + " Eliminate your opponents! (Diamond"); + match.broadcastMessage(CC.YELLOW + "Gear, Heal Potions)"); + match.broadcastMessage(""); + return; + } + + this.match.setStartTimestamp(System.currentTimeMillis()); + } else { + this.match.broadcastWithSound(CC.YELLOW + "The match starts in " + CC.GOLD + + this.match.getCountdown() + CC.YELLOW + " second(s)...", Sound.CLICK); + } + break; + case FIGHTING: + match.incrementDuration(); + break; + case ENDING: + if (this.match.decrementCountdown() == 0) { + this.plugin.getTournamentManager().removeTournamentMatch(this.match); + + this.match.getRunnables().forEach(id -> this.plugin.getServer().getScheduler().cancelTask(id)); + + this.match.getEntitiesToRemove().forEach(Entity::remove); + + this.match.getTeams().forEach(team -> team.alivePlayers().forEach(player -> Practice.getInstance().getProfileManager().sendToSpawn(player))); + + this.match.spectatorPlayers().forEach(this.plugin.getMatchManager()::removeSpectator); + + this.match.getPlacedBlockLocations().forEach(location -> location.getBlock().setType(Material.AIR)); + + this.match.getPlacedBlockLocations().forEach(location -> location.getBlock().setType(Material.AIR)); + + + BlockState blockState; + while ((blockState = this.match.getOriginalBlockChanges().pollLast()) != null) { + blockState.getLocation().getBlock().setType(blockState.getType()); + blockState.update(true, false); + } + + if (this.match.getKit().isBuild() || this.match.getKit().isSpleef()) { + ChunkRestorationManager.getIChunkRestoration().reset(match.getStandaloneArena()); + this.match.getArena().addAvailableArena(this.match.getStandaloneArena()); + this.plugin.getArenaManager().removeArenaMatchUUID(this.match.getStandaloneArena()); + } + + this.plugin.getMatchManager().removeMatch(this.match); + this.cancel(); + } + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/task/MatchResetRunnable.java b/Practice/src/main/java/me/devkevin/practice/match/task/MatchResetRunnable.java new file mode 100644 index 0000000..7ef1e4c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/task/MatchResetRunnable.java @@ -0,0 +1,55 @@ +package me.devkevin.practice.match.task; + +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.BlockState; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/01/2023 @ 15:48 + * MatchResetRunnable / me.devkevin.practice.match.task / Practice + */ +@RequiredArgsConstructor +public class MatchResetRunnable extends BukkitRunnable { + + private final Practice plugin = Practice.getInstance(); + private final Match match; + + @Override + public void run() { + int count = 0; + + if (this.match.getKit().isBuild()) { + for (Location location : this.match.getPlacedBlockLocations()) { + if (++count <= 15) { + location.getBlock().setType(Material.AIR); + this.match.removePlacedBlockLocation(location); + } else { + break; + } + } + } else { + for (BlockState blockState : this.match.getOriginalBlockChanges()) { + if (++count <= 15) { + blockState.setType(blockState.getType()); + blockState.update(); + blockState.update(true); + blockState.update(true, false); + this.match.removeOriginalBlockChange(blockState); + } else { + break; + } + } + } + + if (count < 15) { + this.match.getArena().addAvailableArena(this.match.getStandaloneArena()); + this.plugin.getArenaManager().removeArenaMatchUUID(this.match.getStandaloneArena()); + this.cancel(); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/task/NewRoundRunnable.java b/Practice/src/main/java/me/devkevin/practice/match/task/NewRoundRunnable.java new file mode 100644 index 0000000..3cca1c5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/task/NewRoundRunnable.java @@ -0,0 +1,52 @@ +package me.devkevin.practice.match.task; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import org.bukkit.entity.Player; +import org.bukkit.metadata.FixedMetadataValue; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 18/12/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class NewRoundRunnable extends BukkitRunnable { + private final Match match; + private final Player player; + private int ticks; + + public NewRoundRunnable(Match match, Player player) { + this.match = match; + this.player = player; + this.ticks = 4; + + this.runTaskTimer(Practice.getInstance(), 20L , 20L); + } + + @Override + public void run() { + this.ticks--; + + if (this.player == null) { + this.cancel(); + return; + } + + switch (this.ticks) { + case 3: + this.player.setAllowFlight(true); + this.player.setFlying(true); + this.player.setMetadata("e", new FixedMetadataValue(Practice.getInstance(), "")); + break; + case 2: + case 1: + this.player.sendMessage(CC.YELLOW + "You will respawn in " + CC.PINK + this.ticks + CC.YELLOW + " second" + (this.ticks == 1 ? "" : "s" + ".")); + break; + case 0: + //TODO: + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/task/RematchRunnable.java b/Practice/src/main/java/me/devkevin/practice/match/task/RematchRunnable.java new file mode 100644 index 0000000..ff9ceed --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/task/RematchRunnable.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.match.task; + +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import org.bukkit.entity.Player; + +import java.util.UUID; + +/** + * Copyright 01/12/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@RequiredArgsConstructor +public class RematchRunnable implements Runnable { + private final Practice plugin = Practice.getInstance(); + + private final UUID playerUUID; + + @Override + public void run() { + Player player = this.plugin.getServer().getPlayer(this.playerUUID); + + if (player != null) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile != null) { + if (profile.isInSpawn()) { + profile.setRematchID(-1); + } + } + this.plugin.getMatchManager().removeRematch(playerUUID); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/team/KillableTeam.java b/Practice/src/main/java/me/devkevin/practice/match/team/KillableTeam.java new file mode 100644 index 0000000..3f1eec1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/team/KillableTeam.java @@ -0,0 +1,75 @@ +package me.devkevin.practice.match.team; + +import lombok.Data; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Stream; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Data +public class KillableTeam { + + protected final Practice plugin = Practice.getInstance(); + + private final List players; + private final List alivePlayers = new ArrayList<>(); + private final String leaderName; + @Setter private UUID leader; + + public KillableTeam(UUID leader, List players) { + this.leader = leader; + this.leaderName = this.plugin.getServer().getPlayer(leader).getName(); + this.players = players; + this.alivePlayers.addAll(players); + } + + public void killPlayer(UUID playerUUID) { + this.alivePlayers.remove(playerUUID); + } + + public Stream alivePlayers() { + return this.alivePlayers.stream().map(this.plugin.getServer()::getPlayer).filter(Objects::nonNull); + } + + public Stream players() { + return this.players.stream().map(this.plugin.getServer()::getPlayer).filter(Objects::nonNull); + } + + public List getPlayersConverted() { + List newPlayerList = new ArrayList<>(); + + for (UUID uuid : this.players) { + if (Bukkit.getPlayer(uuid) != null) { + Player player = Bukkit.getPlayer(uuid); + + newPlayerList.add(player); + } + } + + return newPlayerList; + } + + public int onlinePlayers() { + int count = 0; + for (UUID uuid : players) { + Profile profile = this.plugin.getProfileManager().getProfileData(uuid); + + if (profile != null && !profile.isLeaving()) { + count++; + } + } + return count; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/PlayerTimer.java b/Practice/src/main/java/me/devkevin/practice/match/timer/PlayerTimer.java new file mode 100644 index 0000000..2590a74 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/PlayerTimer.java @@ -0,0 +1,123 @@ +package me.devkevin.practice.match.timer; + +import java.util.Map; +import java.util.Objects; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.timer.event.TimerClearEvent; +import me.devkevin.practice.match.timer.event.TimerExtendEvent; +import me.devkevin.practice.match.timer.event.TimerPauseEvent; +import me.devkevin.practice.match.timer.event.TimerStartEvent; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public abstract class PlayerTimer extends Timer { + + @Getter + protected final Map cooldowns = new ConcurrentHashMap<>(); + + public PlayerTimer(String name, long defaultCooldown) { + super(name, defaultCooldown); + } + + protected void handleExpiry(Player player, UUID playerUUID) { + this.cooldowns.remove(playerUUID); + } + + public TimerCooldown clearCooldown(UUID uuid) { + return this.clearCooldown(null, uuid); + } + + public TimerCooldown clearCooldown(Player player) { + Objects.requireNonNull(player); + return clearCooldown(player, player.getUniqueId()); + } + + public TimerCooldown clearCooldown(Player player, UUID playerUUID) { + TimerCooldown runnable = this.cooldowns.remove(playerUUID); + if (runnable != null) { + runnable.cancel(); + if (player == null) { + Practice.getInstance().getServer().getPluginManager().callEvent(new TimerClearEvent(playerUUID, this)); + } else { + Practice.getInstance().getServer().getPluginManager().callEvent(new TimerClearEvent(player, this)); + } + } + + return runnable; + } + + public boolean isPaused(Player player) { + return this.isPaused(player.getUniqueId()); + } + + public boolean isPaused(UUID playerUUID) { + TimerCooldown runnable = this.cooldowns.get(playerUUID); + return runnable != null && runnable.isPaused(); + } + + public void setPaused(UUID playerUUID, boolean paused) { + TimerCooldown runnable = this.cooldowns.get(playerUUID); + if (runnable != null && runnable.isPaused() != paused) { + TimerPauseEvent event = new TimerPauseEvent(playerUUID, this, paused); + Bukkit.getPluginManager().callEvent(event); + if (!event.isCancelled()) { + runnable.setPaused(paused); + } + } + } + + public long getRemaining(Player player) { + return this.getRemaining(player.getUniqueId()); + } + + public long getRemaining(UUID playerUUID) { + TimerCooldown runnable = this.cooldowns.get(playerUUID); + return runnable == null ? 0L : runnable.getRemaining(); + } + + public boolean setCooldown(Player player, UUID playerUUID) { + return this.setCooldown(player, playerUUID, this.defaultCooldown, false); + } + + public boolean setCooldown(Player player, UUID playerUUID, long duration, boolean overwrite) { + return this.setCooldown(player, playerUUID, duration, overwrite, null); + } + + public boolean setCooldown(Player player, UUID playerUUID, long duration, boolean overwrite, + Predicate currentCooldownPredicate) { + TimerCooldown runnable = duration > 0L ? this.cooldowns.get(playerUUID) : this.clearCooldown(player, playerUUID); + if (runnable != null) { + long remaining = runnable.getRemaining(); + if (!overwrite && remaining > 0L && duration <= remaining) { + return false; + } + + TimerExtendEvent event = new TimerExtendEvent(player, playerUUID, this, remaining, duration); + Practice.getInstance().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + + boolean flag = true; + if (currentCooldownPredicate != null) { + flag = currentCooldownPredicate.test(remaining); + } + + if (flag) { + runnable.setRemaining(duration); + } + + return flag; + } else { + Practice.getInstance().getServer().getPluginManager().callEvent(new TimerStartEvent(player, playerUUID, this, duration)); + runnable = new TimerCooldown(this, playerUUID, duration); + } + + this.cooldowns.put(playerUUID, runnable); + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/Timer.java b/Practice/src/main/java/me/devkevin/practice/match/timer/Timer.java new file mode 100644 index 0000000..e46321d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/Timer.java @@ -0,0 +1,17 @@ +package me.devkevin.practice.match.timer; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public abstract class Timer { + + @Getter + protected final String name; + @Getter + protected final long defaultCooldown; + + public final String getDisplayName() { + return this.name; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/TimerCooldown.java b/Practice/src/main/java/me/devkevin/practice/match/timer/TimerCooldown.java new file mode 100644 index 0000000..bdd3ae7 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/TimerCooldown.java @@ -0,0 +1,102 @@ +package me.devkevin.practice.match.timer; + +import java.util.UUID; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.timer.event.TimerExpireEvent; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +public class TimerCooldown { + + @Getter + private final Timer timer; + private final UUID owner; + private BukkitTask eventNotificationTask; + @Getter + private long expiryMillis; + + @Getter + @Setter(AccessLevel.PROTECTED) + private long pauseMillis; + + protected TimerCooldown(Timer timer, long duration) { + this.owner = null; + this.timer = timer; + this.setRemaining(duration); + } + + protected TimerCooldown(Timer timer, UUID playerUUID, long duration) { + this.timer = timer; + this.owner = playerUUID; + this.setRemaining(duration); + } + + public long getRemaining() { + return this.getRemaining(false); + } + + protected void setRemaining(long milliseconds) throws IllegalStateException { + if (milliseconds <= 0L) { + this.cancel(); + return; + } + + long expiryMillis = System.currentTimeMillis() + milliseconds; + if (expiryMillis != this.expiryMillis) { + this.expiryMillis = expiryMillis; + + if (this.eventNotificationTask != null) { + this.eventNotificationTask.cancel(); + } + + long ticks = milliseconds / 50L; + this.eventNotificationTask = new BukkitRunnable() { + @Override + public void run() { + if (TimerCooldown.this.timer instanceof PlayerTimer && owner != null) { + ((PlayerTimer) timer).handleExpiry( + Practice.getInstance().getServer().getPlayer(TimerCooldown.this.owner), TimerCooldown.this.owner); + } + + Practice.getInstance().getServer().getPluginManager().callEvent( + new TimerExpireEvent(TimerCooldown.this.owner, TimerCooldown.this.timer)); + } + }.runTaskLaterAsynchronously(JavaPlugin.getProvidingPlugin(this.getClass()), ticks); + } + } + + protected long getRemaining(boolean ignorePaused) { + if (!ignorePaused && this.pauseMillis != 0L) { + return this.pauseMillis; + } else { + return this.expiryMillis - System.currentTimeMillis(); + } + } + + protected boolean isPaused() { + return this.pauseMillis != 0L; + } + + public void setPaused(boolean paused) { + if (paused != this.isPaused()) { + if (paused) { + this.pauseMillis = this.getRemaining(true); + this.cancel(); + } else { + this.setRemaining(this.pauseMillis); + this.pauseMillis = 0L; + } + } + } + + protected void cancel() throws IllegalStateException { + if (this.eventNotificationTask != null) { + this.eventNotificationTask.cancel(); + this.eventNotificationTask = null; + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/TimerManager.java b/Practice/src/main/java/me/devkevin/practice/match/timer/TimerManager.java new file mode 100644 index 0000000..ecfcb97 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/TimerManager.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.match.timer; + +import java.util.LinkedHashSet; +import java.util.Set; +import lombok.Data; +import lombok.Getter; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; + +@Data +public class TimerManager implements Listener { + + @Getter + private final Set timers = new LinkedHashSet<>(); + + private final JavaPlugin plugin; + + public TimerManager(JavaPlugin plugin) { + this.plugin = plugin; + } + + public void registerTimer(Timer timer) { + this.timers.add(timer); + if (timer instanceof Listener) { + this.plugin.getServer().getPluginManager().registerEvents((Listener) timer, this.plugin); + } + } + + public void unregisterTimer(Timer timer) { + this.timers.remove(timer); + } + + public T getTimer(Class timerClass) { + for (Timer timer : this.timers) { + if (timer.getClass().equals(timerClass)) { + return (T) timer; + } + } + + return null; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerClearEvent.java b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerClearEvent.java new file mode 100644 index 0000000..0b62476 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerClearEvent.java @@ -0,0 +1,63 @@ +package me.devkevin.practice.match.timer.event; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +import me.devkevin.practice.Practice; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import me.devkevin.practice.match.timer.Timer; + +public class TimerClearEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + private final Optional userUUID; + private final Timer timer; + private Optional player; + + public TimerClearEvent(Timer timer) { + this.userUUID = Optional.empty(); + this.timer = timer; + } + + public TimerClearEvent(UUID userUUID, Timer timer) { + this.userUUID = Optional.of(userUUID); + this.timer = timer; + } + + public TimerClearEvent(Player player, Timer timer) { + Objects.requireNonNull(player); + + this.player = Optional.of(player); + this.userUUID = Optional.of(player.getUniqueId()); + this.timer = timer; + } + + public static HandlerList getHandlerList() { + return TimerClearEvent.HANDLERS; + } + + public Optional getPlayer() { + if (player == null) { + player = this.userUUID.isPresent() ? + Optional.of(Practice.getInstance().getServer().getPlayer(this.userUUID.get())) : Optional.empty(); + } + + return player; + } + + public Optional getUserUUID() { + return this.userUUID; + } + + public Timer getTimer() { + return this.timer; + } + + @Override + public HandlerList getHandlers() { + return TimerClearEvent.HANDLERS; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerExpireEvent.java b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerExpireEvent.java new file mode 100644 index 0000000..033b703 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerExpireEvent.java @@ -0,0 +1,65 @@ +package me.devkevin.practice.match.timer.event; + +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; + +import me.devkevin.practice.Practice; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import me.devkevin.practice.match.timer.Timer; + +public class TimerExpireEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + + private final Optional userUUID; + private final Timer timer; + + private Optional player; + + public TimerExpireEvent(Timer timer) { + this.userUUID = Optional.empty(); + this.timer = timer; + } + + public TimerExpireEvent(UUID userUUID, Timer timer) { + this.userUUID = Optional.ofNullable(userUUID); + this.timer = timer; + } + + public TimerExpireEvent(Player player, Timer timer) { + Objects.requireNonNull(player); + + this.player = Optional.of(player); + this.userUUID = Optional.of(player.getUniqueId()); + this.timer = timer; + } + + public static HandlerList getHandlerList() { + return TimerExpireEvent.HANDLERS; + } + + public Optional getPlayer() { + if (player == null) { + player = this.userUUID.isPresent() ? + Optional.of(Practice.getInstance().getServer().getPlayer(this.userUUID.get())) : Optional.empty(); + } + + return player; + } + + public Optional getUserUUID() { + return this.userUUID; + } + + public Timer getTimer() { + return this.timer; + } + + @Override + public HandlerList getHandlers() { + return TimerExpireEvent.HANDLERS; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerExtendEvent.java b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerExtendEvent.java new file mode 100644 index 0000000..bda4a27 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerExtendEvent.java @@ -0,0 +1,81 @@ +package me.devkevin.practice.match.timer.event; + +import java.util.Optional; +import java.util.UUID; +import javax.annotation.Nullable; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import me.devkevin.practice.match.timer.Timer; + +public class TimerExtendEvent extends Event implements Cancellable { + + private static final HandlerList HANDLERS = new HandlerList(); + private final Optional player; + private final Optional userUUID; + private final Timer timer; + private final long previousDuration; + private boolean cancelled; + private long newDuration; + + public TimerExtendEvent(Timer timer, long previousDuration, long newDuration) { + this.player = Optional.empty(); + this.userUUID = Optional.empty(); + this.timer = timer; + this.previousDuration = previousDuration; + this.newDuration = newDuration; + } + + public TimerExtendEvent(@Nullable Player player, UUID uniqueId, Timer timer, long previousDuration, + long newDuration) { + this.player = Optional.ofNullable(player); + this.userUUID = Optional.ofNullable(uniqueId); + this.timer = timer; + this.previousDuration = previousDuration; + this.newDuration = newDuration; + } + + public static HandlerList getHandlerList() { + return TimerExtendEvent.HANDLERS; + } + + public Optional getPlayer() { + return this.player; + } + + public Optional getUserUUID() { + return this.userUUID; + } + + public Timer getTimer() { + return this.timer; + } + + public long getPreviousDuration() { + return this.previousDuration; + } + + public long getNewDuration() { + return this.newDuration; + } + + public void setNewDuration(long newDuration) { + this.newDuration = newDuration; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public HandlerList getHandlers() { + return TimerExtendEvent.HANDLERS; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerPauseEvent.java b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerPauseEvent.java new file mode 100644 index 0000000..52ab19e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerPauseEvent.java @@ -0,0 +1,60 @@ +package me.devkevin.practice.match.timer.event; + +import java.util.Optional; +import java.util.UUID; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import me.devkevin.practice.match.timer.Timer; + +public class TimerPauseEvent extends Event implements Cancellable { + + private static final HandlerList HANDLERS = new HandlerList(); + private final boolean paused; + private final Optional userUUID; + private final Timer timer; + private boolean cancelled; + + public TimerPauseEvent(Timer timer, boolean paused) { + this.userUUID = Optional.empty(); + this.timer = timer; + this.paused = paused; + } + + public TimerPauseEvent(UUID userUUID, Timer timer, boolean paused) { + this.userUUID = Optional.ofNullable(userUUID); + this.timer = timer; + this.paused = paused; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + public Optional getUserUUID() { + return this.userUUID; + } + + public Timer getTimer() { + return this.timer; + } + + public boolean isPaused() { + return this.paused; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerStartEvent.java b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerStartEvent.java new file mode 100644 index 0000000..ab4dda0 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/event/TimerStartEvent.java @@ -0,0 +1,58 @@ +package me.devkevin.practice.match.timer.event; + +import java.util.Optional; +import java.util.UUID; +import javax.annotation.Nullable; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import me.devkevin.practice.match.timer.Timer; + +public class TimerStartEvent extends Event { + + private static final HandlerList HANDLERS = new HandlerList(); + + private final Optional player; + private final Optional userUUID; + private final Timer timer; + private final long duration; + + public TimerStartEvent(Timer timer, final long duration) { + this.player = Optional.empty(); + this.userUUID = Optional.empty(); + this.timer = timer; + this.duration = duration; + } + + public TimerStartEvent(@Nullable Player player, UUID uniqueId, Timer timer, long duration) { + this.player = Optional.ofNullable(player); + this.userUUID = Optional.ofNullable(uniqueId); + this.timer = timer; + this.duration = duration; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + public Optional getPlayer() { + return this.player; + } + + public Optional getUserUUID() { + return this.userUUID; + } + + public Timer getTimer() { + return this.timer; + } + + public long getDuration() { + return this.duration; + } + + @Override + public HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/timer/impl/EnderpearlTimer.java b/Practice/src/main/java/me/devkevin/practice/match/timer/impl/EnderpearlTimer.java new file mode 100644 index 0000000..39304fa --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/timer/impl/EnderpearlTimer.java @@ -0,0 +1,84 @@ +package me.devkevin.practice.match.timer.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.match.timer.PlayerTimer; +import org.apache.commons.lang3.time.DurationFormatUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.EnderPearl; +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.ProjectileLaunchEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerTeleportEvent; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class EnderpearlTimer extends PlayerTimer implements Listener { + + public EnderpearlTimer() { + super("Enderpearl", TimeUnit.SECONDS.toMillis(15)); + } + + @Override + protected void handleExpiry(Player player, UUID playerUUID) { + super.handleExpiry(player, playerUUID); + + if (player == null) { + return; + } + + player.sendMessage(ChatColor.GREEN + "Your enderpearl cooldown expired!"); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if ((event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR) || !event.hasItem()) { + return; + } + Player player = event.getPlayer(); + + if (event.getItem().getType() == Material.ENDER_PEARL) { + long cooldown = this.getRemaining(player); + if (cooldown > 0) { + event.setCancelled(true); + player.sendMessage(CC.RED + "Enderpearl cooldown" + CC.GRAY + ": " + CC.YELLOW + DurationFormatUtils.formatDurationWords(cooldown, true, true) + " seconds"); + player.updateInventory(); + } + } + } + + @EventHandler + public void onPearlLaunch(ProjectileLaunchEvent event) { + if (event.getEntity().getShooter() instanceof Player) { + if (event.getEntity() instanceof EnderPearl) { + Player player = (Player) event.getEntity().getShooter(); + this.setCooldown(player, player.getUniqueId()); + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerTeleportEvent(PlayerTeleportEvent event) { + if (event.getCause() != PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { + return; + } + Player player = event.getPlayer(); + + if (this.getRemaining(player) != 0) { + // Was the event cancelled? + if (event.isCancelled()) { + this.clearCooldown(player); + } + } + event.getTo().setX((double) event.getTo().getBlockX() + 0.5D); + event.getTo().setZ((double) event.getTo().getBlockZ() + 0.5D); + if (event.getTo().getBlock().getType() != Material.AIR) { + event.getTo().setY(event.getTo().getY() - (event.getTo().getY() - event.getTo().getBlockY())); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/vote/Vote.java b/Practice/src/main/java/me/devkevin/practice/match/vote/Vote.java new file mode 100644 index 0000000..a218d97 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/vote/Vote.java @@ -0,0 +1,27 @@ +package me.devkevin.practice.match.vote; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/01/2023 @ 16:35 + * vote / me.devkevin.practice.match / Practice + */ +@Getter +@RequiredArgsConstructor +public enum Vote { + ONE_STAR(CC.RED, 1), + TWO_STARS(CC.YELLOW, 2), + THREE_STARS(CC.YELLOW, 3), + FOUR_STARS(CC.YELLOW, 4), + FIVE_STARS(CC.GREEN, 5); + + private final String color; + private final int vote; + + public String getDisplayName() { + return this.color + "[" + this.vote + "\u272e]"; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/vote/VoteManager.java b/Practice/src/main/java/me/devkevin/practice/match/vote/VoteManager.java new file mode 100644 index 0000000..9f101c4 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/vote/VoteManager.java @@ -0,0 +1,86 @@ +package me.devkevin.practice.match.vote; + +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.ChatComponentBuilder; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.HoverEvent; +import net.minecraft.server.v1_8_R3.MinecraftServer; +import org.bson.Document; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/01/2023 @ 16:38 + * VoteManager / me.devkevin.practice.match.vote / Practice + */ +@Getter +@RequiredArgsConstructor +public class VoteManager { + private final Practice plugin; + private final List pendingVotes = new ArrayList<>(); + + public boolean hasVoted(Player player, Arena arena) { + if (Thread.currentThread() == MinecraftServer.getServer().primaryThread) { + return false; + } + if (arena == null) { + return false; + } + return this.plugin.getPracticeDatabase().getVotesCollection().find(Filters.and(Filters.eq("uuid", (Object)player.getUniqueId().toString()), Filters.eq("arena", (Object) arena.getName()))).first() != null; + } + + public void sendVoteMessage(Player player, Arena arena) { + if (this.hasVoted(player, arena)) { + return; + } + + ChatComponentBuilder builder = new ChatComponentBuilder(""); + builder.append(CC.AQUA + "Give us some feedback about "); + builder.append(CC.GOLD + arena.getName()); + builder.append(CC.PINK + " by clicking one of the stars: "); + + Arrays.stream(Vote.values()).forEach(rating -> builder.append(rating.getDisplayName() + " ") + .event(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/rate " + rating.name())) + .event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ChatComponentBuilder(CC.GREEN + "Click to rate " + rating.getDisplayName() + CC.GREEN + ".").create()))); + + player.sendMessage(builder.create()); + } + + public void attemptVote(Player player, Arena arena, Vote vote) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.getLastArenaPlayed() == null) { + return; + } + + if (!profile.getLastArenaPlayed().getName().equals(arena.getName())) { + player.sendMessage(CC.RED + "You can not vote for that arena."); + return; + } + + if (this.hasVoted(player, arena)) { + player.sendMessage(CC.RED + "You have already voted for that arena."); + return; + } + + if (this.pendingVotes.contains(player.getUniqueId())) { + return; + } + + this.pendingVotes.add(player.getUniqueId()); + this.plugin.getPracticeDatabase().getVotesCollection().insertOne(new Document("uuid", player.getUniqueId().toString()).append("arena", arena.getName()).append("vote", vote.name())); + player.sendMessage(CC.YELLOW + "You rated " + CC.GOLD + arena.getName() + CC.YELLOW + " with " + vote.getDisplayName() + CC.YELLOW + ". Thank you for your feedback."); + this.pendingVotes.remove(player.getUniqueId()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/vote/commands/ArenaStatsCommand.java b/Practice/src/main/java/me/devkevin/practice/match/vote/commands/ArenaStatsCommand.java new file mode 100644 index 0000000..7b90bea --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/vote/commands/ArenaStatsCommand.java @@ -0,0 +1,65 @@ +package me.devkevin.practice.match.vote.commands; + +import com.mongodb.client.MongoCursor; +import com.mongodb.client.model.Filters; +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.vote.Vote; +import me.devkevin.practice.util.TaskUtil; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bson.Document; +import org.bukkit.entity.Player; + +import java.util.HashMap; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/01/2023 @ 23:40 + * ArenaStatsCommand / me.devkevin.practice.match.vote.commands / Practice + */ +public class ArenaStatsCommand extends PracticeCommand { + @Override @Command(name = "arenastats", permission = Rank.ADMIN) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "/arenastats "); + return; + } + + Arena arena = getPlugin().getArenaManager().getArena(args[0]); + + if (arena == null) { + player.sendMessage(CC.RED + "/arenastats "); + return; + } + + TaskUtil.runAsync(() -> { + AtomicInteger total = new AtomicInteger(); + HashMap ratings = new HashMap<>(); + + try (MongoCursor it = getPlugin().getPracticeDatabase().getVotesCollection().find(Filters.eq("arena", (Object) arena.getName())).iterator()) { + it.forEachRemaining(document -> { + Vote rating = Vote.valueOf(document.getString("vote")); + ratings.computeIfAbsent(rating, i -> new AtomicInteger()).incrementAndGet(); + total.incrementAndGet(); + }); + } + + player.sendMessage(CC.GOLD + "Ratings for " + CC.YELLOW + arena.getName() + CC.GOLD + ":"); + player.sendMessage(CC.GRAY + "Total votes: " + CC.WHITE + total.get()); + + ratings.forEach((rating, number) -> { + double decimalPercent = (double) number.get() / (double) total.get(); + double percent = decimalPercent == 1.0 ? decimalPercent : (1.0 - decimalPercent) * 100.0; + double rounded = (double) Math.round(percent * 100.0) / 100.0; + player.sendMessage(rating.getDisplayName() + CC.GRAY + ": " + CC.WHITE + number.get() + CC.GOLD + " (" + rounded + "%)"); + }); + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/match/vote/commands/RateCommand.java b/Practice/src/main/java/me/devkevin/practice/match/vote/commands/RateCommand.java new file mode 100644 index 0000000..2427f29 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/match/vote/commands/RateCommand.java @@ -0,0 +1,44 @@ +package me.devkevin.practice.match.vote.commands; + +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.vote.Vote; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.TaskUtil; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 24/01/2023 @ 23:33 + * RateCommand / me.devkevin.practice.match.vote.commands / Practice + */ +public class RateCommand extends PracticeCommand { + @Override @Command(name = "rate") + public void onCommand(CommandArgs command) { + if (!(command.getSender() instanceof Player)) { + return; + } + + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length != 1) { + return; + } + + Profile profile = getPlugin().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.getLastArenaPlayed() == null) return; + + Vote vote; + try { + vote = Vote.valueOf(args[0]); + } + catch (Exception unused) { + return; + } + + TaskUtil.runAsync(() -> getPlugin().getVoteManager().attemptVote(player, profile.getLastArenaPlayed(), vote)); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/npc/NpcListener.java b/Practice/src/main/java/me/devkevin/practice/npc/NpcListener.java new file mode 100644 index 0000000..3ba2c95 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/npc/NpcListener.java @@ -0,0 +1,47 @@ +package me.devkevin.practice.npc; + +import club.inverted.chatcolor.CC; +import me.devkevin.npc.events.NPCInteractEvent; +import me.devkevin.npc.npcs.NPC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.matches.OngoingMatchesMenu; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +/** + * Copyright 28/11/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class NpcListener implements Listener { + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onInteractNPC(NPCInteractEvent event) { + Player player = event.getPlayer(); + NPC npc = event.getNpc(); + + switch (npc.getName()) { + case "Unranked": + player.openInventory(plugin.getQueueMenu().getUnrankedMenu().getCurrentPage()); + break; + case "Ranked": + player.openInventory(plugin.getQueueMenu().getRankedMenu().getCurrentPage()); + break; + case "Matches": + new OngoingMatchesMenu().openMenu(player); + break; + case "KitEditor": + break; + case "Store": + player.sendMessage(CC.GRAY + "Store: " + CC.RED + "https://store.zelta.cc"); + break; + case "Website": + player.sendMessage(CC.GRAY + "Website: " + CC.RED + "https://www.zelta.cc"); + break; + default: + break; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/options/ProfileOptions.java b/Practice/src/main/java/me/devkevin/practice/options/ProfileOptions.java new file mode 100644 index 0000000..a18bb1f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/options/ProfileOptions.java @@ -0,0 +1,60 @@ +package me.devkevin.practice.options; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.options.item.ProfileOptionsItem; +import me.devkevin.practice.options.item.ProfileOptionsItemState; +import me.devkevin.practice.util.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Accessors(chain = true) +public class ProfileOptions { + + @Getter @Setter private boolean duelRequests = true; + @Getter @Setter private boolean partyInvites = true; + @Getter @Setter private boolean spectators = true; + @Getter @Setter private boolean scoreboard = true; + @Getter @Setter private ProfileOptionsItemState time = ProfileOptionsItemState.DAY; + @Getter @Setter private ProfileOptionsItemState pingBased = ProfileOptionsItemState.NO_RANGE; + @Getter @Setter private boolean visibility = true; + + public Inventory getInventory() { + Inventory toReturn = Bukkit.createInventory(null, 54, CC.D_GRAY + "Settings"); + + int[] slots = new int[] {1, 2, 3, 5, 6, 7, 8, 9, 17, 18, 26, 27, 35, 36, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53}; + + toReturn.setItem(0, new ItemBuilder(Material.BED).name(CC.RED + "Back to General").build()); + + toReturn.setItem(4, + new ItemBuilder(Material.NETHER_STAR).name(CC.DARK_RED + "Settings") + .lore("") + .lore(CC.GRAY + "Change your settings as you want.") + .lore("") + .build()); + + toReturn.setItem(20, ProfileOptionsItem.DUEL_REQUESTS.getItem(duelRequests ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + toReturn.setItem(22, ProfileOptionsItem.PARTY_INVITES.getItem(partyInvites ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + toReturn.setItem(24, ProfileOptionsItem.ALLOW_SPECTATORS.getItem(spectators ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + toReturn.setItem(38, ProfileOptionsItem.TOGGLE_SCOREBOARD.getItem(scoreboard ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + toReturn.setItem(40, ProfileOptionsItem.TOGGLE_TIME.getItem(time)); + toReturn.setItem(42, ProfileOptionsItem.TOGGLE_PING.getItem(pingBased)); + + + toReturn.setItem(12, ProfileOptionsItem.TOGGLE_VISIBILITY.getItem(visibility ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + toReturn.setItem(14, new ItemBuilder(Material.BOOKSHELF).name(CC.DARK_RED + "General Settings").build()); + + for (int i : slots) { + toReturn.setItem(i, new ItemBuilder(Material.STAINED_GLASS_PANE).name(" ").durability(15).build()); + } + return toReturn; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/options/command/OptionsCommand.java b/Practice/src/main/java/me/devkevin/practice/options/command/OptionsCommand.java new file mode 100644 index 0000000..4713b8f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/options/command/OptionsCommand.java @@ -0,0 +1,23 @@ +package me.devkevin.practice.options.command; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class OptionsCommand extends PracticeCommand { + + @Command(name = "poptions", aliases = {"toggle"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + player.openInventory(profile.getOptions().getInventory()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/options/item/ProfileOptionsItem.java b/Practice/src/main/java/me/devkevin/practice/options/item/ProfileOptionsItem.java new file mode 100644 index 0000000..ad510ca --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/options/item/ProfileOptionsItem.java @@ -0,0 +1,148 @@ +package me.devkevin.practice.options.item; + +import lombok.AllArgsConstructor; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.util.ItemBuilder; +import org.apache.commons.lang3.StringEscapeUtils; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@AllArgsConstructor +public enum ProfileOptionsItem { + + DUEL_REQUESTS(new ItemBuilder(Material.DIAMOND_SWORD).name(CC.DARK_RED + "Duel Requests").lore(CC.GRAY + "Do you want to accept duel requests?").build()), + PARTY_INVITES(new ItemBuilder(Material.SKULL_ITEM).name(CC.DARK_RED + "Party Invites").lore(CC.GRAY + "Do you want to accept party invitations?").durability(3).build()), + TOGGLE_SCOREBOARD(new ItemBuilder(Material.PAINTING).name(CC.DARK_RED + "Toggle Scoreboard").lore("Toggle your scoreboard").build()), + ALLOW_SPECTATORS(new ItemBuilder(Material.DIAMOND_HELMET).name(CC.DARK_RED + "Allow Spectators").lore(CC.GRAY + "Allow players to spectate your matches?").build()), + TOGGLE_TIME(new ItemBuilder(Material.SLIME_BALL).name(CC.DARK_RED + "Toggle Time").lore(CC.GRAY + "Toggle between day, sunset & night").build()), + TOGGLE_PING(new ItemBuilder(Material.FLINT_AND_STEEL).name(CC.DARK_RED + "Toggle Ping Matchmaking").lore(CC.GRAY + "Toggle between -1, 25, 50, 75, 100 ping ranges").build()), + TOGGLE_VISIBILITY(new ItemBuilder(Material.WATCH).name(CC.DARK_RED + "Toggle Visibility").lore(CC.GRAY + "Toggle your visibility").build()); + + private final ItemStack item; + + public ItemStack getItem(ProfileOptionsItemState state) { + if (this == DUEL_REQUESTS || this == PARTY_INVITES || this == ALLOW_SPECTATORS || this == TOGGLE_VISIBILITY) { + List lore = new ArrayList<>(); + + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + lore.add(CC.GRAY + "Do you want to accept duel requests?"); + lore.add(""); + lore.add(" " + (state == ProfileOptionsItemState.ENABLED ? ChatColor.GREEN + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.ENABLED)); + lore.add(" " + (state == ProfileOptionsItemState.DISABLED ? ChatColor.RED + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.DISABLED)); + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + + return new ItemBuilder(item).lore(lore).build(); + } + + else if(this == TOGGLE_TIME) { + List lore = new ArrayList<>(); + + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + lore.add(CC.GRAY + "Toggle between day, sunset & night"); + lore.add(""); + lore.add(" " + (state == ProfileOptionsItemState.DAY ? ChatColor.YELLOW + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.DAY)); + lore.add(" " + (state == ProfileOptionsItemState.SUNSET ? ChatColor.GOLD + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.SUNSET)); + lore.add(" " + (state == ProfileOptionsItemState.NIGHT ? ChatColor.BLUE + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.NIGHT)); + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + + return new ItemBuilder(item).lore(lore).build(); + } + + else if(this == TOGGLE_SCOREBOARD) { + List lore = new ArrayList<>(); + + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + lore.add(CC.GRAY + "Toggle your scoreboard"); + lore.add(""); + lore.add(" " + (state == ProfileOptionsItemState.ENABLED ? ChatColor.GREEN + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.ENABLED)); + lore.add(" " + (state == ProfileOptionsItemState.DISABLED ? ChatColor.RED + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.DISABLED)); + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + + return new ItemBuilder(item).lore(lore).build(); + } + + else if(this == TOGGLE_PING) { + List lore = new ArrayList<>(); + + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + lore.add(" " + (state == ProfileOptionsItemState.NO_RANGE ? ChatColor.RED + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.NO_RANGE)); + lore.add(" " + (state == ProfileOptionsItemState.RANGE_25 ? ChatColor.YELLOW + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.RANGE_25)); + lore.add(" " + (state == ProfileOptionsItemState.RANGE_50 ? ChatColor.YELLOW + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.RANGE_50)); + lore.add(" " + (state == ProfileOptionsItemState.RANGE_75 ? ChatColor.YELLOW + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.RANGE_75)); + lore.add(" " + (state == ProfileOptionsItemState.RANGE_100 ? ChatColor.YELLOW + StringEscapeUtils.unescapeHtml4("►") + " " : " ") + ChatColor.GRAY + getOptionDescription(ProfileOptionsItemState.RANGE_100)); + lore.add(ChatColor.DARK_GRAY.toString() + ChatColor.STRIKETHROUGH + "------------------------"); + + return new ItemBuilder(item).lore(lore).build(); + } + + return getItem(ProfileOptionsItemState.DISABLED); + } + + public String getOptionDescription(ProfileOptionsItemState state) { + if (this == DUEL_REQUESTS || this == PARTY_INVITES || this == ALLOW_SPECTATORS || this == TOGGLE_VISIBILITY) { + + if (state == ProfileOptionsItemState.ENABLED) { + return "Enable"; + } else if (state == ProfileOptionsItemState.DISABLED) { + return "Disable"; + } + } + + else if(this == TOGGLE_TIME) { + if (state == ProfileOptionsItemState.DAY) { + return "Day"; + } else if (state == ProfileOptionsItemState.SUNSET) { + return "Sunset"; + } else if (state == ProfileOptionsItemState.NIGHT) { + return "Night"; + } + } + + else if(this == TOGGLE_SCOREBOARD) { + if (state == ProfileOptionsItemState.ENABLED) { + return "Enable"; + } else if (state == ProfileOptionsItemState.SHOW_PING) { + return "Show Ping"; + } else if (state == ProfileOptionsItemState.DISABLED) { + return "Disable"; + } + } + + else if(this == TOGGLE_PING) { + if (state == ProfileOptionsItemState.NO_RANGE) { + return "No Ping Range"; + } else if (state == ProfileOptionsItemState.RANGE_25) { + return "25ms Range"; + } else if (state == ProfileOptionsItemState.RANGE_50) { + return "50ms Range"; + } else if (state == ProfileOptionsItemState.RANGE_75) { + return "75ms Range"; + } else if (state == ProfileOptionsItemState.RANGE_100) { + return "100ms Range"; + } + } + + + return getOptionDescription(ProfileOptionsItemState.DISABLED); + } + + public static ProfileOptionsItem fromItem(ItemStack itemStack) { + for (ProfileOptionsItem item : values()) { + for (ProfileOptionsItemState state : ProfileOptionsItemState.values()) { + if (item.getItem(state).isSimilar(itemStack)) { + return item; + } + } + } + return null; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/options/item/ProfileOptionsItemState.java b/Practice/src/main/java/me/devkevin/practice/options/item/ProfileOptionsItemState.java new file mode 100644 index 0000000..3d9cd59 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/options/item/ProfileOptionsItemState.java @@ -0,0 +1,21 @@ +package me.devkevin.practice.options.item; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public enum ProfileOptionsItemState { + + ENABLED, + DISABLED, + SHOW_PING, + DAY, + SUNSET, + NIGHT, + NO_RANGE, + RANGE_25, + RANGE_50, + RANGE_75, + RANGE_100 +} diff --git a/Practice/src/main/java/me/devkevin/practice/options/listener/ProfileOptionsListeners.java b/Practice/src/main/java/me/devkevin/practice/options/listener/ProfileOptionsListeners.java new file mode 100644 index 0000000..4a382c6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/options/listener/ProfileOptionsListeners.java @@ -0,0 +1,172 @@ +package me.devkevin.practice.options.listener; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.options.item.ProfileOptionsItem; +import me.devkevin.practice.options.item.ProfileOptionsItemState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.Arrays; + +/** + * Copyright 11/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ProfileOptionsListeners implements Listener { + + @EventHandler + public void onInventoryInteractEvent(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + CoreProfile playerData = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + Inventory inventory = event.getInventory(); + ItemStack itemStack = event.getCurrentItem(); + + if (itemStack != null && itemStack.getType() != Material.AIR) { + Inventory options = profile.getOptions().getInventory(); + if (inventory.getTitle().equals(options.getTitle()) && Arrays.equals(inventory.getContents(), options.getContents())) { + event.setCancelled(true); + ProfileOptionsItem item = ProfileOptionsItem.fromItem(itemStack); + + if (itemStack.getType() == Material.BOOKSHELF) { + event.setCancelled(true); + player.performCommand("settings"); + System.out.println("TEST"); + return; + } + + if (itemStack.getType() == Material.BED) { + event.setCancelled(true); + player.openInventory(Practice.getInstance().getGeneralSettingMenu().getGeneralMenu().getCurrentPage()); + return; + } + + if (item != null) { + if (item == ProfileOptionsItem.DUEL_REQUESTS) { + profile.getOptions().setDuelRequests(!profile.getOptions().isDuelRequests()); + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().isDuelRequests() ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + } else if (item == ProfileOptionsItem.PARTY_INVITES) { + profile.getOptions().setPartyInvites(!profile.getOptions().isPartyInvites()); + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().isPartyInvites() ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + } else if (item == ProfileOptionsItem.TOGGLE_SCOREBOARD) { + profile.getOptions().setScoreboard(!profile.getOptions().isScoreboard()); + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().isScoreboard() ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + } else if (item == ProfileOptionsItem.ALLOW_SPECTATORS) { + + if (!player.hasPermission("practice.donors.*")) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot toggle spectators with " + playerData.getGrant().getRank().getColor() + playerData.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://udrop.buycraft.net/."); + player.sendMessage(""); + return; + } + + profile.getOptions().setSpectators(!profile.getOptions().isSpectators()); + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().isSpectators() ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + + } else if (item == ProfileOptionsItem.TOGGLE_TIME) { + + if (profile.getOptions().getTime() == ProfileOptionsItemState.DAY) { + profile.getOptions().setTime(ProfileOptionsItemState.SUNSET); + player.performCommand("sunset"); + } + else if(profile.getOptions().getTime() == ProfileOptionsItemState.SUNSET) { + profile.getOptions().setTime(ProfileOptionsItemState.NIGHT); + player.performCommand("night"); + } + + else if (profile.getOptions().getTime() == ProfileOptionsItemState.NIGHT) { + profile.getOptions().setTime(ProfileOptionsItemState.DAY); + player.performCommand("day"); + } + + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().getTime())); + } else if (itemStack.getType() != Material.STAINED_GLASS_PANE) { + event.setCancelled(true); + } else if (item == ProfileOptionsItem.TOGGLE_VISIBILITY) { + + if (!player.hasPermission("practice.donors.*")) { + player.sendMessage(CC.RED + "You do not have permission to use that command."); + return; + } + + if (profile.getState() != ProfileState.SPAWN) { + player.sendMessage(CC.RED + "Cannot execute this command in your current state."); + return; + } + + profile.getOptions().setVisibility(!profile.getOptions().isVisibility()); + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().isVisibility() ? ProfileOptionsItemState.ENABLED : ProfileOptionsItemState.DISABLED)); + + Bukkit.getServer().getOnlinePlayers().forEach(p -> { + + boolean playerSeen = profile.getOptions().isVisibility() && player.hasPermission("practice.donors.*") && Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()).getState() == ProfileState.SPAWN; + boolean pSeen = profile.getOptions().isVisibility() && player.hasPermission("practice.donors.*") && Practice.getInstance().getProfileManager().getProfileData(p.getUniqueId()).getState() == ProfileState.SPAWN; + + if(playerSeen) { + p.showPlayer(player); + } else { + p.hidePlayer(player); + } + + if(pSeen) { + player.showPlayer(p); + } else { + player.hidePlayer(p); + } + }); + + player.sendMessage(CC.YELLOW + "You have toggled the visibility."); + } else if (item == ProfileOptionsItem.TOGGLE_PING) { + + if (!player.hasPermission("practice.donors.emerald")) { + player.sendMessage(CC.RED + "This option requires Void Emerald or up."); + player.closeInventory(); + return; + } + + if (profile.getOptions().getPingBased() == ProfileOptionsItemState.NO_RANGE) { + profile.getOptions().setPingBased(ProfileOptionsItemState.RANGE_25); + profile.setPingRange(25); + } + else if (profile.getOptions().getPingBased() == ProfileOptionsItemState.RANGE_25) { + profile.getOptions().setPingBased(ProfileOptionsItemState.RANGE_50); + profile.setPingRange(50); + } + + else if (profile.getOptions().getPingBased() == ProfileOptionsItemState.RANGE_50) { + profile.getOptions().setPingBased(ProfileOptionsItemState.RANGE_75); + profile.setPingRange(75); + } + + else if (profile.getOptions().getPingBased() == ProfileOptionsItemState.RANGE_75) { + profile.getOptions().setPingBased(ProfileOptionsItemState.RANGE_100); + profile.setPingRange(100); + } + + else if (profile.getOptions().getPingBased() == ProfileOptionsItemState.RANGE_100) { + profile.getOptions().setPingBased(ProfileOptionsItemState.NO_RANGE); + profile.setPingRange(-1); + } + + inventory.setItem(event.getRawSlot(), item.getItem(profile.getOptions().getPingBased())); + } + } + } + } + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/PanelCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/PanelCommand.java new file mode 100644 index 0000000..8839505 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/PanelCommand.java @@ -0,0 +1,9 @@ +package me.devkevin.practice.panel.commands; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PanelCommand { +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/DebugBlockedCommands.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/DebugBlockedCommands.java new file mode 100644 index 0000000..d0e6ec4 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/DebugBlockedCommands.java @@ -0,0 +1,26 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +import java.util.Arrays; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DebugBlockedCommands extends PracticeCommand { + + @Override @Command(name = "debugblocked", permission = Rank.ADMIN) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + player.sendMessage(CC.translate("&7" + Arrays.toString(PracticeLang.blockedCommands))); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceChunkSaveCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceChunkSaveCommand.java new file mode 100644 index 0000000..7f08217 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceChunkSaveCommand.java @@ -0,0 +1,43 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ForceChunkSaveCommand extends PracticeCommand { + + @Override @Command(name = "forcechunksave", permission = Rank.ADMIN, usage = "&cUsage: /forcechunksave ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 2) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Arena arena = getPlugin().getArenaManager().getArena(args[0]); + int copyNumber = Integer.parseInt(args[1]); + + if (arena != null) { + if (arena.getStandaloneArenas().get(copyNumber) == null) { + player.sendMessage(CC.translate("&cThat copy doesn't exist.")); + return; + } + + //getPlugin().getChunkRestaurationManager().copy(arena.getStandaloneArenas().get(copyNumber)); + player.sendMessage(CC.translate("&aSuccessfully saved standalone arena chunks for " + arena.getName() + " #" + copyNumber + ".")); + } else { + player.sendMessage(CC.translate("That arena doesn't exist.")); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceGlobalEloUpdateCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceGlobalEloUpdateCommand.java new file mode 100644 index 0000000..c0673b1 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceGlobalEloUpdateCommand.java @@ -0,0 +1,23 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ForceGlobalEloUpdateCommand extends PracticeCommand { + + @Override @Command(name = "forceglobalrefresh", permission = Rank.ADMIN) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + player.sendMessage(CC.translate("&aForce global refresh has been refreshed correctly")); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceQueueCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceQueueCommand.java new file mode 100644 index 0000000..5350fc6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/ForceQueueCommand.java @@ -0,0 +1,54 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ForceQueueCommand extends PracticeCommand { + + @Override @Command(name = "forcequeue", permission = Rank.ADMIN, usage = "&cUsage: /forcequeue ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 2) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + Profile profile = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + if (profile == null) { + player.sendMessage(CC.translate("&cThere is no data stored for that player.")); + return; + } + + Kit kit = getPlugin().getKitManager().getKit(args[1]); + if (kit == null) { + player.sendMessage(CC.translate("&cThat kit does not exist.")); + return; + } + + getPlugin().getQueueMenu().addToQueue(target, profile, kit, QueueType.UN_RANKED); + player.sendMessage(CC.translate("&aYou have forcefully added " + target.getName() + " into the " + kit.getName() + " queue.")); + target.sendMessage(CC.translate("&7&oYou have been forcefully added into the " + kit.getName() + " queue by " + player.getName())); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GlobalEloDebugCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GlobalEloDebugCommand.java new file mode 100644 index 0000000..addcb80 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GlobalEloDebugCommand.java @@ -0,0 +1,49 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class GlobalEloDebugCommand extends PracticeCommand { + + @Override @Command(name = "elodebug", permission = Rank.ADMIN, usage = "&cUsage: /elodebug ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 1) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]); + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + Profile profileTarget = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + AtomicInteger eloValue = new AtomicInteger(0); + + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&aRanked kits: " + getPlugin().getKitManager().getRankedKits().size())); + player.sendMessage(CC.translate("&agetGlobalElo(): " + profileTarget.getGlobalElo())); + player.sendMessage(CC.translate("&aTotal getGlobalElo Sum: " + eloValue.get())); + player.sendMessage(CC.translate("&aCalculated getGlobalElo(): " + (eloValue.get() / getPlugin().getKitManager().getRankedKits().size()))); + player.sendMessage(CC.CHAT_BAR); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GlobalQueueDebugCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GlobalQueueDebugCommand.java new file mode 100644 index 0000000..8f4c5bb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GlobalQueueDebugCommand.java @@ -0,0 +1,41 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class GlobalQueueDebugCommand extends PracticeCommand { + + @Override @Command(name = "globalqueuedebug", permission = Rank.ADMIN, usage = "&cUsage: /globalqueuedebug ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length < 1) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Kit kit = getPlugin().getKitManager().getKit(args[0]); + if (kit == null) { + player.sendMessage(CC.translate("&cThat kit does not exist.")); + return; + } + + getPlugin().getProfileManager().getAllData().forEach(profile -> { + getPlugin().getQueueMenu().addToQueue(Bukkit.getPlayer(profile.getUuid()), profile, kit, QueueType.UN_RANKED); + }); + player.sendMessage(CC.translate("&aYou have forcefully added " + Bukkit.getOnlinePlayers().size() + " players into the " + kit.getName() + " queue.")); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GotoEventCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GotoEventCommand.java new file mode 100644 index 0000000..fdfeb6f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/GotoEventCommand.java @@ -0,0 +1,27 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class GotoEventCommand extends PracticeCommand { + + @Override @Command(name = "gotoevent", aliases = {"eventsworld", "eventworld", "tpevent"}, permission = Rank.ADMIN, usage = "&cUsage: /gotoevent") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + Location eventWorld = Bukkit.getWorld("event").getSpawnLocation(); + player.teleport(eventWorld); + player.sendMessage(CC.translate("&aYou have teleported to the events world.")); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/PartyDebugCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/PartyDebugCommand.java new file mode 100644 index 0000000..a029042 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/PartyDebugCommand.java @@ -0,0 +1,62 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyDebugCommand extends PracticeCommand { + + @Override @Command(name = "partydebug", permission = Rank.ADMIN, usage = "&cUsage: /partydebug ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if (args.length == 1) { + if (target != null) { + Profile profile = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + + if (!profile.isInParty()) { + player.sendMessage(CC.translate("&c" + target.getName() + " is not in a Party.")); + return; + } + + Party party = getPlugin().getPartyManager().getParty(target.getUniqueId()); + + final List partyMembers = new ArrayList<>(); + party.getMembers().forEach(mem -> partyMembers.add(Bukkit.getPlayer(mem).getName())); + + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&6&lParty Debug")); + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate(" &e&l&fLeader: &f" + Bukkit.getPlayer(party.getLeader()).getName())); + player.sendMessage(CC.translate(" &e&l&fState: " + (party.isOpen() ? "&apublic" : "&cprivate"))); + player.sendMessage(CC.translate(" &e&l&fSize: &f" + party.getMembers().size() + "&7/&f" + party.getLimit())); + player.sendMessage(CC.translate(" &e&l&fMembers: &f" + partyMembers)); + + player.sendMessage(CC.CHAT_BAR); + } else { + player.sendMessage(CC.translate("&cPlayer not found.")); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/PlayerStateDebugCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/PlayerStateDebugCommand.java new file mode 100644 index 0000000..9096080 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/PlayerStateDebugCommand.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PlayerStateDebugCommand extends PracticeCommand { + + @Override @Command(name = "playerstatedebug", aliases = {"pdebug", "playerstate"}, permission = Rank.ADMIN, usage = "&cUsage: /pdebug ") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if (args.length == 1) { + if (target != null) { + Profile profile = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate("&6&lPlayer State Debug")); + player.sendMessage(CC.CHAT_BAR); + player.sendMessage(CC.translate(" &6&l&fName: &f" + target.getName())); + player.sendMessage(CC.translate(" &6&l&fState: &f" + profile.getState())); + player.sendMessage(CC.translate(" &6&l&fWorld: &f" + target.getWorld().getName())); + player.sendMessage(CC.translate(" &6&l&fisFollowing: &f" + profile.isFollowing())); + player.sendMessage(CC.translate(" &6&l&fisSpectating: &f" + profile.isSpectating())); + player.sendMessage(CC.translate(" &6&l&fLocation:")); + player.sendMessage(CC.translate(" &3 &fX &f" + Math.round(target.getLocation().getX()))); + player.sendMessage(CC.translate(" &3 &fY &f" + Math.round(target.getLocation().getY()))); + player.sendMessage(CC.translate(" &3 &fZ &f" + Math.round(target.getLocation().getZ()))); + player.sendMessage(CC.translate(" ")); + if (!profile.getCachedPlayer().isEmpty()) { + player.sendMessage(CC.translate(" &6&l&fCached Player: &f" + profile.getCachedPlayer().get(target).getName())); + } else { + player.sendMessage(CC.translate(" &6&l&fCached Player: &f" + profile.getCachedPlayer().get(target))); + } + player.sendMessage(CC.translate(" &6&l&fCachePlayerMap values: &f" + profile.getCachedPlayer().values())); + player.sendMessage(CC.CHAT_BAR); + } else { + player.sendMessage(CC.translate("&cPlayer not found.")); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/SafeStopCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/SafeStopCommand.java new file mode 100644 index 0000000..eface93 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/SafeStopCommand.java @@ -0,0 +1,121 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SafeStopCommand extends PracticeCommand { + + @Override @Command(name = "safestop", permission = Rank.DEVELOPER, usage = "&cUsage: /safeStop") + public void onCommand(CommandArgs command) { + Player sender = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + sender.sendMessage(CC.CHAT_BAR); + sender.sendMessage(CC.translate("&cYou need to confirm to make this.")); + sender.sendMessage(""); + sender.sendMessage(CC.translate("&cThis command is so powerful (ta' potente), so watch out.")); + sender.sendMessage(""); + sender.sendMessage(CC.translate("&cThis command will stop all queues (players will be not")); + sender.sendMessage(CC.translate("&cable to join into a queue), all matchs will be")); + sender.sendMessage(CC.translate("&ccancelled and players will be sent to lobby.")); + sender.sendMessage(""); + sender.sendMessage(CC.translate("&cIf really wanna make this, use /safeStop confirm")); + sender.sendMessage(CC.CHAT_BAR); + return; + } + + if (args[0].equalsIgnoreCase("confirm")) { + getPlugin().setRestarting(true); + Thread thread = new Thread(() -> { + Bukkit.getOnlinePlayers().forEach(target -> { + + Profile profile = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + + if (profile == null) { + sender.sendMessage(CC.translate("&cPlayer not found!")); + } else { + if (profile.isFighting()) { + new BukkitRunnable() { + @Override + public void run() { + Match match = getPlugin().getMatchManager().getMatchFromUUID(profile.getCurrentMatchID()); + match.setMatchState(MatchState.ENDING); + match.getTeams().forEach(team -> team.alivePlayers().forEach(player -> getPlugin().getProfileManager().sendToSpawn(player))); + match.spectatorPlayers().forEach(getPlugin().getMatchManager()::removeSpectator); + getPlugin().getMatchManager().removeMatch(match); + sender.sendMessage(CC.translate("&aSuccessfully cancelled &6" + target.getName() + "'s &amatch.")); + + match.broadcastMessage(CC.translate("&7&m------------------------------------------------")); + match.broadcastMessage(CC.translate("&c&lMatch Cancelled!")); + match.broadcastMessage(CC.translate("&f ❖ Cancelled by: &c" + sender.getName())); + match.broadcastMessage(""); + match.broadcastMessage(CC.translate("&7This will not affect your statistics!")); + match.broadcastMessage(CC.translate("&7&m------------------------------------------------")); + + + if (match.getKit().isBuild() || match.getKit().isSpleef()) { + match.getArena().addAvailableArena(match.getStandaloneArena()); + getPlugin().getArenaManager().removeArenaMatchUUID(match.getStandaloneArena()); + } + } + }.runTask(getPlugin()); + try { + Thread.sleep(1000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } else { + sender.sendMessage(CC.translate("&c" + target.getName() + " is not in a match!")); + } + } + }); + sender.sendMessage(CC.translate("&cDeleting all parties!")); + getPlugin().getPartyManager().getParties().values().forEach(party -> getPlugin().getPartyManager().leaveParty(Bukkit.getPlayer(party.getLeader()))); + sender.sendMessage(CC.translate("&cDeleted parties!")); + sender.sendMessage(CC.translate("&cSending users to lobby")); + Bukkit.getOnlinePlayers().forEach(player -> { + ByteArrayOutputStream b = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(b); + try { + out.writeUTF("Connect"); + out.writeUTF("Hub"); // send players to Hub server + } catch (Exception ignored) { + } + player.sendPluginMessage(getPlugin(), "BungeeCord", b.toByteArray()); + }); + + try { + Thread.sleep(10000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + new BukkitRunnable() { + @Override + public void run() { + Bukkit.shutdown(); + } + }.runTask(getPlugin()); + }); + thread.setName("Practice SafeStop Match Canceller Worker"); + thread.start(); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/SetMatchesPlayedCommand.java b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/SetMatchesPlayedCommand.java new file mode 100644 index 0000000..2d4a83a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/commands/impl/SetMatchesPlayedCommand.java @@ -0,0 +1,44 @@ +package me.devkevin.practice.panel.commands.impl; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SetMatchesPlayedCommand extends PracticeCommand { + + @Override @Command(name = "setplayedmatches", permission = Rank.ADMIN, usage = "&cUsage: /setplayedmatches [player] [matches]") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.translate(command.getCommand().getUsage())); + return; + } + + Player target = Bukkit.getPlayer(args[0]); + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + if (args.length == 2) { + int amount = Integer.parseInt(args[1]); + getPlugin().getProfileManager().getProfileData(target.getUniqueId()).setMatchesPlayed(amount); + player.sendMessage(CC.translate(LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + "&a's played matches has been modified. New played matches: " + amount)); + } else { + player.sendMessage(CC.translate("&cUsage: /setplayedmatches ")); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/panel/menu/PanelMenu.java b/Practice/src/main/java/me/devkevin/practice/panel/menu/PanelMenu.java new file mode 100644 index 0000000..5224dca --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/panel/menu/PanelMenu.java @@ -0,0 +1,9 @@ +package me.devkevin.practice.panel.menu; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PanelMenu { +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/Party.java b/Practice/src/main/java/me/devkevin/practice/party/Party.java new file mode 100644 index 0000000..c6d65b6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/Party.java @@ -0,0 +1,176 @@ +package me.devkevin.practice.party; + +import club.inverted.chatcolor.CC; +import lombok.Data; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.MatchTeam; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Copyright 28/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Data +public class Party { + private final Practice plugin = Practice.getInstance(); + + private Map kits = new HashMap<>(); + + private final UUID leader; + private final Set members = new HashSet<>(); + private int limit = 15; + private boolean open; + private BukkitTask broadcastTask; + + private List matchTeams = new ArrayList<>(); + + private List bards = new ArrayList<>(); + private List archers = new ArrayList<>(); + + public Party(UUID leader) { + this.leader = leader; + this.members.add(leader); + } + + public void addMember(UUID uuid) { + this.members.add(uuid); + } + + public void removeMember(UUID uuid) { + this.members.remove(uuid); + } + + public void broadcast(String message) { + this.members().forEach(member -> member.sendMessage(message)); + } + + public boolean isArcherFull() { + return !getArchers().isEmpty(); + } + + public boolean isBardFull() { + return !getBards().isEmpty(); + } + + public void removeClass(UUID uuid) { + this.bards.remove(uuid); + this.archers.remove(uuid); + } + + public void addArcher(UUID uuid) { + this.bards.remove(uuid); + if (getArchers().size() != 0) { + this.removeClass(uuid); + } else { + this.archers.add(uuid); + } + } + + public void addBard(UUID uuid) { + this.archers.remove(uuid); + if (getBards().size() != 0) { + this.addArcher(uuid); + } else { + this.bards.add(uuid); + } + } + + public List getPartySplitTeam(UUID uuid) { + List uuids = new ArrayList<>(); + for (UUID pUuid : findTeam(uuid).getAlivePlayers()) { + if (pUuid != uuid) { + uuids.add(pUuid); + } + } + + return uuids; + } + + private MatchTeam findTeam(UUID uuid) { + MatchTeam team = null; + for (MatchTeam matchTeam : matchTeams) { + if (matchTeam.getPlayers().contains(uuid)) { + team = matchTeam; + } + } + + return team; + } + + public MatchTeam findOpponent(UUID uuid) { + MatchTeam team = null; + for (MatchTeam matchTeam : matchTeams) { + if (!matchTeam.getPlayers().contains(uuid)) { + team = matchTeam; + } + } + + return team; + } + + public MatchTeam[] splits() { + matchTeams.clear(); + + List teamA = new ArrayList<>(); + List teamB = new ArrayList<>(); + + ThreadLocalRandom random = ThreadLocalRandom.current(); + + for (UUID member : this.members) { + if (teamA.size() == teamB.size()) { + if (random.nextBoolean()) { + teamA.add(member); + } else { + teamB.add(member); + } + } else { + if (teamA.size() < teamB.size()) { + teamA.add(member); + } else { + teamB.add(member); + } + } + } + + MatchTeam team1 = new MatchTeam(teamA.get(0), teamA, 0); + MatchTeam team2 = new MatchTeam(teamB.get(0), teamB, 1); + matchTeams.add(team1); + matchTeams.add(team2); + + return new MatchTeam[] { + team1, + team2 + }; + } + + public List getPartyMembersExcludeMember(UUID uuid) { + return members.stream().filter(m -> m != uuid).collect(Collectors.toList()); + } + + public List getPartyMembersExcludeLeader() { + return members.stream().filter(m -> !this.leader.equals(m)).collect(Collectors.toList()); + } + + public Stream members() { + return this.members.stream().map(this.plugin.getServer()::getPlayer).filter(Objects::nonNull); + } + + public class PartyTask extends BukkitRunnable { + + @Override + public void run() { + if (isOpen()) { + Bukkit.broadcastMessage(CC.translate("")); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyAcceptCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyAcceptCommand.java new file mode 100644 index 0000000..25122f0 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyAcceptCommand.java @@ -0,0 +1,73 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 30/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyAcceptCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "party.accept", aliases = {"p.accept"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "/party accept "); + return; + } + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party != null) { + player.sendMessage(CC.RED + "You're already in a party."); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.getState() != ProfileState.SPAWN) { + player.sendMessage(CC.RED + "You can't do that in your current state"); + return; + } + + Player target = this.plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(String.format(PracticeLang.PLAYER_NOT_FOUND, args[0])); + return; + } + + Party targetParty = this.plugin.getPartyManager().getParty(target.getUniqueId()); + + if (targetParty == null) { + player.sendMessage(CC.RED + "That player is not in a party."); + return; + } + + if (targetParty.getMembers().size() >= targetParty.getLimit()) { + player.sendMessage(CC.RED + "That party is full and cannot hold anymore players."); + return; + } + + if (!this.plugin.getPartyManager().hasPartyInvite(player.getUniqueId(), targetParty.getLeader())) { + player.sendMessage(CC.RED + "You have not been invited to that party."); + return; + } + + this.plugin.getPartyManager().joinParty(targetParty.getLeader(), player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyCreateCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyCreateCommand.java new file mode 100644 index 0000000..44e47d3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyCreateCommand.java @@ -0,0 +1,40 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 31/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyCreateCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "party.create", aliases = {"p.create"}, inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party != null) { + player.sendMessage(CC.RED + "You are already in a party."); + return; + } + + if (profile.getState() != ProfileState.SPAWN) { + player.sendMessage(CC.RED + "You need to be in the spawn to execute that command."); + return; + } + + this.plugin.getPartyManager().createParty(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyHelpCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyHelpCommand.java new file mode 100644 index 0000000..c760bbc --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyHelpCommand.java @@ -0,0 +1,62 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 31/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyHelpCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + String[] LINE = new String[] { + PracticeLang.line, + CC.YELLOW + "Party Commands:", + "", + CC.AQUA + "/party create", + CC.AQUA + "/party leave", + CC.AQUA + "/party join", + CC.AQUA + "/party info", + CC.AQUA + "/party help", + "", + CC.YELLOW + "Party Leader Commands:", + "", + CC.AQUA + "/party open", + CC.AQUA + "/party lock", + CC.AQUA + "/party kick (player)", + CC.AQUA + "/party invite (player)", + CC.AQUA + "/party setlimit (amount)", + PracticeLang.line + }; + + String[] LINE_2 = new String[] { + PracticeLang.line, + CC.YELLOW + "Party Commands:", + "", + CC.AQUA + "/party create", + CC.AQUA + "/party leave", + CC.AQUA + "/party join", + CC.AQUA + "/party info", + CC.AQUA + "/party help", + PracticeLang.line + }; + + @Command(name = "party", aliases = {"p", "t", "team", "party.help", "p.help", "t.help", "team.help"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + if (this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + player.sendMessage(LINE); + } else { + player.sendMessage(LINE_2); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyInfoCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyInfoCommand.java new file mode 100644 index 0000000..0f5e703 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyInfoCommand.java @@ -0,0 +1,53 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +/** + * Copyright 12/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyInfoCommand extends PracticeCommand { + + @Command(name = "party.info", aliases = {"p.info"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You are not in a party."); + } else { + List members = new ArrayList<>(party.getMembers()); + members.remove(party.getLeader()); + + StringBuilder builder = new StringBuilder(CC.GOLD + "Members" + CC.GRAY + " (" + CC.RESET + (party.getMembers().size() + CC.GRAY + "): ")); + members.stream().map(Practice.getInstance().getServer()::getPlayer).filter(Objects::nonNull).forEach(member -> builder.append(LandCore.getInstance().getProfileManager().getProfile(member.getUniqueId()).getGrant().getRank().getColor() + member.getName()).append(",")); + + + String[] information = new String[] { + CC.DARK_GRAY + CC.STRIKETHROUGH + "----------------------------------------------------", + CC.RED + "Party Information:", + CC.GOLD + "Leader: " + LandCore.getInstance().getProfileManager().getProfile(party.getLeader()).getGrant().getRank().getColor() + Practice.getInstance().getServer().getPlayer(party.getLeader()).getName(), + CC.GOLD + builder.toString(), + CC.GOLD + "Party State: " + CC.GRAY + (party.isOpen() ? + CC.GREEN + "Open" : + CC.RED + "Locked"), + CC.DARK_GRAY + CC.STRIKETHROUGH + "----------------------------------------------------" + }; + + player.sendMessage(information); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyInviteCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyInviteCommand.java new file mode 100644 index 0000000..5775c19 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyInviteCommand.java @@ -0,0 +1,95 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 30/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyInviteCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "party.invite", aliases = {"party.inv", "p.invite", "p.inv"}, inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + if (args.length == 0) { + player.sendMessage(CC.RED + "/party invite "); + return; + } + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You do not have a party."); + return; + } + + if (!this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the leader of your party."); + return; + } + + if (party.isOpen()) { + player.sendMessage(CC.RED + "The party state is Open. You do not need to invite players."); + return; + } + + if (party.getMembers().size() >= party.getLimit()) { + player.sendMessage(CC.RED + "Party size has reached it's limit"); + return; + } + + Player target = this.plugin.getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(CC.RED + target.getName() + " not found."); + return; + } + + + Profile targetProfile = this.plugin.getProfileManager().getProfileData(target.getUniqueId()); + + if (targetProfile.isBusy()) { + player.sendMessage(LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + CC.RED + " is currently busy."); + return; + } + + if (target.getUniqueId() == player.getUniqueId()) { + player.sendMessage(CC.RED + "You can't invite yourself."); + return; + } + + if (this.plugin.getPartyManager().getParty(target.getUniqueId()) != null) { + player.sendMessage(CC.RED + "That player is already in a party."); + return; + } + + if (this.plugin.getPartyManager().hasPartyInvite(target.getUniqueId(), player.getUniqueId())) { + player.sendMessage(CC.RED + "That player has already been invited to your party."); + return; + } + + this.plugin.getPartyManager().createPartyInvite(player.getUniqueId(), target.getUniqueId()); + + party.broadcast(LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + " " + CC.YELLOW + "has been invited to the party."); + + Clickable partyInvite = new Clickable(CC.DARK_GREEN + "You have been invited to join " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.DARK_GREEN + "'s party.", + CC.GRAY + "Click to accept", + "/party accept " + player.getName()); + + partyInvite.sendToPlayer(target); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyJoinCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyJoinCommand.java new file mode 100644 index 0000000..333c5e5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyJoinCommand.java @@ -0,0 +1,51 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 12/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyJoinCommand extends PracticeCommand { + + @Command(name = "party.join", aliases = {"p.join"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (party != null) { + player.sendMessage(CC.RED + "You are already in a party."); + } else if (args.length == 0) { + player.sendMessage(CC.RED + "Usage: /party join (name)"); + } else if (profile.getState() != ProfileState.SPAWN) { + player.sendMessage(CC.RED + "Cannot execute this command in your current state."); + } else { + Player target = Practice.getInstance().getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(CC.RED + target.getName() + " not found."); + return; + } + + Party targetParty = Practice.getInstance().getPartyManager().getParty(target.getUniqueId()); + + if (targetParty == null || !targetParty.isOpen() || targetParty.getMembers().size() >= targetParty.getLimit()) { + player.sendMessage(CC.RED + "You can't join this party."); + } else { + Practice.getInstance().getPartyManager().joinParty(targetParty.getLeader(), player); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyKickCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyKickCommand.java new file mode 100644 index 0000000..80837c8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyKickCommand.java @@ -0,0 +1,51 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 12/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyKickCommand extends PracticeCommand { + + @Command(name = "party.kick", aliases = {"p.kick"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You are not in a party."); + } else if (args.length == 0) { + player.sendMessage(CC.RED + "Usage: /party kick (name)"); + } else { + if (party.getLeader() != player.getUniqueId()) { + player.sendMessage(CC.RED + "You are not the leader of the party!"); + return; + } + + Player target = Practice.getInstance().getServer().getPlayer(args[0]); + + if (target == null) { + player.sendMessage(CC.RED + target.getName() + " not found."); + return; + } + + Party targetParty = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (targetParty == null || targetParty.getLeader() != party.getLeader()) { + player.sendMessage(CC.RED + "That player is not in your party."); + } else { + Practice.getInstance().getPartyManager().leaveParty(target); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyLeaveCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyLeaveCommand.java new file mode 100644 index 0000000..671f928 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyLeaveCommand.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 31/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyLeaveCommand extends PracticeCommand { + + private final Practice plugin = Practice.getInstance(); + + @Command(name = "party.leave", aliases = {"p.leave"}, inGameOnly = true) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You are not in a party."); + } else if (profile.getState() != ProfileState.SPAWN) { + player.sendMessage(CC.RED + "You need to be in the spawn to execute that command."); + } else { + this.plugin.getPartyManager().leaveParty(player); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyLimitCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyLimitCommand.java new file mode 100644 index 0000000..8500a98 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyLimitCommand.java @@ -0,0 +1,104 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +/** + * Copyright 12/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyLimitCommand extends PracticeCommand { + + @Command(name = "party.setlimit", aliases = {"p.setlimit"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You are not in a party."); + } else if (args.length == 0) { + player.sendMessage(CC.RED + "Usage: /party setlimit (amount)"); + } else { + + if (party.getLeader() != player.getUniqueId()) { + player.sendMessage(CC.RED + "You are not the leader of the party!"); + return; + } + + try { + int limit = Integer.parseInt(args[0]); + + CoreProfile playerData = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (!player.hasPermission("practice.donors.*")) { + if (limit < 2 || limit > 25) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot set your limit party with " + playerData.getGrant().getRank().getColor() + playerData.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://udrop.buycraft.net/ to set the limit to 25."); + player.sendMessage(""); + } else { + party.setLimit(limit); + player.sendMessage(CC.GREEN + "You have set the party player limit to " + CC.YELLOW + limit + CC.GREEN + " players."); + } + } + else if (!player.hasPermission("practice.donors.gold")) { + if (limit < 2 || limit > 40) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot set your limit party with " + playerData.getGrant().getRank().getColor() + playerData.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://udrop.buycraft.net/ to set the limit to 40."); + player.sendMessage(""); + } else { + party.setLimit(limit); + player.sendMessage(CC.GREEN + "You have set the party player limit to " + CC.YELLOW + limit + CC.GREEN + " players."); + } + } + else if (!player.hasPermission("practice.donors.emerald")) { + if (limit < 2 || limit > 60) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot set your limit party with " + playerData.getGrant().getRank().getColor() + playerData.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://udrop.buycraft.net/ to set the limit to 60."); + player.sendMessage(""); + } else { + party.setLimit(limit); + player.sendMessage(CC.GREEN + "You have set the party player limit to " + CC.YELLOW + limit + CC.GREEN + " players."); + } + } + else if (!player.hasPermission("practice.donors.diamond")) { + if (limit < 2 || limit > 80) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot set your limit party with " + playerData.getGrant().getRank().getColor() + playerData.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://udrop.buycraft.net/ to set the limit to 80."); + player.sendMessage(""); + } else { + party.setLimit(limit); + player.sendMessage(CC.GREEN + "You have set the party player limit to " + CC.YELLOW + limit + CC.GREEN + " players."); + } + } + else if (!player.hasPermission("practice.donors.udrop")) { + if (limit < 2 || limit > 100) { + player.sendMessage(""); + player.sendMessage(CC.RED + "You cannot set your limit party with " + playerData.getGrant().getRank().getColor() + playerData.getGrant().getRank().getName() + CC.RED + " rank."); + player.sendMessage(CC.GRAY + "Purchase rank at https://udrop.buycraft.net/ to set the limit to 100."); + player.sendMessage(""); + } else { + party.setLimit(limit); + player.sendMessage(CC.GREEN + "You have set the party player limit to " + CC.YELLOW + limit + CC.GREEN + " players."); + } + } + + } catch (NumberFormatException e) { + player.sendMessage(CC.RED + "That is not a number."); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyListCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyListCommand.java new file mode 100644 index 0000000..9c64116 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyListCommand.java @@ -0,0 +1,45 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.UUID; + +/** + * Copyright 12/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyListCommand extends PracticeCommand { + + @Command(name = "party.list", aliases = {"p.list"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You are not in a party."); + } else { + StringBuilder builder = new StringBuilder(CC.GOLD + "Your party" + CC.GRAY + " (" + CC.RESET + party.getMembers().size() + CC.GRAY + "):\n"); + + List members = new ArrayList<>(party.getMembers()); + + members.remove(party.getLeader()); + + builder.append(CC.GREEN).append("Leader: ").append(LandCore.getInstance().getProfileManager().getProfile(party.getLeader()).getGrant().getRank().getColor() + Practice.getInstance().getServer().getPlayer(party.getLeader()).getName()).append("\n"); + + members.stream().map(Practice.getInstance().getServer()::getPlayer).filter(Objects::nonNull).forEach(member -> builder.append(LandCore.getInstance().getProfileManager().getProfile(member.getUniqueId()).getGrant().getRank().getColor() + member.getName()).append("\n")); + + player.sendMessage(builder.toString()); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/command/PartyOpenCommand.java b/Practice/src/main/java/me/devkevin/practice/party/command/PartyOpenCommand.java new file mode 100644 index 0000000..e2afa76 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/command/PartyOpenCommand.java @@ -0,0 +1,68 @@ +package me.devkevin.practice.party.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 12/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PartyOpenCommand extends PracticeCommand { + + @Command(name = "party.open", aliases = {"p.open", "party.lock", "p.lock"}) + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + + Party party = Practice.getInstance().getPartyManager().getParty(player.getUniqueId()); + + if (party == null) { + player.sendMessage(CC.RED + "You are not in a party."); + } else { + if (party.getLeader() != player.getUniqueId()) { + player.sendMessage(CC.RED + "You are not the leader of the party!"); + return; + } + + party.setOpen(!party.isOpen()); + + if (party.isOpen()) { + if (player.hasPermission("practice.donors.*")) { + party.setBroadcastTask(new BukkitRunnable() { + @Override + public void run() { + for (Player online : Bukkit.getOnlinePlayers()) { + Party partyPlayer = Practice.getInstance().getPartyManager().getParty(online.getUniqueId()); + Player leader = Bukkit.getPlayer(party.getLeader()); + + if (partyPlayer == null) { + Clickable clickable = new Clickable(LandCore.getInstance().getProfileManager().getProfile(leader.getUniqueId()).getGrant().getRank().getColor() + leader.getName() + + CC.RESET + " is hosting a public party" + CC.GOLD + "[Click to join]", + CC.GRAY + "Click to join", + "/party join " + leader.getName()); + + clickable.sendToPlayer(online); + } + } + } + }.runTaskTimerAsynchronously(Practice.getInstance(), 20L, 20L * 60L)); + } + } else { + if (party.getBroadcastTask() != null){ + party.getBroadcastTask().cancel(); + } + } + + party.broadcast(CC.YELLOW + "Your party is now " + (party.isOpen() ? CC.GREEN + CC.BOLD + "OPEN" : CC.RED + CC.BOLD + "LOCKED")); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/manager/PartyManager.java b/Practice/src/main/java/me/devkevin/practice/party/manager/PartyManager.java new file mode 100644 index 0000000..bf8d003 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/manager/PartyManager.java @@ -0,0 +1,187 @@ +package me.devkevin.practice.party.manager; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.TaskUtil; +import me.devkevin.practice.util.TtlHashMap; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Copyright 28/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class PartyManager { + + private final Practice plugin = Practice.getInstance(); + + private final Map> partyInvites = new TtlHashMap<>(TimeUnit.SECONDS, 15); + private final Map parties = new HashMap<>(); + private final Map partyLeaders = new HashMap<>(); + + public boolean isLeader(UUID uuid) { + return this.parties.containsKey(uuid); + } + + public boolean hasPartyInvite(UUID player, UUID other) { + return this.partyInvites.get(player) != null && this.partyInvites.get(player).contains(other); + } + + public void removePartyInvites(UUID uuid) { + this.partyInvites.remove(uuid); + } + + public void createPartyInvite(UUID requester, UUID requested) { + this.partyInvites.computeIfAbsent(requested, k -> new ArrayList<>()).add(requester); + } + + public boolean isInParty(UUID player, Party party) { + Party targetParty = this.getParty(player); + return targetParty != null && targetParty.getLeader() == party.getLeader(); + } + + private void givePartyItems(Player player) { + player.closeInventory(); + player.getInventory().setContents(this.plugin.getHotbarItem().getPartyItems()); + player.updateInventory(); + } + + public Party getParty(UUID uuid) { + if (this.parties.containsKey(uuid)) { + return this.parties.get(uuid); + } + if (this.partyLeaders.containsKey(uuid)) { + UUID leader = this.partyLeaders.get(uuid); + return this.parties.get(leader); + } + return null; + } + + public void createParty(Player player) { + Party party = new Party(player.getUniqueId()); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + this.parties.put(player.getUniqueId(), party); + this.plugin.getPartyMenu().addParty(player); + this.plugin.getProfileManager().sendToSpawnAndResetButNotTP(player); + + profile.setState(ProfileState.PARTY); + + givePartyItems(player); + + player.sendMessage(CC.YELLOW + "You have created a party."); + player.sendMessage(CC.GRAY + CC.I + "Note: " + CC.RED + CC.I + "Party system is under development if you see any bug report or contact with any admin please."); + } + + private void disbandParty(Party party, boolean tournament) { + this.plugin.getPartyMenu().removeParty(party); + this.parties.remove(party.getLeader()); + + if (party.getBroadcastTask() != null) { + party.getBroadcastTask().cancel(); + } + + party.broadcast(CC.RED + "Your party has been disbanded."); + + party.members().forEach(member -> { + Profile profile = this.plugin.getProfileManager().getProfileData(member.getUniqueId()); + + if (this.partyLeaders.get(profile.getUuid()) != null) { + this.partyLeaders.remove(profile.getUuid()); + } + + if (profile.getState() == ProfileState.SPAWN) { + this.plugin.getProfileManager().sendToSpawnAndResetButNotTP(member); + } + }); + } + + public void joinParty(UUID leader, Player player) { + Party party = this.getParty(leader); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + this.partyLeaders.put(player.getUniqueId(), leader); + party.addMember(player.getUniqueId()); + this.plugin.getPartyMenu().updateParty(party); + this.plugin.getProfileManager().sendToSpawnAndResetButNotTP(player); + + profile.setState(ProfileState.PARTY); + givePartyItems(player); + + party.broadcast(LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GREEN + " has joined the party."); + } + + public void leaveParty(Player player) { + Party party = this.getParty(player.getUniqueId()); + + if (party == null) { + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (this.parties.containsKey(player.getUniqueId())) { + this.disbandParty(party, false); + } else { + party.broadcast(LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.RED + " has left the party"); + party.removeMember(player.getUniqueId()); + + party.getBards().remove(player.getUniqueId()); + party.getArchers().remove(player.getUniqueId()); + + this.partyLeaders.remove(player.getUniqueId()); + + this.plugin.getPartyMenu().updateParty(party); + + if (profile.getState() == ProfileState.SPECTATING) { + this.plugin.getProfileManager().sendToSpawn(player); + return; + } else { + this.plugin.getProfileManager().sendToSpawnAndResetButNotTP(player); + } + } + + switch (profile.getState()) { + case FIGHTING: + this.plugin.getMatchManager().removeFighter(player, profile, false); + break; + case SPECTATING: + if(this.plugin.getEventManager().getSpectators().contains(player.getUniqueId())) { + this.plugin.getEventManager().removeSpectator(player); + } else { + this.plugin.getMatchManager().removeSpectator(player); + } + this.plugin.getProfileManager().sendToSpawn(player); + break; + case SPAWN: + TaskUtil.runLater(new BukkitRunnable() { + @Override + public void run() { + if (player.getInventory().getContents() == null) { + player.getInventory().setContents(plugin.getHotbarItem().getSpawnItems()); + } + player.updateInventory(); + } + }, 3L); + break; + } + + party.getMembers().stream().map(Bukkit::getPlayer).filter(Objects::nonNull).forEach(member -> { + member.hidePlayer(player); + player.hidePlayer(member); + }); + + this.plugin.getProfileManager().sendToSpawnAndResetButNotTP(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/party/menu/PartyMenu.java b/Practice/src/main/java/me/devkevin/practice/party/menu/PartyMenu.java new file mode 100644 index 0000000..c2860d3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/party/menu/PartyMenu.java @@ -0,0 +1,548 @@ +package me.devkevin.practice.party.menu; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.*; +import java.util.stream.Collectors; + +import static me.devkevin.practice.util.PlayerUtil.PLACEHOLDER_ITEM; + +/** + * Copyright 28/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class PartyMenu { + + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI partyMenu = new InventoryUI(CC.DARK_RED + "Duel another parties", true, 6); + private final InventoryUI partyEvent = new InventoryUI(CC.DARK_RED + "Host Party Events", true, 4); + + private final InventoryUI partySplitMenu = new InventoryUI(CC.DARK_RED + "Select a Party Split Kit", true,1); + private final InventoryUI partyFFAMenu = new InventoryUI(CC.DARK_RED + "Select a Party FFA Kit", true,1); + private final InventoryUI partyRedroverMenu = new InventoryUI(CC.DARK_RED + "Select a Redrover Kit", true,1); + private final InventoryUI partyKothMenu = new InventoryUI(CC.DARK_RED + "Play Koth Mode", true, 1); + private final InventoryUI partyHCFMenu = new InventoryUI(CC.DARK_RED + "Play HCF Mdde", true, 1); + + private final Map partySplitMapInventories = new HashMap<>(); + private final Map partyFFAMapInventories = new HashMap<>(); + private final Map redroverMapInventories = new HashMap<>(); + + public PartyMenu() { + this.PartyMenu(); + } + + private void PartyMenu() { + for (int i = 0; i < 9 * 4; i++) { + this.partyEvent.setItem(i, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM)); + } + + + Collection kits = this.plugin.getKitManager().getKits(); + + for (Kit kit : kits) { + if (kit.isEnabled()) { + this.partyFFAMenu.addItem(new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + handleFFAClick(player, kit); + } + }); + this.partySplitMenu.addItem(new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + handleSplitClick(player, kit); + } + }); + if (!kit.getName().equalsIgnoreCase("HCF")) { + this.partyRedroverMenu.addItem(new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + handleRedroverClick(player, kit); + } + }); + } + } + } + + this.partyKothMenu.setItem(0, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.FENCE_GATE).name(CC.DARK_RED + "Koth").build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.sendMessage(CC.RED + "Under development."); + } + }); + this.partyHCFMenu.setItem(0, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.POTION).data(373).name(CC.DARK_RED + "HCF").build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.sendMessage(CC.RED + "Under development."); + } + }); + + + // party events + this.partyEvent.setItem(11, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.LEASH).name(CC.DARK_RED + "Party Split") + .lore(CC.GRAY + "Slip your party into") + .lore(CC.GRAY + "two teams and fight.") + .lore("") + .lore(CC.DARK_RED + "Click to host") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(partySplitMenu.getCurrentPage()); + } + }); + this.partyEvent.setItem(13, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.BLAZE_ROD).name(CC.DARK_RED + "Party FFA") + .lore(CC.GRAY + "Everyone in the party") + .lore(CC.GRAY + "fights everybody else.") + .lore("") + .lore(CC.DARK_RED + "Click to host") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(partyFFAMenu.getCurrentPage()); + } + }); + this.partyEvent.setItem(15, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.REDSTONE).name(CC.DARK_RED + "Red Rover") + .lore(CC.GRAY + "Fight in a series of 1v1s") + .lore(CC.GRAY + "until there is a winner") + .lore("") + .lore(CC.DARK_RED + "Click to host") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(partyRedroverMenu.getCurrentPage()); + } + }); + this.partyEvent.setItem(21, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.FENCE_GATE).name(CC.DARK_RED + "Party Koth") + .lore(CC.GRAY + "Slip your party into") + .lore(CC.GRAY + "two teams and fight") + .lore(CC.GRAY + "capping a koth to win.") + .lore("") + .lore(CC.DARK_RED + "Click to host") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(partyKothMenu.getCurrentPage()); + } + }); + this.partyEvent.setItem(23, new InventoryUI.AbstractClickableItem( + new ItemBuilder(Material.DIAMOND_CHESTPLATE).name(CC.DARK_RED + "Party HCF") + .lore(CC.GRAY + "Slip your party into") + .lore(CC.GRAY + "two teams choosing") + .lore(CC.GRAY + "Bard, Archer, Diamond") + .lore(CC.GRAY + "kit and fight.") + .lore("") + .lore(CC.DARK_RED + "Click to host") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(partyHCFMenu.getCurrentPage()); + } + }); + + for (Kit kit : this.plugin.getKitManager().getKits()) { + InventoryUI partySplitInventory = new InventoryUI(CC.BLUE + "Select Split Arena", true, 3); + InventoryUI partyFFAInventory = new InventoryUI(CC.BLUE + "Select FFA Arena", true, 3); + InventoryUI redroverInventory = new InventoryUI(CC.BLUE + "Select Redrover Arena", true, 3); + + for (Arena arena : this.plugin.getArenaManager().getArenas().values()) { + if (!arena.isEnabled()) { + continue; + } + + if (kit.getArenaWhiteList().size() > 0 && !kit.getArenaWhiteList().contains(arena.getName())) { + continue; + } + + ItemStack dirt = ItemUtil.createItem(Material.DIRT, CC.YELLOW + arena.getName()); + + partySplitInventory.addItem(new InventoryUI.AbstractClickableItem(dirt) { + @Override + public void onClick(InventoryClickEvent event) { + PartyMenu.this.handlePartySplitMapClick((Player) event.getWhoClicked(), arena, kit); + } + }); + partyFFAInventory.addItem(new InventoryUI.AbstractClickableItem(dirt) { + @Override + public void onClick(InventoryClickEvent event) { + PartyMenu.this.handlePartyFFAMapClick((Player) event.getWhoClicked(), arena, kit); + } + }); + redroverInventory.addItem(new InventoryUI.AbstractClickableItem(dirt) { + @Override + public void onClick(InventoryClickEvent event) { + PartyMenu.this.handleRedroverMapClick((Player) event.getWhoClicked(), arena, kit); + } + }); + } + this.partySplitMapInventories.put(kit.getName(), partySplitInventory); + this.partyFFAMapInventories.put(kit.getName(), partyFFAInventory); + this.redroverMapInventories.put(kit.getName(), redroverInventory); + } + } + + public void addParty(Player player) { + ItemStack skull = new ItemBuilder(Material.SKULL_ITEM) + .name(LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GRAY + " (" + "1" + ")") + .durability(3) + .owner(player.getName()) + .lore(PracticeLang.line) + .lore(CC.GRAY + "Members: ") + .lore(CC.RED + "No members online") + .lore("") + .lore(CC.GRAY + "Click here to duel " + player.getName() + "'s party.") + .lore(PracticeLang.line) + .build(); + this.partyMenu.addItem(new InventoryUI.AbstractClickableItem(skull) { + @Override + public void onClick(InventoryClickEvent event) { + Player sender = (Player)event.getWhoClicked(); + player.closeInventory(); + sender.performCommand("duel " + player.getName()); + } + }); + } + + public void updateParty(Party party) { + Player player = this.plugin.getServer().getPlayer(party.getLeader()); + + for (int i = 0; i < this.partyMenu.getSize(); i++) { + InventoryUI.ClickableItem item = this.partyMenu.getItem(i); + + if (item != null) { + ItemStack stack = item.getItemStack(); + + if (stack.getItemMeta().hasDisplayName() && stack.getItemMeta().getDisplayName().contains(player.getName())) { + List strings = new ArrayList<>(); + + strings.add(PracticeLang.line); + strings.add(CC.GRAY + "Members: "); + + party.members().forEach(member -> strings.add(CC.GRAY + " - " + LandCore.getInstance().getProfileManager().getProfile(member.getUniqueId()).getGrant().getRank().getColor() + member.getName())); + + strings.add(""); + strings.add(CC.GRAY + "Click here to duel " + player.getName() + "'s party."); + strings.add(PracticeLang.line); + + ItemUtil.reloreItem(stack, strings.toArray(new String[0])); + ItemUtil.renameItem(stack, LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + CC.GRAY + " (" + CC.GRAY + party.getMembers().size() + CC.GRAY + ")"); + + item.setItemStack(stack); + break; + } + } + } + } + + public void removeParty(Party party) { + Player player = this.plugin.getServer().getPlayer(party.getLeader()); + + for (int i = 0; i < this.partyMenu.getSize(); i++) { + InventoryUI.ClickableItem item = this.partyMenu.getItem(i); + + if (item != null) { + ItemStack stack = item.getItemStack(); + + if (stack.getItemMeta().hasDisplayName() && stack.getItemMeta().getDisplayName().contains(player.getName())) { + this.partyMenu.removeItem(i); + break; + } + } + } + } + + private void handleFFAClick(Player player, Kit kit) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null || kit == null || !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + return; + } + + player.closeInventory(); + + if (party.getMembers().size() < 2) { + player.sendMessage(CC.RED + "You need more than 2 players to start an event."); + } else { + if (player.hasPermission("practice.donors.*")) { + player.closeInventory(); + player.openInventory(this.partyFFAMapInventories.get(kit.getName()).getCurrentPage()); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(party.getLeader()); + Arena arena = this.plugin.getArenaManager().getRandomArena(kit, profile.getLastArenaPlayed()); + if (arena == null) { + player.sendMessage(CC.RED + "No available arenas found."); + return; + } + + if (kit.getName().equals("Parkour")) { + player.sendMessage(CC.RED + "Sorry but you can't use this kit in FFA mode!"); + return; + } + + if (kit.getName().equals("BedWars")) { + player.sendMessage(CC.RED + "Sorry but you can't use this kit in FFA mode!"); + return; + } + + this.createFFAMatch(party, arena, kit); + } + } + + private void handleSplitClick(Player player, Kit kit) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null || kit == null || !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + return; + } + + player.closeInventory(); + + if (party.getMembers().size() < 2) { + player.sendMessage(CC.RED + "You need more than 2 players to start an event."); + } else { + if (player.hasPermission("practice.donors.*")) { + player.closeInventory(); + player.openInventory(this.partySplitMapInventories.get(kit.getName()).getCurrentPage()); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(party.getLeader()); + Arena arena = this.plugin.getArenaManager().getRandomArena(kit, profile.getLastArenaPlayed()); + if (arena == null) { + player.sendMessage(CC.RED + "No available arenas found."); + return; + } + + if (kit.getName().equals("BedWars")) { + player.sendMessage(CC.RED + "Sorry but you can't use this kit in FFA mode!"); + } + } + } + + private void handleRedroverClick(Player player, Kit kit) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null || kit == null || !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + return; + } + + player.closeInventory(); + + if (party.getMembers().size() < 4) { + player.sendMessage(CC.RED + "You need more than 4 players to start an event."); + } else { + if (player.hasPermission("practice.donors.*")) { + player.closeInventory(); + player.openInventory(this.redroverMapInventories.get(kit.getName()).getCurrentPage()); + return; + } + + Profile profile = this.plugin.getProfileManager().getProfileData(party.getLeader()); + Arena arena = this.plugin.getArenaManager().getRandomArena(kit, profile.getLastArenaPlayed()); + if (arena == null) { + player.sendMessage(CC.RED + "No available arenas found."); + return; + } + + this.createRedroverMatch(party, arena, kit); + } + } + + private void handlePartyFFAMapClick(Player player, Arena arena, Kit kit) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null || !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + return; + } + + player.closeInventory(); + + if (party.getMembers().size() < 2) { + player.sendMessage(CC.RED + "You need more than 2 players to start an event."); + } else { + this.createFFAMatch(party, arena, kit); + } + } + + private void handlePartySplitMapClick(Player player, Arena arena, Kit kit) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null || !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + return; + } + + player.closeInventory(); + + if (party.getMembers().size() < 2) { + player.sendMessage(CC.RED + "You need more than 2 players to start an event."); + } else { + this.createSplitMatch(party, arena, kit); + } + } + + private void handleRedroverMapClick(Player player, Arena arena, Kit kit) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + if (party == null || !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + return; + } + + player.closeInventory(); + + if (party.getMembers().size() < 2) { + player.sendMessage(CC.RED + "You need more than 2 players to start an event."); + } else { + this.createRedroverMatch(party, arena, kit); + } + } + + private void createFFAMatch(Party party, Arena arena, Kit kit) { + MatchTeam team = new MatchTeam(party.getLeader(), Lists.newArrayList(party.getMembers()), 0); + Match match = new Match(arena, kit, QueueType.UN_RANKED, team); + + match.broadcastMessage( + CC.YELLOW + "Starting a party FFA match with kit " + + CC.BLUE + kit.getName() + + CC.YELLOW + " and arena " + + CC.BLUE + arena.getName() + + CC.YELLOW + "."); + + this.plugin.getMatchManager().createMatch(match); + } + + private void createSplitMatch(Party party, Arena arena, Kit kit) { + MatchTeam[] teams = party.splits(); + Match match = new Match(arena, kit, QueueType.UN_RANKED, teams); + Player leaderA = this.plugin.getServer().getPlayer(teams[0].getLeader()); + Player leaderB = this.plugin.getServer().getPlayer(teams[1].getLeader()); + + match.broadcastMessage( + CC.YELLOW + "Starting a party Split match with kit " + + CC.BLUE + kit.getName() + + CC.YELLOW + " and arena " + + CC.BLUE + arena.getName() + + CC.YELLOW + " between " + + CC.BLUE + leaderA.getName() + + CC.YELLOW + "'s team and " + + CC.BLUE + leaderB.getName() + + CC.YELLOW + "'s team."); + + this.plugin.getMatchManager().createMatch(match); + } + + private void createRedroverMatch(Party party, Arena arena, Kit kit) { + MatchTeam[] teams = party.splits(); + Match match = new Match(arena, kit, QueueType.UN_RANKED, teams); + Player leaderA = this.plugin.getServer().getPlayer(teams[0].getLeader()); + Player leaderB = this.plugin.getServer().getPlayer(teams[1].getLeader()); + + match.broadcastMessage( + CC.YELLOW + "Starting a party Redrover match with kit " + + CC.BLUE + kit.getName() + + CC.YELLOW + " and arena " + + CC.BLUE + arena.getName() + + CC.YELLOW + " between " + + CC.BLUE + leaderA.getName() + + CC.YELLOW + "'s team and " + + CC.BLUE + leaderB.getName() + + CC.YELLOW + "'s team."); + + this.plugin.getMatchManager().createMatch(match); + } + + public Inventory getMenu(int page) { + int max = (int) Math.ceil(plugin.getPartyManager().getParties().values().size() / 18.0); + + Inventory inventory = Bukkit.createInventory(null, 27, CC.translate("&4Parties")); + inventory.setItem(0, new ItemBuilder(Material.ARROW).name(CC.GRAY + "Previous Page").build()); + inventory.setItem(8, new ItemBuilder(Material.ARROW).name(CC.GRAY + "Next Page").build()); + + int minIndex = (int) ((double) (page - 1) * 18); + int maxIndex = (int) ((double) (page) * 18); + + List toLoop = new ArrayList<>(plugin.getPartyManager().getParties().values()); + Collections.reverse(toLoop); + + toLoop.forEach(party -> { + int number = toLoop.indexOf(party); + + if(number >= minIndex && number < maxIndex) { + number -= (int) ((double) (18) * (page - 1)) - 9; + + List lore = new ArrayList<>(); + int[] count = {0}; + + List members = new ArrayList<>(party.getMembers().stream().map(Bukkit::getPlayer).collect(Collectors.toList())); + members.remove(Bukkit.getPlayer(party.getLeader())); + + lore.add(""); + lore.add(CC.GRAY + "Members:"); + if(members.isEmpty()) { + lore.add(CC.RED + "No members online"); + } else { + members.forEach(member -> { + if(count[0] != 10) { + lore.add(" &7- " + LandCore.getInstance().getProfileManager().getProfile(member.getUniqueId()).getGrant().getRank().getColor() + member.getDisplayName()); + count[0]++; + } + }); + } + lore.add(""); + lore.add(CC.GREEN + "Click to duel"); + + inventory.setItem(number, new ItemBuilder(Material.SKULL_ITEM) + .durability(3) + .owner(Bukkit.getPlayer(party.getLeader()).getName()) + .name(LandCore.getInstance().getProfileManager().getProfile(party.getLeader()).getGrant().getRank().getColor() + Bukkit.getPlayer(party.getLeader()).getName() + CC.GRAY + "'s Party" ) + .lore(lore).build()); + } + }); + return inventory; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/Profile.java b/Practice/src/main/java/me/devkevin/practice/profile/Profile.java new file mode 100644 index 0000000..76739e3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/Profile.java @@ -0,0 +1,267 @@ +package me.devkevin.practice.profile; + +import com.google.common.collect.Maps; +import com.google.gson.annotations.SerializedName; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.kit.PlayerKit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.menu.MatchDetailsMenu; +import me.devkevin.practice.options.ProfileOptions; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.Cooldown; +import net.minecraft.server.v1_8_R3.Packet; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@Setter +@RequiredArgsConstructor +public class Profile { + + public static final int DEFAULT_ELO = 1000; + public static Map players = Maps.newHashMap(); + + /* + * The maps don't need getters as they are never accessed directly. + */ + private final Map> playerKits = new HashMap<>(); + private final Map kits = new ConcurrentHashMap<>(); + private final Map rankedLosses = new HashMap<>(); + private final Map rankedWins = new HashMap<>(); + private final Map rankedElo = new HashMap<>(); + private final Map partyElo = new HashMap<>(); + private final Map currentWinstreak = new HashMap<>(); + private final Map highestWinStreak = new HashMap<>(); + + private Map cachedPlayer = new ConcurrentHashMap<>(); + + @Getter private MatchDetailsMenu lastSnapshot; + + @SerializedName("uuid") + private final UUID uuid; + public String name; + private ProfileState state = ProfileState.LOADING; + private ProfileOptions options = new ProfileOptions(); + + private List potions = new ArrayList<>(); + private List packets = new ArrayList<>(); + + private UUID currentMatchID; + private UUID duelSelecting; + + private int teamID = -1; + private int rematchID = -1; + private int eloRange = 250; + private int pingRange = 50; + + public int unrankedWins; + public int unrankedLosses; + + private int experience; + + private int oitcKills; + private int oitcDeaths; + private int oitcWins; + private int oitcLosses; + + private int sumoWins; + private int sumoLosses; + + private int tntrunEventWins; + private int tntrunEventLosses; + + private boolean disconnected = false; + private boolean npcsLoaded = true; + private boolean selectClasses = true; + private int elo, potionsThrown, potionsMissed, hits, combo, longestCombo; + private long lastDamagedMillis = 0; + private double wastedHP; + + private int wTapHits; + private int criticalHits; + private int blockedHits; + + private long lastRespawnTime; + + private boolean respawning; + private boolean hasRespawned; + + private int currentCps; + private int cps; + + private int playedArcher, playedBard; + + private boolean canRate = false; + + private int matchesPlayed; + private int globalElo = Profile.DEFAULT_ELO; + private int uDropElo = Profile.DEFAULT_ELO; + + private Cooldown playerCommandCooldown = new Cooldown(0); + + private UUID followingId; + private boolean following; + + private boolean dataLoaded; + + private int globalWinStreak; + private int globalHighestWinStreak; + + private boolean leaving = false; + + private Arena lastArenaPlayed; + + private Match match; + + public int getMaxCustomKits() { + return 4; + } + + public void addPlayerKit(int index, PlayerKit playerKit) { + this.getPlayerKits(playerKit.getName()).put(index, playerKit); + } + + public Map getPlayerKits(String kitName) { + return this.playerKits.computeIfAbsent(kitName, k -> new HashMap<>()); + } + + public double getPotionAccuracy() { + if (potionsMissed == 0) { + return 100.0; + } else if (potionsThrown == potionsMissed) { + return 50.0; + } + return Math.round(100.0D - (((double) potionsMissed / (double) potionsThrown) * 100.0D)); + } + + public void incrementPotionsThrown() { + this.potionsThrown++; + } + + public void incrementPotionsMissed() { + this.potionsMissed++; + } + + public void incrementPlayedBard() { + this.playedBard++; + } + + public void incrementPlayedArcher() { + this.playedBard++; + } + + public void incrementCriticalHits() { + criticalHits++; + } + + public void incrementBlockedHits() { + blockedHits++; + } + + + public int getWins(String kitName) { + return this.rankedWins.computeIfAbsent(kitName, k -> 0); + } + + public void setWins(String kitName, int wins) { + this.rankedWins.put(kitName, wins); + } + + public int getLosses(String kitName) { + return this.rankedLosses.computeIfAbsent(kitName, k -> 0); + } + + public void setLosses(String kitName, int losses) { + this.rankedLosses.put(kitName, losses); + } + + public int getElo(String kitName) { + return this.rankedElo.computeIfAbsent(kitName, k -> Profile.DEFAULT_ELO); + } + + public void setElo(String kitName, int elo) { + this.rankedElo.put(kitName, elo); + } + + public int getPartyElo(String kitName) { + return this.partyElo.computeIfAbsent(kitName, k -> Profile.DEFAULT_ELO); + } + + public void setPartyElo(String kitName, int elo) { + this.partyElo.put(kitName, elo); + } + + public boolean isInSpawn() { return state == ProfileState.SPAWN; } + public boolean isInQueue() { return state == ProfileState.QUEUE; } + public boolean isFighting() { return state == ProfileState.FIGHTING; } + public boolean isInParty() { return state == ProfileState.PARTY; } + public boolean isSpectating() { return state == ProfileState.SPECTATING; } + public boolean isEditing() { return state == ProfileState.EDITING; } + public boolean isInStaffMode() { return state == ProfileState.STAFF; } + public boolean isInEvent() { return state == ProfileState.EVENT; } + public boolean isInSoloUnranked() { return state == ProfileState.SoloUnranked; } + public boolean isInSoloRanked() { return state == ProfileState.RankedSolo; } + public boolean isBusy() { return this.isInQueue() || this.isFighting() || this.isEditing(); } + public boolean isBotMatch() { return state == ProfileState.BOT_FIGHTING; } + + public void setCurrentWinstreak(String kitName, int streak) { + this.currentWinstreak.put(kitName, streak); + } + + public int getCurrentWinstreak(String kitName) { + return this.currentWinstreak.computeIfAbsent(kitName, k -> 0); + } + + public void setHighestWinStreak(String kitName, int streak) { + this.highestWinStreak.put(kitName, streak); + } + + public int getHighestWinStreak(String kitName) { + return this.highestWinStreak.computeIfAbsent(kitName, k -> 0); + } + + public void setHits(int hits) { + if (System.currentTimeMillis() - lastDamagedMillis < 250) { + return; + } + + this.hits = hits; + this.lastDamagedMillis = System.currentTimeMillis(); + } + + public int getGlobalWins() { + final AtomicInteger integer = new AtomicInteger(); + final List kits = new ArrayList<>(Practice.getInstance().getKitManager().getKits()); + + kits.forEach(kit -> { + integer.addAndGet(getWins(kit.getName())); + }); + + return integer.get(); + } + + public int getGlobalLosses() { + final AtomicInteger integer = new AtomicInteger(); + final List kits = new ArrayList<>(Practice.getInstance().getKitManager().getKits()); + + kits.forEach(kit -> { + integer.addAndGet(this.getLosses(kit.getName())); + }); + + return integer.get(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/hotbar/HotbarItem.java b/Practice/src/main/java/me/devkevin/practice/profile/hotbar/HotbarItem.java new file mode 100644 index 0000000..05448f8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/hotbar/HotbarItem.java @@ -0,0 +1,198 @@ +package me.devkevin.practice.profile.hotbar; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.practice.util.ItemBuilder; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class HotbarItem { + + private final ItemStack playAgain = new ItemBuilder(Material.PAPER).name(CC.YELLOW + "Play Again" + CC.GRAY + " (Right Click)").unbreakable(true).build(); + + private final ItemStack[] spawnItems = new ItemStack[] { + new ItemBuilder(Material.IRON_SWORD) + .name(CC.YELLOW + "Unranked Queue" + CC.GRAY + " (Right Click)") + .unbreakable(true) + .build(), + new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.YELLOW + "Ranked Queue" + CC.GRAY + " (Right Click)") + .unbreakable(true) + .build(), + new ItemBuilder(Material.BOOK) + .name(CC.YELLOW + "Edit Kits" + CC.GRAY + " (Right Click)") + .unbreakable(true) + .build(), + null, + new ItemBuilder(Material.NAME_TAG) + .name(CC.YELLOW + "Parties" + CC.GRAY + " (Right Click)") + .unbreakable(true) + .build(), + null, + null, + new ItemBuilder(Material.SIGN) + .name(CC.YELLOW + "Leaderboards" + CC.GRAY + " (Right Click)") + .unbreakable(true) + .build(), + new ItemBuilder(Material.CHEST) + .durability(3) + .name(CC.YELLOW + "Settings" + CC.GRAY + " (Right Click)") + .unbreakable(true) + .build() + }; + + private final ItemStack[] queueItems = new ItemStack[] { + new ItemBuilder(Material.INK_SACK).durability(1).name(CC.RED + "Leave the Queue" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + null, + null, + null, + null, + null, + null, + null, + null + }; + + private final ItemStack[] specItems = new ItemStack[] { + null, + null, + null, + null, + null, + null, + null, + null, + new ItemBuilder(Material.INK_SACK).durability(1).name(CC.RED + "Stop Spectating" + CC.GRAY + " (Right Click)").unbreakable(true).build() + }; + + private final ItemStack[] specPartyItems = new ItemStack[] { + null, + null, + null, + null, + null, + null, + null, + null, + new ItemBuilder(Material.INK_SACK).durability(1).name(CC.RED + "Stop Spectating Party" + CC.GRAY + " (Right Click)").unbreakable(true).build() + }; + + private final ItemStack[] partyItems = new ItemStack[] { + new ItemBuilder(Material.GOLD_AXE).name(CC.AQUA + "Play Menu" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + new ItemBuilder(Material.GOLD_SWORD).name(CC.DARK_GREEN + "Party Events" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + null, + null, + new ItemBuilder(Material.SLIME_BALL).name(CC.YELLOW + "Fight other parties" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + null, + new ItemBuilder(Material.PAPER).name(CC.GOLD + "Information" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + new ItemBuilder(Material.BOOK).name(CC.DARK_BLUE + "HCF kits" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + new ItemBuilder(Material.INK_SACK).durability(1).name(CC.RED + "Leave Party" + CC.GRAY + " (Right Click)").unbreakable(true).build() + }; + + private final ItemStack DEFAULT_KIT = new ItemBuilder(Material.ENCHANTED_BOOK).name(CC.translate("&eDefault Kit" + CC.GRAY + " (Right Click)")).unbreakable(true).build(); + + private final ItemStack[] eventItems = new ItemStack[] { + null, + null, + null, + null, + null, + null, + null, + null, + new ItemBuilder(Material.NETHER_STAR).name(CC.RED + "Leave Event").unbreakable(true).build() + }; + + + private final ItemStack[] lmsItems = new ItemStack[] { + null, + null, + null, + null, + null, + null, + null, + null, + null + }; + + private final ItemStack[] staffModeItems = new ItemStack[] { + null, + null, + null, + null, + null, + null, + null, + null, + new ItemBuilder(Material.INK_SACK).durability(1).name(CC.RED + "Leave Staff Mode").unbreakable(true).build() + }; + + private final ItemStack[] editorItems = new ItemStack[] { + new ItemBuilder(Material.PAPER).name(CC.YELLOW + "Edit kit" + CC.GRAY + " (Right Click)").unbreakable(true).build(), + null, + null, + null, + null, + null, + null, + null, + new ItemBuilder(Material.INK_SACK).durability(1).name(CC.RED + "Back to spawn" + CC.GRAY + " (Right Click)").unbreakable(true).build() + }; + + private final ItemStack[] boxingSword = new ItemStack[] { + new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.GOLD + CC.BOLD + "Boxing Sword") + .enchantment(Enchantment.DAMAGE_ALL, 2) + .unbreakable(true) + .build(), + null, + null, + null, + null, + null, + null, + null, + null + }; + + private final ItemStack[] boxingSwordDonor = new ItemStack[] { + new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.GOLD + CC.BOLD + "Boxing Sword") + .enchantment(Enchantment.DAMAGE_ALL, 2) + .unbreakable(true) + .build(), + new ItemBuilder(Material.IRON_SWORD) + .name(CC.GOLD + CC.BOLD + "Boxing Sword") + .enchantment(Enchantment.DAMAGE_ALL, 2) + .unbreakable(true) + .build(), + new ItemBuilder(Material.GOLD_SWORD) + .name(CC.GOLD + CC.BOLD + "Boxing Sword") + .enchantment(Enchantment.DAMAGE_ALL, 2) + .unbreakable(true) + .build(), + new ItemBuilder(Material.STONE_SWORD) + .name(CC.GOLD + CC.BOLD + "Boxing Sword") + .enchantment(Enchantment.DAMAGE_ALL, 2) + .unbreakable(true) + .build(), + new ItemBuilder(Material.WOOD_SWORD) + .name(CC.GOLD + CC.BOLD + "Boxing Sword") + .enchantment(Enchantment.DAMAGE_ALL, 2) + .unbreakable(true) + .build(), + null, + null, + null, + null + }; + +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/listener/InventoryListener.java b/Practice/src/main/java/me/devkevin/practice/profile/listener/InventoryListener.java new file mode 100644 index 0000000..be6c3a5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/listener/InventoryListener.java @@ -0,0 +1,54 @@ +package me.devkevin.practice.profile.listener; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.CraftingInventory; +import org.bukkit.inventory.Inventory; + +/** + * Copyright 15/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class InventoryListener implements Listener { + + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + Inventory clicked = event.getClickedInventory(); + if (clicked == null) { + event.setCancelled(true); + return; + } + + if (!clicked.equals(player.getInventory())) { + if (clicked instanceof CraftingInventory) { + event.setCancelled(true); + player.updateInventory(); + return; + } + return; + } + + if (player.getGameMode().equals(GameMode.CREATIVE)) return; + if (profile.isFighting()) return; + + if (profile.isInSpawn() || profile.isInQueue() + || profile.isSpectating() + || profile.isInParty() + || profile.isInEvent() && player.getItemInHand() != null && player.getItemInHand().getType() == Material.COMPASS) { + event.setCancelled(true); + } + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/profile/listener/MovementListener.java b/Practice/src/main/java/me/devkevin/practice/profile/listener/MovementListener.java new file mode 100644 index 0000000..c643422 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/listener/MovementListener.java @@ -0,0 +1,69 @@ +package me.devkevin.practice.profile.listener; + +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerToggleFlightEvent; +import org.bukkit.potion.PotionEffectType; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 05/02/2023 @ 23:59 + * MovementListener / me.devkevin.practice.profile.listener / Practice + */ +@RequiredArgsConstructor +public class MovementListener implements Listener { + private final Practice plugin; + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + if (event.getPlayer() == null) { + return; + } + + Location to = event.getTo(); + Location from = event.getFrom(); + Player player = event.getPlayer(); + Profile practicePlayerData = plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (practicePlayerData == null) { + plugin.getLogger().warning(player.getName() + "'s player data is null" + "(" + this.getClass().getName() + ")"); + return; + } + + if (practicePlayerData.getState() == ProfileState.FIGHTING) { + Match match = plugin.getMatchManager().getMatch(player.getUniqueId()); + if (match == null) { + return; + } + + if (match.getKit().isSumo() || match.getKit().isSpleef() || match.getKit().isBedWars()) { + if (match.getKit().isSumo() || match.getKit().isSpleef()) { + if (to.getBlock().isLiquid()) { + plugin.getMatchManager().removeFighter(player, practicePlayerData, true); + } + } + + if (to.getX() != from.getX() || to.getZ() != from.getZ()) { + if (match.getMatchState() == MatchState.STARTING) { + player.teleport(from); + } + } + } + } + } + + @EventHandler + public void onFlight(PlayerToggleFlightEvent event) { + if (event.getPlayer().hasPotionEffect(PotionEffectType.WEAKNESS)) { + event.setCancelled(true); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/listener/PlayerTabCompleteFix.java b/Practice/src/main/java/me/devkevin/practice/profile/listener/PlayerTabCompleteFix.java new file mode 100644 index 0000000..2174527 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/listener/PlayerTabCompleteFix.java @@ -0,0 +1,33 @@ +package me.devkevin.practice.profile.listener; + +import me.devkevin.practice.Practice; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerChatTabCompleteEvent; +import org.bukkit.util.StringUtil; + +import java.util.List; + +/** + * Copyright 19/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PlayerTabCompleteFix implements Listener { + + private final Practice plugin = Practice.getInstance(); + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerChatTabComplete(PlayerChatTabCompleteEvent event) { + List completions = (List) event.getTabCompletions(); + completions.clear(); + String token = event.getLastToken(); + for (Player player : this.plugin.getServer().getOnlinePlayers()) { + if (StringUtil.startsWithIgnoreCase(player.getName(), token)) { + completions.add(player.getName()); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/listener/ProfileListener.java b/Practice/src/main/java/me/devkevin/practice/profile/listener/ProfileListener.java new file mode 100644 index 0000000..f5c3eb9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/listener/ProfileListener.java @@ -0,0 +1,1013 @@ +package me.devkevin.practice.profile.listener; + +import club.inverted.chatcolor.CC; +import com.bizarrealex.aether.Aether; +import com.bizarrealex.aether.event.BoardCreateEvent; +import com.bizarrealex.aether.scoreboard.Board; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.events.PracticeEvent; +import me.devkevin.practice.events.oitc.OITCEvent; +import me.devkevin.practice.events.oitc.OITCPlayer; +import me.devkevin.practice.hcf.menu.ClassSelectionMenu; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.kit.PlayerKit; +import me.devkevin.practice.leaderboard.menu.LeaderboardsMenu; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.match.matches.OngoingMatchesMenu; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.Animation; +import net.minecraft.server.v1_8_R3.PacketPlayInClientCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.block.Sign; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.FishHook; +import org.bukkit.entity.Item; +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.*; +import org.bukkit.event.player.*; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.potion.Potion; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ProfileListener implements Listener { + private final List blockedCommands = new ArrayList<>(); + + @Getter + private final Practice plugin = Practice.getInstance(); + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + me.devkevin.practice.profile.Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (profile == null) return; + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + Board board = Board.getByPlayer(player); + if (board != null) Board.getBoards().remove(board); + + switch (profile.getState()) { + case FIGHTING: + profile.setLeaving(true); + this.plugin.getMatchManager().removeFighter(player, profile, false); + break; + case SPECTATING: + if (this.plugin.getEventManager().getSpectators().contains(player.getUniqueId())) { + this.plugin.getEventManager().removeSpectator(player); + } else { + this.plugin.getMatchManager().removeSpectator(player); + } + break; + case QUEUE: + if (party == null) { + this.plugin.getQueue().removePlayerFromQueue(player); + } else if (this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + this.plugin.getQueue().removePartyFromQueue(party); + } + break; + case EVENT: + PracticeEvent practiceEvent = this.plugin.getEventManager().getEventPlaying(player); + if (practiceEvent != null) { + practiceEvent.leave(player); + } + break; + } + profile.getCachedPlayer().clear(); + this.plugin.getMatchManager().removeMatchRequests(player.getUniqueId()); + this.plugin.getPartyManager().leaveParty(player); + this.plugin.getPartyManager().removePartyInvites(player.getUniqueId()); + this.plugin.getTournamentManager().leaveTournament(player); + + try { + this.plugin.getProfileManager().removePlayerData(player.getUniqueId()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @EventHandler + public void onPlayerKick(PlayerKickEvent event) { + Player player = event.getPlayer(); + me.devkevin.practice.profile.Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (profile == null) return; + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + + Board board = Board.getByPlayer(player); + if (board != null) Board.getBoards().remove(board); + + switch (profile.getState()) { + case FIGHTING: + profile.setLeaving(true); + this.plugin.getMatchManager().removeFighter(player, profile, false); + break; + case SPECTATING: + + if(this.plugin.getEventManager().getSpectators().contains(player.getUniqueId())) { + this.plugin.getEventManager().removeSpectator(player); + } else { + this.plugin.getMatchManager().removeSpectator(player); + } + + break; + case QUEUE: + if (party == null) { + this.plugin.getQueue().removePlayerFromQueue(player); + } else if (this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + this.plugin.getQueue().removePartyFromQueue(party); + } + break; + case EVENT: + PracticeEvent practiceEvent = this.plugin.getEventManager().getEventPlaying(player); + if (practiceEvent != null) { // A redundant check, but just in case + practiceEvent.leave(player); + } + break; + } + + profile.getCachedPlayer().clear(); + this.plugin.getMatchManager().removeMatchRequests(player.getUniqueId()); + this.plugin.getPartyManager().leaveParty(player); + this.plugin.getPartyManager().removePartyInvites(player.getUniqueId()); + this.plugin.getTournamentManager().leaveTournament(player); + + try { + this.plugin.getProfileManager().removePlayerData(player.getUniqueId()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @EventHandler + public void onProfileFirstConnect(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + this.plugin.getProfileManager().createPlayerData(player); + + if (Board.getByPlayer(player) == null) { + Aether board = this.plugin.getBoard(); + Bukkit.getPluginManager().callEvent(new BoardCreateEvent(new Board(player, board, board.getOptions()), player)); + } + + try { + this.plugin.getProfileManager().sendToSpawn(player); + } catch (Exception e) { + player.sendMessage(CC.RED + "Error: spawn location not set."); + } + + Animation animation = new Animation("footer", player.getUniqueId(), 30L); + + animation.getLines().add(CC.GRAY + CC.I + "prac.lol"); + animation.getLines().add(CC.GRAY + CC.I + "store.prac.lol"); + animation.getLines().add(CC.GRAY + CC.I + "prac.lol/discord"); + animation.getLines().add(CC.GRAY + CC.I + "prac.lol/twitter"); + } + + @EventHandler + public void onPlayerJoin(AsyncPlayerPreLoginEvent event) { + me.devkevin.practice.profile.Profile profile = null; + + try { + profile = new me.devkevin.practice.profile.Profile(event.getUniqueId()); + + if (profile.getName() == null) { + profile.setName(event.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @EventHandler + public void onPlayerInteractSoup(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (!player.isDead() && player.getItemInHand().getType() == Material.MUSHROOM_SOUP && player.getHealth() < 19.0) { + final double newHealth = Math.min(player.getHealth() + 7.0, 20.0); + player.setHealth(newHealth); + player.getItemInHand().setType(Material.BOWL); + player.updateInventory(); + } + } + + @EventHandler + @SuppressWarnings("deprecation") + public void onPlayerItemConsume(PlayerItemConsumeEvent event) { + ItemStack item = event.getItem(); + if (item == null) { + return; + } + + Material type = item.getType(); + Player player = event.getPlayer(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + ProfileState state = profile.getState(); + if (state == ProfileState.SPAWN || state == ProfileState.EDITING || state == ProfileState.SPECTATING) { + return; + } + + if (type != Material.GOLDEN_APPLE) { + return; + } + + if (state != ProfileState.FIGHTING) { + return; + } + + if (profile.isFighting()) { + if (!item.hasItemMeta()) { + return; + } + if (!item.getItemMeta().hasDisplayName()) { + return; + } + if (!item.getItemMeta().getDisplayName().contains("Golden Head")) { + return; + } + + player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 200, 1)); + player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 2400, 0)); + player.setFoodLevel(Math.min(player.getFoodLevel() + 6, 20)); + } + } + + @EventHandler + public void onRegenerate(EntityRegainHealthEvent event) { + if (!(event.getEntity() instanceof Player)) { + return; + } + + if (event.getRegainReason() != EntityRegainHealthEvent.RegainReason.SATIATED) { + return; + } + + Player player = (Player) event.getEntity(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + switch (profile.getState()) { + case FIGHTING: + Match match = plugin.getMatchManager().getMatch(profile); + if (match.getKit().isBoxing() || match.getKit().isBuild() || match.getKit().isSumo()) { + event.setCancelled(true); + } + + EntityRegainHealthEvent.RegainReason reason = event.getRegainReason(); + double amount = event.getAmount(); + + if (reason == EntityRegainHealthEvent.RegainReason.MAGIC && amount > 2.0) { + profile.setWastedHP(8.0 - amount); + } + break; + case EVENT: + // TODO: + break; + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + Profile profileData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if ((event.getAction() != Action.RIGHT_CLICK_BLOCK && event.getAction() != Action.RIGHT_CLICK_AIR)) { + return; + } + if (player.getGameMode() == GameMode.CREATIVE) { + if (profileData.getState() != ProfileState.SPECTATING) { + return; + } + } + if (profileData.getState() == ProfileState.SPECTATING) { + event.setCancelled(true); + } + + if (event.getAction().name().endsWith("_BLOCK")) { + if (event.getClickedBlock().getType().name().contains("SIGN") && event.getClickedBlock().getState() instanceof Sign) { + Sign sign = (Sign) event.getClickedBlock().getState(); + if (ChatColor.stripColor(sign.getLine(1)).equals("[Soup]")) { + event.setCancelled(true); + + Inventory inventory = this.plugin.getServer().createInventory(null, 54, + ChatColor.DARK_GRAY + "Soup Refill"); + + for (int i = 0; i < 54; i++) { + inventory.setItem(i, new ItemStack(Material.MUSHROOM_SOUP)); + } + + event.getPlayer().openInventory(inventory); + } + } + if (event.getClickedBlock().getType() == Material.CHEST || event.getClickedBlock().getType() == Material.ENDER_CHEST) { + event.setCancelled(true); + } + + if (event.getClickedBlock().getType().name().contains("DOOR")) { + event.setCancelled(true); + } + + if (event.getClickedBlock().getType().name().contains("FENCE")) { + event.setCancelled(true); + } + } + + if (event.getAction().name().startsWith("RIGHT_")) { + ItemStack item = event.getItem(); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (player.getItemInHand() == null || !event.hasItem()) return; + + switch (profileData.getState()) { + case LOADING: + player.sendMessage( + CC.RED + "You must wait until your player data has loaded before you can use items."); + break; + case SPAWN: + if (item == null) { + return; + } + event.setCancelled(true); + switch (item.getType()) { + case DIAMOND_SWORD: + if (party != null) { // in the case the plugin bugged + player.sendMessage(CC.RED + "You can't join to the Ranked Queue while in a party."); + return; + } + + if (this.plugin.getTournamentManager().isInTournament(player.getUniqueId())) { + player.sendMessage(CC.RED + "You can't do that while you're in a tournament."); + return; + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (profileData.getMatchesPlayed() >= 10) { + player.openInventory(plugin.getQueueMenu().getRankedMenu().getCurrentPage()); + } else if (coreProfile.hasDonor()) { + player.openInventory(plugin.getQueueMenu().getRankedMenu().getCurrentPage()); + } else { + player.sendMessage(ChatColor.RED + "You need to play " + (10 - profileData.getMatchesPlayed()) + " unranked matches before playing ranked!"); + } + + break; + case IRON_SWORD: + if (party != null) { // in the case the plugin bugged + player.sendMessage(CC.RED + "You can't join to the Unranked Queue while in a party."); + return; + } + + if (this.plugin.getTournamentManager().isInTournament(player.getUniqueId())) { + player.sendMessage(CC.RED + "You can't do that while you're in a tournament."); + return; + } + + player.openInventory(this.plugin.getQueueMenu().getUnrankedMenu().getCurrentPage()); + + //player.openInventory(this.plugin.getQueueJoinMenu().getUnrankedMenu().getCurrentPage()); + break; + case GOLD_SWORD: + //player.openInventory(this.plugin.getQueueJoinMenu().getBotSelectKitMenu().getCurrentPage()); + break; + case WOOD_SWORD: + player.sendMessage(CC.RED + "Soon "); + break; + case NAME_TAG: + this.plugin.getPartyManager().createParty(player); + break; + case CHEST: + player.openInventory(this.plugin.getGeneralSettingMenu().getGeneralMenu().getCurrentPage()); + break; + case PAPER: + if (item.isSimilar(plugin.getHotbarItem().getPlayAgain())) { + if (plugin.getMatchManager().hasPlayAgainRequest(player.getUniqueId())) { + player.performCommand("playagain"); + } + } else { + if (party == null) { + player.performCommand("inventory " + profileData.getLastSnapshot().getSnapshotId().toString()); + return; + } + + if (!this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + player.sendMessage(ChatColor.RED + "You are not the leader of this party."); + return; + } + player.openInventory(this.plugin.getPartyMenu().getPartyMenu().getCurrentPage()); + } + break; + case BOOK: + player.openInventory(this.plugin.getKitEditorMenu().getKitEditor().getCurrentPage()); + break; + case INK_SACK: + + if (item.getData().getData() == 1) { + UUID rematching = this.plugin.getMatchManager().getRematcher(player.getUniqueId()); + Player rematcher = this.plugin.getServer().getPlayer(rematching); + + if (rematcher == null) { + player.sendMessage(ChatColor.RED + "That player is not online."); + return; + } + + if (this.plugin.getMatchManager() + .getMatchRequest(rematcher.getUniqueId(), player.getUniqueId()) != null) { + this.plugin.getServer().dispatchCommand(player, "accept " + rematcher.getName()); + } else { + this.plugin.getServer().dispatchCommand(player, "duel " + rematcher.getName()); + } + } + break; + /*case EYE_OF_ENDER: + player.openInventory(this.plugin.getHostMenu().getHostMenu().getCurrentPage()); + break;*/ + case COMPASS: + new OngoingMatchesMenu().openMenu(player); + break; + case SIGN: + new LeaderboardsMenu().openMenu(player); + break; + case TRIPWIRE_HOOK: + if (event.getAction() == Action.RIGHT_CLICK_AIR || + event.getAction() == Action.LEFT_CLICK_AIR || + event.getAction() == Action.RIGHT_CLICK_BLOCK || + event.getAction() == Action.LEFT_CLICK_BLOCK) { + player.sendMessage(CC.translate("&aYour current cps: &c" + profileData.getCurrentCps())); + } + break; + } + case QUEUE: + if (item == null) { + return; + } + + if (item.getType() == Material.INK_SACK) { + if (party == null) { + this.plugin.getQueue().removePlayerFromQueue(player); + } else { + this.plugin.getQueue().removePartyFromQueue(party); + } + break; + } + break; + case PARTY: + if (item == null) { + return; + } + + switch (item.getType()) { + case PAPER: + player.performCommand("party info"); + break; + case INK_SACK: + this.plugin.getPartyManager().leaveParty(player); + break; + case EMERALD: + UUID rematching = this.plugin.getMatchManager().getRematcher(player.getUniqueId()); + Player rematcher = this.plugin.getServer().getPlayer(rematching); + + if (rematcher == null) { + player.sendMessage(CC.RED + "That player is no longer online."); + return; + } + + if (this.plugin.getMatchManager() + .getMatchRequest(rematcher.getUniqueId(), player.getUniqueId()) != null) { + this.plugin.getServer().dispatchCommand(player, "accept " + rematcher.getName()); + } else { + this.plugin.getServer().dispatchCommand(player, "duel " + rematcher.getName()); + } + break; + case GOLD_AXE: + player.openInventory(this.plugin.getPartyQueueJoinMenu().getPartyQueueMenu().getCurrentPage()); + break; + case SLIME_BALL: + if (party != null && !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + player.sendMessage(CC.RED + "You're not the leader of your party."); + return; + } + player.openInventory(this.plugin.getPartyMenu().getPartyMenu().getCurrentPage()); + break; + case GOLD_SWORD: + if (party != null && !this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + player.sendMessage(CC.RED + "You're not the leader of your party."); + return; + } + player.openInventory(this.getPlugin().getPartyMenu().getPartyEvent().getCurrentPage()); + break; + case NETHER_STAR: + player.performCommand("party list"); + break; + case BOOK: + if (party != null) { + if (!party.getLeader().equals(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are not the leader of the party!"); + return; + } + + new ClassSelectionMenu().openMenu(player); + } + break; + } + break; + case SPECTATING: + if (item == null) { + return; + } + + if (item.isSimilar(plugin.getHotbarItem().getPlayAgain())) { + if (plugin.getMatchManager().hasPlayAgainRequest(player.getUniqueId())) { + player.performCommand("playagain"); + } + } + + if (item.getType() == Material.INK_SACK) { + if (this.plugin.getEventManager().getSpectators().contains(player.getUniqueId())) { + this.plugin.getEventManager().removeSpectator(player); + } else if (party == null) { + this.plugin.getMatchManager().removeSpectator(player); + } else { + this.plugin.getPartyManager().leaveParty(player); + } + } + break; + case EDITING: + if(event.getClickedBlock() == null) { + return; + } + switch (event.getClickedBlock().getType()) { + case WALL_SIGN: + case SIGN: + case SIGN_POST: + this.plugin.getEditorManager().removeEditor(player.getUniqueId()); + Bukkit.getScheduler().runTaskLater(plugin, () -> + this.plugin.getProfileManager().sendToSpawn(player), 1L); + break; + case CHEST: + Kit kit = this.plugin.getKitManager() + .getKit(this.plugin.getEditorManager().getEditingKit(player.getUniqueId())); + + if (kit.isCombo()) { + player.closeInventory(); + event.setCancelled(true); + player.sendMessage(CC.RED + "You are not allowed to do this while editing a GApple kit."); + } + + else if (kit.isBuild()) { + player.closeInventory(); + event.setCancelled(true); + player.sendMessage(CC.RED + "You are not allowed to do this while editing a Build kit."); + } + + else if (kit.isBoxing()) { + player.closeInventory(); + event.setCancelled(true); + player.sendMessage(CC.RED + "You are not allowed to do this while editing a Boxing kit."); + } + + //Check if the edit kit contents are empty before opening the inventory. + else if (kit.getKitEditContents()[0] != null) { + Inventory editorInventory = this.plugin.getServer().createInventory(null, 36); + + editorInventory.setContents(kit.getKitEditContents()); + player.openInventory(editorInventory); + } + event.setCancelled(true); + break; + case ANVIL: + player.openInventory( + this.plugin.getKitEditorMenu().getEditingKitInventory(player.getUniqueId()).getCurrentPage()); + event.setCancelled(true); + break; + case ENDER_PEARL: + event.setCancelled(true); + break; + } + case STAFF: + if (item == null) { + return; + } + + switch (item.getType()) { + case INK_SACK: + // reset player from staff mode + this.plugin.getProfileManager().sendToSpawn(player); + break; + } + break; + case FIGHTING: + if (item == null) { + return; + } + Match match = this.plugin.getMatchManager().getMatch(profileData); + + if (item.isSimilar(plugin.getHotbarItem().getPlayAgain())) { + if (plugin.getMatchManager().hasPlayAgainRequest(player.getUniqueId())) { + player.performCommand("playagain"); + } + } + + switch (item.getType()) { + case MUSHROOM_SOUP: + if(player.getHealth() <= 19.0D && !player.isDead()) { + if(player.getHealth() < 20.0D || player.getFoodLevel() < 20) { + player.getItemInHand().setType(Material.BOWL); + } + player.setHealth(player.getHealth() + 7.0D > 20.0D ? 20.0D : player.getHealth() + + 7.0D); + player.setFoodLevel(player.getFoodLevel() + 2 > 20 ? 20 : player.getFoodLevel() + 2); + player.setSaturation(12.8F); + player.updateInventory(); + } + break; + case ENCHANTED_BOOK: + Kit kit = match.getKit(); + PlayerInventory inventory = player.getInventory(); + + int kitIndex = inventory.getHeldItemSlot(); + if(kitIndex == 8) { + kit.applyToPlayer(player); + } else { + Map kits = profileData.getPlayerKits(kit.getName()); + + PlayerKit playerKit = kits.get(kitIndex + 1); + + if(playerKit != null) { + playerKit.applyToPlayer(player); + } + } + break; + case POTION: + if (match.getMatchState() == MatchState.STARTING) { + if (!Potion.fromItemStack(item).isSplash()) { + break; + } + event.setCancelled(true); + player.sendMessage(ChatColor.RED + "You can't throw pots in your current state!"); + player.updateInventory(); + } + break; + case ENDER_PEARL: + if (match.getMatchState() == MatchState.STARTING) { + event.setCancelled(true); + player.sendMessage(ChatColor.RED + "You can't throw enderpearls in your current state!"); + player.updateInventory(); + } + break; + } + break; + case EVENT: + if (item == null) { + return; + } + if (item.getType() == Material.NETHER_STAR) { + PracticeEvent eventPlaying = this.plugin.getEventManager().getEventPlaying(player); + + if (eventPlaying != null) { + eventPlaying.leave(player); + } else { + this.plugin.getProfileManager().sendToSpawn(player); + } + } + break; + } + } + } + + @EventHandler(ignoreCancelled = true) + public void onPlayerItemDamage(PlayerItemDamageEvent event) { + Player player = event.getPlayer(); + me.devkevin.practice.profile.Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + + if (profile.isInSpawn()) { + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + me.devkevin.practice.profile.Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + + switch (profile.getState()) { + case EVENT: + PracticeEvent currentEvent = this.plugin.getEventManager().getEventPlaying(player); + + if(currentEvent != null) { + if(currentEvent instanceof OITCEvent) { + OITCEvent oitcEvent = (OITCEvent) currentEvent; + OITCPlayer oitcKiller = oitcEvent.getPlayer(player.getKiller()); + OITCPlayer oitcPlayer = oitcEvent.getPlayer(player); + oitcPlayer.setLastKiller(oitcKiller); + //PlayerUtil.re(event); + break; + } + + if (currentEvent.onDeath() != null) { + currentEvent.onDeath().accept(player); + } + } + break; + } + } + + + @EventHandler + public void onPlayerDeath(PlayerDeathEvent event) { + Player player = event.getEntity(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + profile.getPotions().clear(); + profile.getPackets().clear(); + + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { + if (player.isDead()) { + ((CraftPlayer) player).getHandle().playerConnection.a(new PacketPlayInClientCommand(PacketPlayInClientCommand.EnumClientCommand.PERFORM_RESPAWN)); + } + }); + + switch (profile.getState()) { + case FIGHTING: { + Match match = plugin.getMatchManager().getMatch(player.getUniqueId()); + + if (match.isPartyMatch()) { + plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, () -> { + if (player.isDead()) { + ((CraftPlayer) player).getHandle().playerConnection.a(new PacketPlayInClientCommand(PacketPlayInClientCommand.EnumClientCommand.PERFORM_RESPAWN)); + } + }); + } + + this.plugin.getMatchManager().removeFighter(player, profile, true); + } + case EVENT: + PracticeEvent currentEvent = this.plugin.getEventManager().getEventPlaying(player); + + if (currentEvent != null) { + if (currentEvent instanceof OITCEvent) { + OITCEvent oitcEvent = (OITCEvent) currentEvent; + OITCPlayer oitcKiller = oitcEvent.getPlayer(player.getKiller()); + OITCPlayer oitcPlayer = oitcEvent.getPlayer(player); + oitcPlayer.setLastKiller(oitcKiller); + //PlayerUtil.respawnPlayer(event); + break; + } + + if (currentEvent.onDeath() != null) { + currentEvent.onDeath().accept(player); + } + } + break; + } + + event.setDroppedExp(0); + event.setDeathMessage(null); + event.getDrops().clear(); + } + + /*@EventHandler + public void onHungerDamage(EntityDamageEvent event) { + if (event.getCause() == EntityDamageEvent.DamageCause.STARVATION) { + event.setCancelled(true); + } + }*/ + + @EventHandler + public void onFoodLevelChange(FoodLevelChangeEvent event) { + Player player = (Player) event.getEntity(); + me.devkevin.practice.profile.Profile practicePlayerData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (practicePlayerData.getState() == ProfileState.FIGHTING) { + + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + + if (match.getKit().isBoxing() || match.getKit().isSumo() || this.plugin.getEventManager().getEventPlaying(player) != null) { + event.setCancelled(true); + } + } else { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + Player player = event.getPlayer(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + Item itemDrop = event.getItemDrop(); + Material drop = itemDrop.getItemStack().getType(); + + boolean noDrop = drop.name().contains("_SWORD") || drop.name().contains("_AXE") || drop.name().contains("_SPADE") || drop.name().contains("_PICKAXE") || drop == Material.BOW || drop == Material.ENCHANTED_BOOK || drop == Material.MUSHROOM_SOUP; + + if (profile.getState() == ProfileState.FIGHTING) { + if (drop == Material.ENCHANTED_BOOK) { + event.setCancelled(true); + } else if (noDrop) { + event.setCancelled(true); + player.sendMessage(CC.RED + "You can't drop weapons in 1v1s."); + } else { + Match match = this.plugin.getMatchManager().getMatch(event.getPlayer().getUniqueId()); + this.plugin.getMatchManager().addDroppedItem(match, event.getItemDrop()); + } + } else { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + Player player = event.getPlayer(); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.getState() == ProfileState.FIGHTING) { + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + + if (match.getEntitiesToRemove().contains(event.getItem())) { + match.removeEntityToRemove(event.getItem()); + } else { + event.setCancelled(true); + } + } else if (profile.isSpectating()) { + // don't let player pick items while are in spec mode + event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onConsume(PlayerItemConsumeEvent event) { + ItemStack stack = event.getItem(); + if (stack == null || stack.getType() != Material.POTION) return; + + Bukkit.getScheduler().runTaskLater(Practice.getInstance(), () -> { + }, 1L); + } + + @EventHandler + public void onProjectileLaunch(ProjectileLaunchEvent event) { + if (event.getEntity().getShooter() instanceof Player) { + Player shooter = (Player) event.getEntity().getShooter(); + me.devkevin.practice.profile.Profile shooterData = this.plugin.getProfileManager().getProfileData(shooter.getUniqueId()); + + if (shooterData.getState() == ProfileState.FIGHTING) { + Match match = this.plugin.getMatchManager().getMatch(shooter.getUniqueId()); + match.addEntityToRemove(event.getEntity()); + } + } + } + + @EventHandler + public void onProjectileHit(ProjectileHitEvent event) { + if (event.getEntity().getShooter() instanceof Player) { + Player shooter = (Player) event.getEntity().getShooter(); + me.devkevin.practice.profile.Profile shooterData = this.plugin.getProfileManager().getProfileData(shooter.getUniqueId()); + + if (shooterData != null) { + if (shooterData.getState() == ProfileState.FIGHTING) { + Match match = this.plugin.getMatchManager().getMatch(shooter.getUniqueId()); + + match.removeEntityToRemove(event.getEntity()); + + if (event.getEntityType() == EntityType.ARROW) { + event.getEntity().remove(); + } + } + } + } + } + + @EventHandler + public void onItemDamage(PlayerItemDamageEvent event) { + Player player = event.getPlayer(); + if (player.getLastDamageCause() != null && player.getLastDamageCause() instanceof EntityDamageByEntityEvent) { + if (((EntityDamageByEntityEvent) player.getLastDamageCause()).getDamager() instanceof FishHook) { + event.setCancelled(true); + } + } + } + + + @EventHandler(ignoreCancelled = true) + public void onAsyncPlayerChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + String chatMessage = event.getMessage(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (party != null) { + if (chatMessage.startsWith("!") || chatMessage.startsWith("@")) { + event.setCancelled(true); + + String message = ChatColor.GOLD + "(Party) " + ChatColor.WHITE + player.getName() + ChatColor.GRAY + ": " + chatMessage.replaceFirst("!", "").replaceFirst("@", ""); + + party.broadcast(message); + } + } else { + PlayerKit kitRenaming = this.plugin.getEditorManager().getRenamingKit(player.getUniqueId()); + + if(kitRenaming != null) { + kitRenaming.setDisplayName(ChatColor.translateAlternateColorCodes('&', chatMessage)); + event.setCancelled(true); + event.getPlayer().sendMessage(CC.GREEN + "Successfully renamed kit " + CC.PINK + "#" + kitRenaming.getIndex() + CC.GREEN + "'s name to " + CC.PINK + kitRenaming.getDisplayName() + CC.GREEN + "."); + this.plugin.getEditorManager().removeRenamingKit(event.getPlayer().getUniqueId()); + } + } + } + + @EventHandler + public void onPlayerConsumeItem(PlayerItemConsumeEvent event) { + Player player = event.getPlayer(); + me.devkevin.practice.profile.Profile profileData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + Material drop = event.getItem().getType(); + + if (profileData.getState() == ProfileState.EDITING) { + if (drop.getId() == 373) { + event.setCancelled(true); + player.updateInventory(); + player.sendMessage(CC.RED + "You cant do this while editing kit."); + } + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onPlayerInteractOnKitEditor(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (player.getGameMode() == GameMode.CREATIVE) { + return; + } + + me.devkevin.practice.profile.Profile profileData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (event.getAction().name().startsWith("RIGHT_")) { + ItemStack item = event.getItem(); + + if (profileData.getState() == ProfileState.EDITING) { + if (item == null) { + return; + } + + switch (item.getType()) { + case BOW: + case GOLDEN_APPLE: + case FISHING_ROD: + case ENDER_PEARL: + event.setCancelled(true); + player.sendMessage(CC.RED + "You cant do this while editing kit."); + break; + case POTION: + // don't let players throw pots while editing kit + Potion potion = Potion.fromItemStack(event.getItem()); + + if (potion.isSplash()) { + event.setCancelled(true); + player.updateInventory(); + player.sendMessage(CC.RED + "You cant do this while editing kit."); + } + break; + } + } + } + } + + @EventHandler + public void onFlight(PlayerToggleFlightEvent event) { + if (event.getPlayer().hasPotionEffect(PotionEffectType.WEAKNESS)) { + event.setCancelled(true); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/listener/TabCompleteListener.java b/Practice/src/main/java/me/devkevin/practice/profile/listener/TabCompleteListener.java new file mode 100644 index 0000000..4ca0a17 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/listener/TabCompleteListener.java @@ -0,0 +1,38 @@ +package me.devkevin.practice.profile.listener; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerChatTabCompleteEvent; +import org.bukkit.util.StringUtil; + +import java.util.Collection; + +/** + * Copyright 11/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public final class TabCompleteListener implements Listener { + + // we basically copy+paste the CraftBukkit code but modify the + // visiblity check to work better with how PotPvP uses invis + @EventHandler + public void onPlayerChatTabComplete(PlayerChatTabCompleteEvent event) { + String token = event.getLastToken(); + Collection completions = event.getTabCompletions(); + + completions.clear(); + + for (Player player : Bukkit.getOnlinePlayers()) { + if (!event.getPlayer().canSee(player) && player.hasMetadata("invisible")) { + continue; + } + + if (StringUtil.startsWithIgnoreCase(player.getName(), token)) { + completions.add(player.getName()); + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/listener/WorldListener.java b/Practice/src/main/java/me/devkevin/practice/profile/listener/WorldListener.java new file mode 100644 index 0000000..8e22379 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/listener/WorldListener.java @@ -0,0 +1,370 @@ +package me.devkevin.practice.profile.listener; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.standalone.StandaloneArena; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchState; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.TaskUtil; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.entity.Item; +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.*; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.hanging.HangingBreakEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.Vector; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class WorldListener implements Listener { + + private Practice plugin; + + public WorldListener() { + this.plugin = Practice.getInstance(); + } + + @EventHandler(priority = EventPriority.HIGHEST) + final void onBlockPlaceEvent(BlockPlaceEvent event) { + if (event.isCancelled() && event.getPlayer().getLocation().getBlockY() > event.getBlock().getLocation().getBlockY()) { + event.getPlayer().teleport(event.getPlayer().getLocation()); + event.getPlayer().setVelocity(new Vector()); + new BukkitRunnable() { + public void run() { + event.getPlayer().setVelocity(new Vector(0.0, -0.25, 0.0)); + } + }.runTaskLaterAsynchronously(this.plugin, 1L); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) + public void onBlockBreak(BlockBreakEvent event) { + Player player = event.getPlayer(); + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + this.plugin.getLogger().warning(player.getName() + "'s player data is null"); + event.setCancelled(true); + return; + } + /*PracticeEvent playerEvent = this.plugin.getEventManager().getEventPlaying(player); + + if(playerEvent instanceof SpleefEvent){ + SpleefEvent spleefEvent = (SpleefEvent)playerEvent; + + if (event.getBlock().getType() == Material.SNOW_BLOCK && player.getItemInHand().getType() == Material.DIAMOND_SPADE) { + Location blockLocation = event.getBlock().getLocation(); + + event.setCancelled(true); + spleefEvent.addBlock(event.getBlock().getLocation(), event.getBlock()); + event.getBlock().getDrops().forEach(itemStack -> player.getInventory().addItem(itemStack)); + event.getBlock().setType(Material.AIR); + player.sendBlockChange(event.getBlock().getLocation(), Material.AIR, (byte)0); + player.getWorld().getPlayers().forEach(other -> { + other.sendBlockChange(event.getBlock().getLocation(), Material.AIR, (byte)0); + }); + } + }*/ + + if (profile.getState() == ProfileState.FIGHTING) { + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + + // cancel event when match is starting + if (match.getMatchState() == MatchState.STARTING) { + event.setCancelled(true); + return; + } + + if (match.getKit().isBuild()) { + if (!match.getPlacedBlockLocations().contains(event.getBlock().getLocation())) { + player.sendMessage(ChatColor.RED + "You can't break this block."); + event.setCancelled(true); + } + } else if (match.getKit().isSpleef()) { + double minX = match.getStandaloneArena().getMin().getX(); + double minZ = match.getStandaloneArena().getMin().getZ(); + double maxX = match.getStandaloneArena().getMax().getX(); + double maxZ = match.getStandaloneArena().getMax().getZ(); + if (minX > maxX) { + double lastMinX = minX; + minX = maxX; + maxX = lastMinX; + } + + if (minZ > maxZ) { + double lastMinZ = minZ; + minZ = maxZ; + maxZ = lastMinZ; + } + if (match.getMatchState() == MatchState.STARTING) { + event.setCancelled(true); + return; + } + if (player.getLocation().getX() >= minX && player.getLocation().getX() <= maxX + && player.getLocation().getZ() >= minZ && player.getLocation().getZ() <= maxZ) { + if (event.getBlock().getType() == Material.SNOW_BLOCK && player.getItemInHand().getType() == Material.DIAMOND_SPADE) { + Location blockLocation = event.getBlock().getLocation(); + + event.setCancelled(true); + match.addOriginalBlockChange(event.getBlock().getState()); + Set items = new HashSet<>(); + event.getBlock().getDrops().forEach(itemStack -> items.add(player.getWorld().dropItemNaturally(blockLocation.add(0.0D, 0.25D, 0.0D), itemStack))); + this.plugin.getMatchManager().addDroppedItems(match, items); + event.getBlock().setType(Material.AIR); + } else { + event.setCancelled(true); + } + } else { + event.setCancelled(true); + } + } else { + event.setCancelled(true); + } + } else { + if (player.getGameMode() != GameMode.CREATIVE) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) + public void onBlockPlace(BlockPlaceEvent event) { + Player player = event.getPlayer(); + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + this.plugin.getLogger().warning(player.getName() + "'s player data is null"); + event.setCancelled(true); + return; + } + + if (profile.getState() == ProfileState.FIGHTING) { + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + + // cancel event when match is starting + if (match.getMatchState() == MatchState.STARTING) { + event.setCancelled(true); + return; + } + + if(match == null) { + event.setCancelled(true); + return; + } + + if (!match.getKit().isBuild()) { + event.setCancelled(true); + } else { + double minX = match.getStandaloneArena().getMin().getX(); + double minZ = match.getStandaloneArena().getMin().getZ(); + double maxX = match.getStandaloneArena().getMax().getX(); + double maxZ = match.getStandaloneArena().getMax().getZ(); + if (minX > maxX) { + double lastMinX = minX; + minX = maxX; + maxX = lastMinX; + } + + if (minZ > maxZ) { + double lastMinZ = minZ; + minZ = maxZ; + maxZ = lastMinZ; + } + if (player.getLocation().getX() >= minX && player.getLocation().getX() <= maxX + && player.getLocation().getZ() >= minZ && player.getLocation().getZ() <= maxZ) { + if ((player.getLocation().getY() - match.getStandaloneArena().getA().getY()) < 5.0D && event.getBlockPlaced() != null) { + match.addPlacedBlockLocation(event.getBlockPlaced().getLocation()); + } else { + event.setCancelled(true); + } + } else { + event.setCancelled(true); + } + } + return; + } + + if (!player.isOp() || player.getGameMode() != GameMode.CREATIVE) { + event.setCancelled(true); + } + } + + @EventHandler + public void onBucketEmpty(PlayerBucketEmptyEvent event) { + Player player = event.getPlayer(); + + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (profile == null) { + this.plugin.getLogger().warning(player.getName() + "'s player data is null"); + event.setCancelled(true); + return; + } + + if (profile.getState() == ProfileState.FIGHTING) { + Match match = this.plugin.getMatchManager().getMatch(player.getUniqueId()); + + // cancel event when match is starting + if (match.getMatchState() == MatchState.STARTING) { + event.setCancelled(true); + return; + } + + if (!match.getKit().isBuild()) { + event.setCancelled(true); + } else { + double minX = match.getStandaloneArena().getMin().getX(); + double minZ = match.getStandaloneArena().getMin().getZ(); + double maxX = match.getStandaloneArena().getMax().getX(); + double maxZ = match.getStandaloneArena().getMax().getZ(); + if (minX > maxX) { + double lastMinX = minX; + minX = maxX; + maxX = lastMinX; + } + + if (minZ > maxZ) { + double lastMinZ = minZ; + minZ = maxZ; + maxZ = lastMinZ; + } + if (player.getLocation().getX() >= minX && player.getLocation().getX() <= maxX + && player.getLocation().getZ() >= minZ && player.getLocation().getZ() <= maxZ) { + if ((player.getLocation().getY() - match.getStandaloneArena().getA().getY()) < 5.0D) { + Block block = event.getBlockClicked().getRelative(event.getBlockFace()); + match.addPlacedBlockLocation(block.getLocation()); + } else { + event.setCancelled(true); + } + } else { + event.setCancelled(true); + } + } + return; + } + + if (!player.isOp() || player.getGameMode() != GameMode.CREATIVE) { + event.setCancelled(true); + } + } + + @EventHandler + public void onBlockFromTo(BlockFromToEvent event) { + if (event.getToBlock() == null) { + return; + } + for (StandaloneArena arena : this.plugin.getArenaManager().getArenaMatchUUIDs().keySet()) { + double minX = arena.getMin().getX(); + double minZ = arena.getMin().getZ(); + double maxX = arena.getMax().getX(); + double maxZ = arena.getMax().getZ(); + if (minX > maxX) { + double lastMinX = minX; + minX = maxX; + maxX = lastMinX; + } + + if (minZ > maxZ) { + double lastMinZ = minZ; + minZ = maxZ; + maxZ = lastMinZ; + } + if (event.getToBlock().getX() >= minX && event.getToBlock().getZ() >= minZ + && event.getToBlock().getX() <= maxX && event.getToBlock().getZ() <= maxZ) { + UUID matchUUID = this.plugin.getArenaManager().getArenaMatchUUID(arena); + Match match = this.plugin.getMatchManager().getMatchFromUUID(matchUUID); + + match.addPlacedBlockLocation(event.getToBlock().getLocation()); + break; + } + } + } + + @EventHandler + public void onWorldChange(PlayerTeleportEvent event){ + Location to = event.getTo(); + Location from = event.getFrom(); + + if (to.getWorld() == from.getWorld()) return; + if (!to.getWorld().getName().equalsIgnoreCase("ss")) return; + + TaskUtil.runLater(() -> to.getWorld().getPlayers().forEach(player -> { + player.showPlayer(event.getPlayer()); + event.getPlayer().showPlayer(player); + }), 20L); + } + + @EventHandler + public void onCropsTrampling(PlayerInteractEvent event) { + if (event.getAction() == Action.PHYSICAL + && event.getClickedBlock().getType() == Material.SOIL) { + event.setCancelled(true); + } + } + + @EventHandler + public void onBlockIgnite(BlockIgniteEvent event) { + if (event.getCause() == BlockIgniteEvent.IgniteCause.LIGHTNING) { + event.setCancelled(true); + } + } + + @EventHandler + final void onLeavesDecay(LeavesDecayEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void onWeatherChange(WeatherChangeEvent event) { + if (event.toWeatherState()) { + event.setCancelled(true); + } + } + + @EventHandler + public void onHangingBreak(HangingBreakEvent event) { + event.setCancelled(true); + } + + @EventHandler + final void onBlockBurn(BlockBurnEvent event) { + event.setCancelled(true); + } + + @EventHandler + final void onBlockSpread(BlockSpreadEvent event) { + event.setCancelled(true); + } + + @EventHandler + final void onChunkUnload(ChunkUnloadEvent event) { + event.setCancelled(true); + } + + @EventHandler + final void onCreatureSpawn(CreatureSpawnEvent event) { + event.setCancelled(true); + } + + @EventHandler + final void onWorldLoad(WorldLoadEvent event) { + event.getWorld().getEntities().clear(); + event.getWorld().setDifficulty(Difficulty.HARD); + event.getWorld().setStorm(false); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/profile/manager/ProfileManager.java b/Practice/src/main/java/me/devkevin/practice/profile/manager/ProfileManager.java new file mode 100644 index 0000000..07c3b8d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/manager/ProfileManager.java @@ -0,0 +1,503 @@ +package me.devkevin.practice.profile.manager; + +import club.inverted.chatcolor.CC; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.mongodb.client.MongoCursor; +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.ReplaceOptions; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import me.devkevin.practice.data.PracticeDatabase; +import me.devkevin.practice.file.Config; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.kit.PlayerKit; +import me.devkevin.practice.match.timer.impl.EnderpearlTimer; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.profile.task.SpawnPlayerVisibilityRunnable; +import me.devkevin.practice.queue.QueueEntry; +import me.devkevin.practice.util.InventoryUtil; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.PlayerUtil; +import org.bson.Document; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.json.simple.JSONObject; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ProfileManager { + + private final Practice plugin = Practice.getInstance(); + @Getter private final Map profileData = new ConcurrentHashMap<>(); + + public void createPlayerData(Player player) { + Profile data = new Profile(player.getUniqueId()); + + for (Kit ladder : plugin.getKitManager().getKits()) { + data.getKits().put(ladder.getName(), new PlayerKit[4]); + } + + data.setName(player.getName()); + data.setFollowing(false); + + this.profileData.put(data.getUuid(), data); + } + + public void loadData(Profile profile) { + + + /* + * Loading player kits + */ + Config config = new Config("/players/" + profile.getUuid().toString(), this.plugin); + ConfigurationSection playerKitsSection = config.getConfig().getConfigurationSection("playerkits"); + if (playerKitsSection != null) { + this.plugin.getKitManager().getKits().forEach((kit) -> { + ConfigurationSection kitSection = playerKitsSection.getConfigurationSection(kit.getName()); + if (kitSection != null) { + kitSection.getKeys(false).forEach((kitKey) -> { + Integer kitIndex = Integer.parseInt(kitKey); + String displayName = kitSection.getString(kitKey + ".displayName"); + ItemStack[] contents = (ItemStack[]) ((List) kitSection.get(kitKey + ".contents")).toArray(new ItemStack[0]); + PlayerKit playerKit = new PlayerKit(kit.getName(), kitIndex, contents, displayName); + profile.addPlayerKit(kitIndex, playerKit); + }); + } + + }); + } + + profile.setState(ProfileState.SPAWN); + + /* + * Loading player stats. + */ + Document document = Practice.getInstance().getPracticeDatabase().getProfiles().find(Filters.eq("uuid", profile.getUuid().toString())).first(); + + if (document == null) { + for (Kit kit : this.plugin.getKitManager().getKits()) { + profile.setElo(kit.getName(), 1000); + profile.setWins(kit.getName(), 0); + profile.setLosses(kit.getName(), 0); + profile.setCurrentWinstreak(kit.getName(), 0); + profile.setHighestWinStreak(kit.getName(), 0); + } + + this.saveData(profile); + return; + } + + profile.setName(document.getString("username")); + + Document statsDocument = (Document) document.get("stats"); + Document globalDocument = (Document) document.get("global"); + Document loadoutsDocument = (Document) document.get("loadouts"); + + if (globalDocument == null) { + profile.setGlobalElo(1000); + profile.setMatchesPlayed(0); + profile.setGlobalWinStreak(0); + profile.setGlobalHighestWinStreak(0); + return; + } + + for (String key : loadoutsDocument.keySet()) { + Kit ladder = Practice.getInstance().getKitManager().getKit(key); + if (ladder == null) { + continue; + } + + JsonArray kitsArray = plugin.getJsonParser().parse(loadoutsDocument.getString(key)).getAsJsonArray(); + PlayerKit[] kits = new PlayerKit[4]; + for (JsonElement kitElement : kitsArray) { + JsonObject kitObject = kitElement.getAsJsonObject(); + PlayerKit kit = new PlayerKit(kitObject.get("name").getAsString(), kitObject.get("index").getAsInt(), InventoryUtil.deserializeInventory(kitObject.get("contents").getAsString()), kitObject.get("name").getAsString()); + kit.setContents(InventoryUtil.deserializeInventory(kitObject.get("contents").getAsString())); + kits[kitObject.get("index").getAsInt()] = kit; + } + + profile.getKits().put(ladder.getName(), kits); + } + + profile.setGlobalElo(globalDocument.getInteger("globalElo")); + profile.setMatchesPlayed(globalDocument.getInteger("matchesPlayed")); + profile.setGlobalWinStreak(globalDocument.getInteger("globalWinStreak")); + profile.setGlobalHighestWinStreak(globalDocument.getInteger("highestGlobalWinStreak")); + + statsDocument.keySet().forEach(key -> { + Document ladderDocument = (Document) statsDocument.get(key); + if (ladderDocument == null) { + System.out.println("Ladder document is null for ladder " + key); + return; + } + + if (ladderDocument.containsKey("elo")) { + profile.getRankedElo().put(key, ladderDocument.getInteger("elo")); + } + if (ladderDocument.containsKey("wins")) { + profile.getRankedWins().put(key, ladderDocument.getInteger("wins")); + } + if (ladderDocument.containsKey("losses")) { + profile.getRankedLosses().put(key, ladderDocument.getInteger("losses")); + } + if (ladderDocument.containsKey("currentStreak")) { + profile.getCurrentWinstreak().put(key, ladderDocument.getInteger("currentStreak")); + } + if (ladderDocument.containsKey("highestStreak")) { + profile.getHighestWinStreak().put(key, ladderDocument.getInteger("highestStreak")); + } + }); + + profile.setDataLoaded(true); + } + + public void saveData(Profile profile) { + if (profile == null) return; + if (!profile.isDataLoaded()) return; + + Config config = new Config("/players/" + profile.getUuid().toString(), this.plugin); + + /* + * Saving player kits + */ + this.plugin.getKitManager().getKits().forEach(kit -> { + Map playerKits = profile.getPlayerKits(kit.getName()); + + if (playerKits != null) { + playerKits.forEach((key, value) -> { + config.getConfig().set("playerkits." + kit.getName() + "." + key + ".displayName", value.getDisplayName()); + config.getConfig().set("playerkits." + kit.getName() + "." + key + ".contents", value.getContents()); + }); + + config.getConfig().set("profile.settings.duelRequests", profile.getOptions().isDuelRequests()); + config.getConfig().set("profile.settings.scoreboard", profile.getOptions().isScoreboard()); + config.getConfig().set("profile.settings.partyInvites", profile.getOptions().isPartyInvites()); + config.getConfig().set("profile.settings.spectators", profile.getOptions().isSpectators()); + config.getConfig().set("profile.settings.time", profile.getOptions().getTime().name()); + } + }); + + config.save(); + + /* + * Saving player stats. + */ + Document document = new Document(); + Document statsDocument = new Document(); + Document globalDocument = new Document(); + Document loadoutsDocument = new Document(); + + profile.getCurrentWinstreak().forEach((key, value) -> { + if (key.equalsIgnoreCase("HCF")) return; + + Document ladderDocument; + if (statsDocument.containsKey(key)) { + ladderDocument = (Document) statsDocument.get(key); + } else { + ladderDocument = new Document(); + } + + ladderDocument.put("currentStreak", value); + statsDocument.put(key, ladderDocument); + }); + + profile.getHighestWinStreak().forEach((key, value) -> { + if (key.equalsIgnoreCase("HCF")) return; + + Document ladderDocument; + if (statsDocument.containsKey(key)) { + ladderDocument = (Document) statsDocument.get(key); + } else { + ladderDocument = new Document(); + } + + ladderDocument.put("highestStreak", value); + statsDocument.put(key, ladderDocument); + }); + + profile.getRankedWins().forEach((key, value) -> { + if (key.equalsIgnoreCase("HCF")) return; + + Document ladderDocument; + if (statsDocument.containsKey(key)) { + ladderDocument = (Document) statsDocument.get(key); + } else { + ladderDocument = new Document(); + } + + ladderDocument.put("wins", value); + statsDocument.put(key, ladderDocument); + }); + + profile.getRankedLosses().forEach((key, value) -> { + if (key.equalsIgnoreCase("HCF")) return; + + Document ladderDocument; + if (statsDocument.containsKey(key)) { + ladderDocument = (Document) statsDocument.get(key); + } else { + ladderDocument = new Document(); + } + + ladderDocument.put("losses", value); + statsDocument.put(key, ladderDocument); + }); + + profile.getRankedElo().forEach((key, value) -> { + if (key.equalsIgnoreCase("HCF")) return; + + Document ladderDocument; + if (statsDocument.containsKey(key)) { + ladderDocument = (Document) statsDocument.get(key); + } else { + ladderDocument = new Document(); + } + + ladderDocument.put("elo", value); + statsDocument.put(key, ladderDocument); + }); + + int kits = 0, count = 0; + for (Kit kit : this.plugin.getKitManager().getRankedKits()) { + if (profile.getRankedElo().get(kit.getName()) == null) continue; + kits += profile.getRankedElo().get(kit.getName()); + count++; + } + if (kits == 1) kits = 0; + if (count == 0) count = 1; + + profile.getKits().forEach((key, value) -> { + JsonArray kitsArray = new JsonArray(); + for (int i = 0; i < 4; i++) { + PlayerKit kit = value[i]; + if (kit != null) { + JsonObject kitObject = new JsonObject(); + kitObject.addProperty("index", i); + kitObject.addProperty("name", kit.getName()); + kitObject.addProperty("contents", InventoryUtil.serializeInventory(kit.getContents())); + + kitsArray.add(kitObject); + } + } + + loadoutsDocument.put(key, kitsArray.toString()); + }); + + globalDocument.put("globalElo", (kits / count)); + globalDocument.put("matchesPlayed", profile.getMatchesPlayed()); + + globalDocument.put("globalWinStreak", profile.getGlobalWinStreak()); + globalDocument.put("highestGlobalWinStreak", profile.getGlobalHighestWinStreak()); + + document.put("uuid", profile.getUuid().toString()); + document.put("username", profile.getName()); + document.put("stats", statsDocument); + document.put("global", globalDocument); + document.put("loadouts", loadoutsDocument); + + JSONObject data = new JSONObject(); + + for (Kit kit : plugin.getKitManager().getRankedKits()) { + JSONObject kitData = new JSONObject(); + + kitData.put("elo", profile.getElo(kit.getName())); + kitData.put("party-elo", profile.getPartyElo(kit.getName())); + + data.put(kit, kitData); + } + + Practice.getInstance().getPracticeDatabase().getProfiles().replaceOne(Filters.eq("uuid", profile.getUuid().toString()), document, new ReplaceOptions().upsert(true)); + } + + + public void removePlayerData(UUID uuid) { + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () + -> { + ProfileManager.this.saveData(ProfileManager.this.profileData.get(uuid)); + ProfileManager.this.profileData.remove(uuid); + }); + } + + public Collection getAllData() { + return profileData.values(); + } + + public Profile getProfileData(UUID uuid) { + + if (Bukkit.getPlayer(uuid) != null) { + if (!this.profileData.containsKey(uuid)) { + createPlayerData(Bukkit.getPlayer(uuid)); + } + } + + return this.profileData.get(uuid); + } + + public void giveSpawnItems(Player player) { + boolean inParty = this.plugin.getPartyManager().getParty(player.getUniqueId()) != null; + boolean inEvent = this.plugin.getEventManager().getEventPlaying(player) != null; + boolean isRematching = this.plugin.getMatchManager().isRematching(player.getUniqueId()); + ItemStack[] items = this.plugin.getHotbarItem().getSpawnItems(); + + boolean inQueue = plugin.getQueue().getQueueEntry(player.getUniqueId()) != null; + + if (inParty) { + items = this.plugin.getHotbarItem().getPartyItems(); + } else if (inEvent) { + items = this.plugin.getHotbarItem().getEventItems(); + } else if (inQueue) { + items = this.plugin.getHotbarItem().getQueueItems(); + } + + player.getInventory().setContents(items); + if (inParty) { + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + player.getInventory().setItem(3, new ItemBuilder(Material.NETHER_STAR) + .name(LandCore.getInstance().getProfileManager().getProfile(party.getLeader()).getGrant().getRank().getColor() + Bukkit.getPlayer(party.getLeader()).getName() + CC.GRAY + "'s Party") + .build()); + } + + if (plugin.getMatchManager().hasPlayAgainRequest(player.getUniqueId())) { + player.getInventory().addItem(plugin.getHotbarItem().getPlayAgain()); + } + + player.updateInventory(); + } + + public Kit kit; + + public void sendToSpawn(Player player) { + Profile profile = ProfileManager.this.getProfileData(player.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + QueueEntry queue = this.plugin.getQueue().getQueueEntry(player.getUniqueId()); + + if (queue != null) { + profile.setState(ProfileState.QUEUE); + } else if (party != null) { + profile.setState(ProfileState.PARTY); + } else { + profile.setState(ProfileState.SPAWN); + } + + if (!player.isOnline()) { + return; + } + + this.plugin.getTimerManager().getTimer(EnderpearlTimer.class).clearCooldown(player.getUniqueId()); + + PlayerUtil.reset(player); + + giveSpawnItems(player); + + player.teleport(this.plugin.getCustomLocationManager().getSpawn().toBukkitLocation()); + + // tp player to random spawns + /*Random random = new Random(); + int randomIndex = random.nextInt(getSpawnsLocations().length); + player.teleport(getSpawnsLocations()[randomIndex].toBukkitLocation());*/ + + if (party != null) { + party.getMembers().stream().map(Bukkit::getPlayer).filter(Objects::nonNull).forEach(member -> { + member.showPlayer(player); + player.showPlayer(member); + }); + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile.hasDonor()) { + player.setAllowFlight(true); + player.setFlying(true); + } + + updatePlayerView(); + } + + public void sendToSpawnAndResetButNotTP(Player player) { + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + QueueEntry queue = this.plugin.getQueue().getQueueEntry(player.getUniqueId()); + + if (queue != null) { + profile.setState(ProfileState.QUEUE); + } else if (party != null) { + profile.setState(ProfileState.PARTY); + } else { + profile.setState(ProfileState.SPAWN); + } + + if (!player.isOnline()) { + return; + } + + this.plugin.getTimerManager().getTimer(EnderpearlTimer.class).clearCooldown(player.getUniqueId()); + + PlayerUtil.reset(player); + + giveSpawnItems(player); + + // we won't that when players left to queue or something don't get teleported again to spawn + if (!player.getLocation().getWorld().getName() + .equals(plugin.getCustomLocationManager().getSpawn().toBukkitLocation().getWorld().getName())) { + player.teleport(plugin.getCustomLocationManager().getSpawn().toBukkitLocation()); + } + + if (party != null) { + party.getMembers().stream().map(Bukkit::getPlayer).filter(Objects::nonNull).forEach(member -> { + member.showPlayer(player); + player.showPlayer(member); + }); + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile.hasDonor()) { + player.setAllowFlight(true); + player.setFlying(true); + } + + updatePlayerView(); + } + + /*public CustomLocation[] getSpawnsLocations() { + CustomLocation[] array = new CustomLocation[4]; + array[0] = Practice.getInstance().getCustomLocationManager().getSpawn(); + array[1] = Practice.getInstance().getCustomLocationManager().getSpawn2(); + array[2] = Practice.getInstance().getCustomLocationManager().getSpawn3(); + array[3] = Practice.getInstance().getCustomLocationManager().getSpawn4(); + return array; + }*/ + + public MongoCursor getPlayersSortByLadderElo(Kit ladder) { + final Document sort = new Document(); + sort.put("stats." + ladder.getName() + ".elo", -1); + + return PracticeDatabase.getInstance().getProfiles().find().sort(sort).limit(10).iterator(); + } + + public MongoCursor getPlayersSortedByDocumentElo(String document) { + final Document sort = new Document(); + sort.put("global." + document, -1); + + return PracticeDatabase.getInstance().getProfiles().find().sort(sort).limit(10).iterator(); + } + + public void updatePlayerView() { + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, new SpawnPlayerVisibilityRunnable()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/menu/StatsMenu.java b/Practice/src/main/java/me/devkevin/practice/profile/menu/StatsMenu.java new file mode 100644 index 0000000..f60833e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/menu/StatsMenu.java @@ -0,0 +1,56 @@ +package me.devkevin.practice.profile.menu; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 08/02/2023 @ 3:20 + * StatsMenu / me.devkevin.practice.elo.menu / Practice + */ +@Getter +public class StatsMenu { + private final Practice plugin = Practice.getInstance(); + + public InventoryUI getStatsMenu(Player target) { + InventoryUI menu = new InventoryUI(LandCore.getInstance().getProfileManager().getProfile(target.getUniqueId()).getGrant().getRank().getColor() + target.getName() + CC.YELLOW + "'s stats", 2); + + Profile profile = getPlugin().getProfileManager().getProfileData(target.getUniqueId()); + + for (Kit kit : getPlugin().getKitManager().getKits()) { + List lore = new ArrayList<>(); + String kitName = kit.getName(); + + final double wins = profile.getGlobalWins(); + final double losses = profile.getGlobalLosses(); + final double wlr = wins == 0 || losses == 0 ? 0.0 : wins / losses; + + lore.add(CC.YELLOW + "Elo: " + CC.LIGHT_PURPLE + profile.getElo(kitName)); + lore.add(CC.YELLOW + "Wins: " + CC.LIGHT_PURPLE + profile.getWins(kitName)); + lore.add(CC.YELLOW + "Losses: " + CC.LIGHT_PURPLE + profile.getLosses(kitName)); + lore.add(CC.YELLOW + "W/L Ratio: " + CC.LIGHT_PURPLE + wlr); + + menu.addItem(new InventoryUI.AbstractClickableItem(new ItemBuilder(kit.getIcon().getType()).name(CC.LIGHT_PURPLE + kit.getName()) + .durability(kit.getIcon().getDurability()) + .lore(lore).build()) { + @Override + public void onClick(InventoryClickEvent event) { + + } + }); + } + + return menu; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/state/ProfileState.java b/Practice/src/main/java/me/devkevin/practice/profile/state/ProfileState.java new file mode 100644 index 0000000..7d82b6c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/state/ProfileState.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.profile.state; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public enum ProfileState { + + LOADING, + SPAWN, + QUEUE, + EVENT, + FIGHTING, + PARTY, + SPECTATING, + EDITING, + STAFF, + FACTION, + BOT_FIGHTING, + + // Match system (25/04/2021) + SoloUnranked, + RankedSolo +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/profile/task/DataLoaderWorkerRunnable.java b/Practice/src/main/java/me/devkevin/practice/profile/task/DataLoaderWorkerRunnable.java new file mode 100644 index 0000000..63e02f5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/task/DataLoaderWorkerRunnable.java @@ -0,0 +1,33 @@ +package me.devkevin.practice.profile.task; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; + +/** + * Copyright 12/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DataLoaderWorkerRunnable implements Runnable { + + private final Practice plugin = Practice.getInstance(); + + @Override + public void run() { + + while (true) { + try { + Thread.sleep(1000L); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + for (Profile profile : this.plugin.getProfileManager().getAllData()) { + if (!profile.isDataLoaded()) { + this.plugin.getProfileManager().loadData(profile); + profile.setDataLoaded(true); + } + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/task/ExpBarTask.java b/Practice/src/main/java/me/devkevin/practice/profile/task/ExpBarTask.java new file mode 100644 index 0000000..4225684 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/task/ExpBarTask.java @@ -0,0 +1,44 @@ +package me.devkevin.practice.profile.task; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.timer.impl.EnderpearlTimer; +import org.bukkit.entity.Player; + +import java.util.UUID; + +/** + * Copyright 15/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ExpBarTask implements Runnable { + + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + @Override + public void run() { + + EnderpearlTimer timer = Practice.getInstance().getTimerManager().getTimer(EnderpearlTimer.class); + + for (UUID uuid : timer.getCooldowns().keySet()) { + Player player = Practice.getInstance().getServer().getPlayer(uuid); + + if (player != null) { + long time = timer.getRemaining(player); + int seconds = (int) Math.round((double) time / 1000.0D); + + player.setLevel(seconds); + player.setExp((float) time / 15000.0F); + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/profile/task/ProfileSaveDataTask.java b/Practice/src/main/java/me/devkevin/practice/profile/task/ProfileSaveDataTask.java new file mode 100644 index 0000000..8dae6e5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/task/ProfileSaveDataTask.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.profile.task; + +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import org.bukkit.Bukkit; +import org.bukkit.command.ConsoleCommandSender; + +/** + * Copyright 09/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@RequiredArgsConstructor +public class ProfileSaveDataTask implements Runnable { + + private final Practice plugin = Practice.getInstance(); + private static final ConsoleCommandSender console = Bukkit.getServer().getConsoleSender(); + + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + @Override + public void run() { + int amount = 0; + + for (Profile profile : this.plugin.getProfileManager().getAllData()) { + this.plugin.getProfileManager().saveData(profile); + ++amount; + } + + console.sendMessage("saved " + amount + " players databases"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/profile/task/SpawnPlayerVisibilityRunnable.java b/Practice/src/main/java/me/devkevin/practice/profile/task/SpawnPlayerVisibilityRunnable.java new file mode 100644 index 0000000..cddf3b2 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/profile/task/SpawnPlayerVisibilityRunnable.java @@ -0,0 +1,88 @@ +package me.devkevin.practice.profile.task; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class SpawnPlayerVisibilityRunnable extends BukkitRunnable { + private final Practice plugin = Practice.getInstance(); + + private final static boolean SHOW_PLAYERS = true; //# This will override the player-visibility on spawn and show all the online players in the server. + + @Override + public void run() { + + if (SHOW_PLAYERS) { + this.plugin.getServer().getOnlinePlayers().forEach(player -> { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + if (profile.isInSpawn() || profile.isInQueue()) { + this.plugin.getServer().getOnlinePlayers().forEach(op -> this.plugin.getServer().getScheduler().runTask(this.plugin, () -> { + if (op == null) { + return; + } + + Profile onlineData = this.plugin.getProfileManager().getProfileData(op.getUniqueId()); + if (onlineData == null) { + return; + } + + if (onlineData.isInSpawn() || profile.isInQueue()) { + player.showPlayer(op); + op.showPlayer(player); + } + })); + } + }); + } else { + this.plugin.getServer().getOnlinePlayers().forEach(player -> { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + if (profile.isInSpawn()) { + if (profile.getOptions().isVisibility()) { + this.plugin.getServer().getOnlinePlayers().forEach(op -> this.plugin.getServer().getScheduler().runTask(this.plugin, () -> { + if (op == null) { + return; + } + + Profile onlineData = this.plugin.getProfileManager().getProfileData(op.getUniqueId()); + if (onlineData == null) { + return; + } + + if (onlineData.getState() == ProfileState.SPAWN && op.hasPermission("practice.user.spawn-visibility")) { + player.showPlayer(op); + } else { + player.hidePlayer(op); + } + })); + } else { + this.plugin.getServer().getOnlinePlayers().forEach(op -> this.plugin.getServer().getScheduler().runTask(this.plugin, () -> { + if (op == null) { + return; + } + + Profile onlineData = this.plugin.getProfileManager().getProfileData(op.getUniqueId()); + if (onlineData == null) { + return; + } + + if (onlineData.getState() == ProfileState.SPAWN) { + player.hidePlayer(op); + } + })); + } + } + }); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/queue/Queue.java b/Practice/src/main/java/me/devkevin/practice/queue/Queue.java new file mode 100644 index 0000000..5140afa --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/queue/Queue.java @@ -0,0 +1,404 @@ +package me.devkevin.practice.queue; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.arena.Arena; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.util.PlayerUtil; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Copyright 11/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@Setter +public class Queue { + + private final Map queued = new ConcurrentHashMap<>(); + private final Map playerQueueTime = new HashMap<>(); + + private final Practice plugin = Practice.getInstance(); + + private boolean rankedEnabled = true; + + public Queue() { + plugin.getServer().getScheduler().runTaskTimer(plugin, () -> { + this.queued.forEach((key, value) -> { + if (!value.isFound()) { + if (value.isParty()) { + this.findPartyMatch(plugin.getPartyManager().getParty(key), value.getKitName(), value.getElo(), value.getQueueType()); + } else { + this.findMatch(plugin.getServer().getPlayer(key), value.getKitName(), value.getElo(), value.getQueueType()); + } + } + }); + }, 20L, 20L); + } + + public void addPlayer(Player player, Profile profile, String kitName, QueueType type) { + if (type != QueueType.UN_RANKED && !this.rankedEnabled) { + player.sendMessage(CC.RED + "Ranked is currently disabled until the server restarts."); + player.closeInventory(); + return; + } + + profile.setState(ProfileState.QUEUE); + + int elo = (type == QueueType.RANKED) ? profile.getElo(kitName) : 0; + + QueueEntry entry = new QueueEntry(type, kitName, elo, false); + + this.queued.put(profile.getUuid(), entry); + this.giveQueueItems(player); + + + String message = (type != QueueType.UN_RANKED ? CC.YELLOW + "You were added to the " + CC.GOLD + type.getName() + " " + kitName + CC.YELLOW + + " queue" + + " with " + CC.GOLD + elo + CC.YELLOW + " elo." : + CC.YELLOW + "You were added to the " + CC.GOLD + "Unranked " + kitName + CC.YELLOW + " queue."); + + + player.sendMessage(message); + + this.playerQueueTime.put(player.getUniqueId(), System.currentTimeMillis()); + + if (type.isRanked()) { + player.sendMessage(CC.YELLOW + "Searching in ELO range " + CC.GOLD + + (profile.getEloRange() == -1 + ? "Unrestricted" + : "[" + Math.max(elo - profile.getEloRange() / 2, 0) + + " -> " + Math.max(elo + profile.getEloRange() / 2, 0) + "]")); + } + } + + private void giveQueueItems(Player player) { + player.closeInventory(); + player.getInventory().setContents(this.plugin.getHotbarItem().getQueueItems()); + player.updateInventory(); + } + + public QueueEntry getQueueEntry(UUID uuid) { + return this.queued.get(uuid); + } + + public long getPlayerQueueTime(UUID uuid) { + return this.playerQueueTime.get(uuid); + } + + public int getQueueSize(String ladder, QueueType type) { + return (int) this.queued.entrySet().stream().filter(entry -> entry.getValue().getQueueType() == type).filter(entry -> entry.getValue().getKitName().equals(ladder)).count(); + } + + public int getQueueSize() { + return this.queued.entrySet().size(); + } + + public int getQueueSize(QueueType type) { + return (int) this.queued.entrySet().stream().filter(entry -> entry.getValue().getQueueType() == type).count(); + } + + private void findMatch(Player player, String kitName, int elo, QueueType type) { + long queueTime = System.currentTimeMillis() - this.playerQueueTime.get(player.getUniqueId()); + + if (this.playerQueueTime.containsKey(player.getUniqueId()) && this.playerQueueTime.get(player.getUniqueId()) == null) { + player.kickPlayer("Player data is null. Please re-connect."); + player.sendMessage(CC.RED + "Please re-connect."); + return; + } + + Profile playerData = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (playerData == null) { + plugin.getLogger().warning(player.getName() + "'s player data is null" + "(" + this.getClass().getName() + ")"); + return; + } + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + int eloRange = coreProfile.hasRank(Rank.BASIC) ? playerData.getEloRange() : -1; + int pingRange = coreProfile.hasRank(Rank.DIAMOND) ? playerData.getPingRange() : -1; + int seconds = Math.round(queueTime / 1000L); + + if (seconds > 5 && type != QueueType.UN_RANKED) { + if (pingRange != -1) { + pingRange += (seconds - 5) * 25; + } + + if (eloRange != -1) { + eloRange += seconds * 50; + + if (eloRange >= 3000) { + eloRange = 3000; + } else { + player.sendMessage( + CC.YELLOW + "Searching in ELO range " + + CC.GOLD + (eloRange == -1 ? "Unrestricted" + : "[" + Math.max(elo - eloRange / 2, 0) + " -> " + + Math.max(elo + eloRange / 2, 0) + "]")); + } + } + } + + if (eloRange == -1) { + eloRange = Integer.MAX_VALUE; + } + + if (pingRange == -1) { + pingRange = Integer.MAX_VALUE; + } + + int ping = 0; + + for (Map.Entry queueData : this.queued.entrySet()) { + UUID opponent = queueData.getKey(); + QueueEntry queueEntry = queueData.getValue(); + + if (opponent == player.getUniqueId()) { + continue; + } + + if (!queueEntry.getKitName().equals(kitName)) { + continue; + } + if (queueEntry.getQueueType() != type) { + continue; + } + if (queueEntry.isParty()) { + continue; + } + if (queueEntry.isFound()) { + continue; + } + + Player opponentPlayer = this.plugin.getServer().getPlayer(opponent); + Profile opponentProfile = this.plugin.getProfileManager().getProfileData(opponent); + + if (opponentProfile.getState() == ProfileState.FIGHTING) { + continue; + } + + if (playerData.getState() == ProfileState.FIGHTING) { + continue; + } + + int eloDiff = Math.abs(queueEntry.getElo() - elo); + + if (type.isRanked()) { + if (eloDiff > eloRange) { + continue; + } + + CoreProfile opponentLOL = LandCore.getInstance().getProfileManager().getProfile(opponent); + long opponentQueueTime = System.currentTimeMillis() - + this.playerQueueTime.get(opponentPlayer.getUniqueId()); + int opponentEloRange = opponentLOL.hasRank(Rank.BASIC) ? opponentProfile.getEloRange() : -1; + int opponentPingRange = opponentLOL.hasRank(Rank.DIAMOND) ? opponentProfile.getPingRange() : -1; + int opponentSeconds = Math.round(opponentQueueTime / 1000L); + if (opponentSeconds > 5) { + if (opponentPingRange != -1) { + opponentPingRange += (opponentSeconds - 5) * 25; + } + + if (opponentEloRange != -1) { + opponentEloRange += opponentSeconds * 50; + if (opponentEloRange >= 3000) { + opponentEloRange = 3000; + } + } + } + + if (opponentEloRange == -1) { + opponentEloRange = Integer.MAX_VALUE; + } + + if (opponentPingRange == -1) { + opponentPingRange = Integer.MAX_VALUE; + } + + if (eloDiff > opponentEloRange) { + continue; + } + + int pingDiff = Math.abs(0 - ping); + + if (type == QueueType.RANKED || type == QueueType.FACTION) { + if (pingDiff > opponentPingRange) { + continue; + } + if (pingDiff > pingRange) { + continue; + } + } + } + + Kit kit = plugin.getKitManager().getKit(kitName); + Arena arena = plugin.getArenaManager().getRandomArena(kit, playerData.getLastArenaPlayed()); + + if (arena == null) { + player.sendMessage(ChatColor.RED + "There are no arenas available for this kit."); + return; + } + + if (type.isRanked()) { + player.sendMessage(""); + player.sendMessage(CC.translate("&6&lRanked Match")); + player.sendMessage(CC.translate("&7\u25CF &eMap: &6" + arena.getName())); + player.sendMessage(CC.translate("&7\u25CF &eOpponent: " + LandCore.getInstance().getProfileManager().getProfile(opponentPlayer.getUniqueId()).getGrant().getRank().getColor() + opponentPlayer.getName())); + player.sendMessage(CC.translate("&7\u25CF &eELO: " + (this.queued.get(player.getUniqueId()).getElo() > this.queued.get(opponentPlayer.getUniqueId()).getElo() ? ChatColor.RED: ChatColor.GREEN) + this.queued.get(opponentPlayer.getUniqueId()).getElo() + ChatColor.GRAY + " (" + (this.queued.get(player.getUniqueId()).getElo() > this.queued.get(opponentPlayer.getUniqueId()).getElo() ? ChatColor.RED + "-" : ChatColor.GREEN + "+") + ((Math.max(this.queued.get(opponentPlayer.getUniqueId()).getElo(), this.queued.get(player.getUniqueId()).getElo()) - Math.min(this.queued.get(opponentPlayer.getUniqueId()).getElo(), this.queued.get(player.getUniqueId()).getElo()))) + ChatColor.GRAY + ")")); + player.sendMessage(CC.translate("&7\u25CF &ePing: &6" + PlayerUtil.getPing(opponentPlayer) + " ms")); + player.sendMessage(""); + + opponentPlayer.sendMessage(""); + opponentPlayer.sendMessage(CC.translate("&6&lRanked Match")); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &eMap: &6" + arena.getName())); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &eOpponent:" + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName())); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &eELO: " + (this.queued.get(opponentPlayer.getUniqueId()).getElo() > this.queued.get(player.getUniqueId()).getElo() ? ChatColor.RED : ChatColor.GREEN) + this.queued.get(player.getUniqueId()).getElo() + ChatColor.GRAY + " (" + (this.queued.get(opponentPlayer.getUniqueId()).getElo() > this.queued.get(player.getUniqueId()).getElo() ? ChatColor.RED + "-" : ChatColor.GREEN + "+") + ((Math.max(this.queued.get(player.getUniqueId()).getElo(), this.queued.get(opponentPlayer.getUniqueId()).getElo()) - Math.min(this.queued.get(player.getUniqueId()).getElo(), this.queued.get(opponentPlayer.getUniqueId()).getElo()))) + ChatColor.GRAY + ")")); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &ePing: &6" + PlayerUtil.getPing(player) + " ms")); + opponentPlayer.sendMessage(""); + } else { + player.sendMessage(""); + player.sendMessage(CC.translate("&6&lUnRanked Match")); + player.sendMessage(CC.translate("&7\u25CF &eMap: &6" + arena.getName())); + player.sendMessage(CC.translate("&7\u25CF &eOpponent: " + LandCore.getInstance().getProfileManager().getProfile(opponentPlayer.getUniqueId()).getGrant().getRank().getColor() + opponentPlayer.getName())); + player.sendMessage(CC.translate("&7\u25CF &ePing: &6" + PlayerUtil.getPing(opponentPlayer) + " ms")); + player.sendMessage(""); + + opponentPlayer.sendMessage(""); + opponentPlayer.sendMessage(CC.translate("&6&lUnRanked Match")); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &eMap: &6" + arena.getName())); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &eOpponent: " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName())); + opponentPlayer.sendMessage(CC.translate("&7\u25CF &ePing: &6" + PlayerUtil.getPing(player) + " ms")); + opponentPlayer.sendMessage(""); + } + + MatchTeam teamA = new MatchTeam(player.getUniqueId(), Collections.singletonList(player.getUniqueId()), 0); + MatchTeam teamB = new MatchTeam(opponentPlayer.getUniqueId(), Collections.singletonList(opponentPlayer.getUniqueId()), 1); + Match match = new Match(arena, kit, type, teamA, teamB); + + QueueEntry queueEntry1 = queued.get(player.getUniqueId()); + if (queueEntry1 != null) { // should not be null, but, things happen.gi + queueEntry1.setFound(true); + } + queueEntry.setFound(true); + + this.queued.remove(player.getUniqueId()); + this.queued.remove(opponentPlayer.getUniqueId()); + + this.playerQueueTime.remove(player.getUniqueId()); + this.playerQueueTime.remove(opponentPlayer.getUniqueId()); + + plugin.getMatchManager().createMatch(match); + + return; + } + } + + public void removePlayerFromQueue(Player player) { + QueueEntry entry = this.queued.get(player.getUniqueId()); + + this.queued.remove(player.getUniqueId()); + + this.plugin.getProfileManager().sendToSpawnAndResetButNotTP(player); + + player.sendMessage(ChatColor.RED + "You have left the " + entry.getQueueType().getName() + " " + entry.getKitName() + " queue."); + } + + public void removePartyFromQueue(Party party) { + QueueEntry entry = this.queued.get(party.getLeader()); + + this.queued.remove(party.getLeader()); + + party.members().forEach(this.plugin.getProfileManager()::sendToSpawnAndResetButNotTP); + + String type = entry.getQueueType().isRanked() ? "Ranked" : "Unranked"; + + party.broadcast(ChatColor.YELLOW + "You party has left the " + type + " " + entry.getKitName() + " queue."); + } + + private void findPartyMatch(Party partyA, String kitName, int elo, QueueType type) { + Profile practicePlayerData = this.plugin.getProfileManager().getProfileData(partyA.getLeader()); + UUID opponent = this.queued.entrySet().stream() + .filter(entry -> entry.getKey() != partyA.getLeader()) + .filter(entry -> this.plugin.getProfileManager().getProfileData(entry.getKey()) != null) + .filter(entry -> this.plugin.getProfileManager().getProfileData(entry.getKey()).getState() == ProfileState.QUEUE) + .filter(entry -> entry.getValue().isParty()) + .filter(entry -> entry.getValue().getQueueType() == type) + .filter(entry -> !type.isRanked()) + .filter(entry -> entry.getValue().getKitName().equals(kitName)) + .map(Map.Entry::getKey) + .findFirst().orElse(null); + + if (opponent == null) { + return; + } + + Profile opponentData = this.plugin.getProfileManager().getProfileData(opponent); + if (opponentData.getState() == ProfileState.FIGHTING) { + return; + } + if (practicePlayerData.getState() == ProfileState.FIGHTING) { + return; + } + + Player leaderA = this.plugin.getServer().getPlayer(partyA.getLeader()); + Player leaderB = this.plugin.getServer().getPlayer(opponent); + + Kit kit = this.plugin.getKitManager().getKit(kitName); + Arena arena = this.plugin.getArenaManager().getRandomArena(kit, practicePlayerData.getLastArenaPlayed()); + Party partyB = this.plugin.getPartyManager().getParty(opponent); + + List playersA = new ArrayList<>(partyA.getMembers()); + List playersB = new ArrayList<>(partyB.getMembers()); + + MatchTeam teamA = new MatchTeam(leaderA.getUniqueId(), playersA, 0); + MatchTeam teamB = new MatchTeam(leaderB.getUniqueId(), playersB, 1); + + Match match = new Match(arena, kit, type, teamA, teamB); + this.plugin.getMatchManager().createMatch(match); + + String party1FoundMatchMessage; + String party2FoundMatchMessage; + + if (type.isRanked()) { + party1FoundMatchMessage = CC.YELLOW + "Found ranked match: " + CC.GREEN + leaderA.getName() + + "'s party (" + + elo + " elo)" + CC.YELLOW + " vs. " + + CC.RED + leaderB.getName() + "'s Party (" + + this.queued.get(leaderB.getUniqueId()).getElo() + " elo)"; + party2FoundMatchMessage = CC.YELLOW + "Found ranked match: " + CC.GREEN + leaderB.getName() + "'s party (" + + this.queued.get(leaderB.getUniqueId()).getElo() + " elo)" + CC.YELLOW + + " vs. " + + CC.RED + leaderA.getName() + "'s Party (" + elo + " elo)"; + } else { + party1FoundMatchMessage = CC.YELLOW + "Found unranked match: " + CC.GREEN + leaderA.getName() + + "'s party" + + CC.YELLOW + " vs. " + + CC.RED + leaderB.getName() + "'s party"; + party2FoundMatchMessage = CC.YELLOW + "Found unranked match: " + CC.GREEN + leaderB.getName() + + "'s party" + + CC.YELLOW + " vs. " + + CC.RED + leaderA.getName() + "'s party"; + } + + leaderA.sendMessage(party1FoundMatchMessage); + leaderB.sendMessage(party2FoundMatchMessage); + + this.queued.remove(partyA.getLeader()); + this.queued.remove(partyB.getLeader()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/queue/QueueEntry.java b/Practice/src/main/java/me/devkevin/practice/queue/QueueEntry.java new file mode 100644 index 0000000..49eaffc --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/queue/QueueEntry.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.queue; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; + +/** + * Copyright 12/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@Setter +@RequiredArgsConstructor +public class QueueEntry { + + private final QueueType queueType; + private final String kitName; + + private final int elo; + + private final boolean party; + + private boolean found = false; // prevent player joining multiple games with 1 queue. +} diff --git a/Practice/src/main/java/me/devkevin/practice/queue/QueueType.java b/Practice/src/main/java/me/devkevin/practice/queue/QueueType.java new file mode 100644 index 0000000..7f9db23 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/queue/QueueType.java @@ -0,0 +1,32 @@ +package me.devkevin.practice.queue; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Copyright 11/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +@RequiredArgsConstructor +public enum QueueType { + + UN_RANKED("Unranked"), + RANKED("Ranked"), + FACTION("Faction"); + + private final String name; + + public boolean isRanked() { + return this == RANKED; + } + + public boolean isUnranked() { + return this == UN_RANKED; + } + + public boolean isFaction() { + return this == FACTION; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu.java b/Practice/src/main/java/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu.java new file mode 100644 index 0000000..c019a68 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu.java @@ -0,0 +1,192 @@ +package me.devkevin.practice.queue.menu.party; + +import lombok.Getter; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import java.util.Collection; + +/** + * Copyright 29/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class PartyQueueJoinMenu { + + private Practice plugin = Practice.getInstance(); + + // party main menu for 2v2, 3v3, 4v4, 5v5 + private final InventoryUI partyQueueMenu = new InventoryUI(CC.GOLD + "Select a party queue type", true, 1); + + + // party menu 2v2 + private final InventoryUI party2v2Menu = new InventoryUI(CC.GOLD + "Select Type", true, 1); + private final InventoryUI party2v2MenuUn_ranked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + private final InventoryUI party2v2MenuRanked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + + // party menu 3v3 + private final InventoryUI party3v3Menu = new InventoryUI(CC.GOLD + "Select Type", true, 1); + private final InventoryUI party3v3MenuUn_ranked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + private final InventoryUI party3v3MenuRanked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + + // party menu 4v4 + private final InventoryUI party4v4Menu = new InventoryUI(CC.GOLD + "Select Type", true, 1); + private final InventoryUI party4v4MenuUn_ranked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + private final InventoryUI party4v4MenuRanked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + + // party menu 5v5 + private final InventoryUI party5v5Menu = new InventoryUI(CC.GOLD + "Select Type", true, 1); + private final InventoryUI party5v5MenuUn_ranked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + private final InventoryUI party5v5MenuRanked = new InventoryUI(CC.GOLD + "Select ladder", true, 1); + + public PartyQueueJoinMenu() { + this.QueueMenu(); + } + + private void QueueMenu() { + Collection kits = Practice.getInstance().getKitManager().getKits(); + + // 2v2 start + this.partyQueueMenu.setItem(0, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.GOLD + "2v2 Queue") + .amount(2) + .lore("") + .lore(CC.YELLOW + "Click here to join 2v2 queue.") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(PartyQueueJoinMenu.this.party2v2Menu.getCurrentPage()); + } + }); + this.party2v2Menu.setItem(3, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.EMERALD) + .name(CC.GOLD + "2v2 UnRanked") + .lore("") + .lore(CC.YELLOW + "Click here to select unranked type.") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(PartyQueueJoinMenu.this.party2v2MenuUn_ranked.getCurrentPage()); + } + }); + this.party2v2Menu.setItem(5, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND) + .name(CC.GOLD + "2v2 Ranked") + .lore("") + .lore(CC.YELLOW + "Click here to select ranked type.") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + player.closeInventory(); + player.openInventory(PartyQueueJoinMenu.this.party2v2MenuRanked.getCurrentPage()); + } + }); + + for (Kit kit : kits) { + if (kit.isEnabled()) { + if (!kit.getName().contains("HCF TeamFight")) { + this.party2v2MenuUn_ranked.addItem(new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + + if (profile.isEditing()) { + player.sendMessage(CC.RED + "You cannot queue right now."); + return; + } + + if (kit.getName().contains("HCF TeamFight")) { + Party party = plugin.getPartyManager().getParty(player.getUniqueId()); + + if(party == null) { + player.sendMessage(ChatColor.RED + "This kit can only be played in a party."); + player.closeInventory(); + return; + } + + if (party.getArchers().isEmpty() && party.getBards().isEmpty()) { + player.sendMessage(ChatColor.RED + "You must specify your party's roles (you must atleast ahve one archer or one bard)" + + ".\nUse: /party hcteams"); + player.closeInventory(); + player.closeInventory(); + return; + } + } + + /*addToQueue2V2( + player, + Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()), + kit, + QueueType.UN_RANKED_2v2 + );*/ + } + } + + ); + } + } + if (kit.isRanked()) { + this.party2v2MenuRanked.addItem(new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + + if (profile.isEditing()) { + player.sendMessage(CC.RED + "You cannot queue right now."); + return; + } + + if (kit.getName().contains("HCF TeamFight")) { + + Party party = plugin.getPartyManager().getParty(player.getUniqueId()); + + if(party == null) { + player.sendMessage(ChatColor.RED + "This kit can only be played in a party."); + player.closeInventory(); + return; + } + + if(party.getArchers().isEmpty() || party.getBards().isEmpty()) { + player.sendMessage(ChatColor.RED + "You must specify your party's roles.\nUse: /party hcteams"); + player.closeInventory(); + player.closeInventory(); + return; + } + } + + /*addToQueue2V2( + player, + Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()), + kit, + QueueType.RANKED_2v2 + );*/ + } + }); + } + } + // 2v2 end + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/queue/menu/party/PlayJoinMenu.java b/Practice/src/main/java/me/devkevin/practice/queue/menu/party/PlayJoinMenu.java new file mode 100644 index 0000000..4b033a3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/queue/menu/party/PlayJoinMenu.java @@ -0,0 +1,196 @@ +package me.devkevin.practice.queue.menu.party; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeCache; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.tournament.state.TournamentState; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; + +import static me.devkevin.practice.util.PlayerUtil.PLACEHOLDER_ITEM; + +/** + * Copyright 23/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class PlayJoinMenu { + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI playMenu = new InventoryUI(CC.GRAY + "Play Menu", true, 3); + + public PlayJoinMenu() { + setupMenu(); + this.plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this::setupMenu, 20L, 20L); + } + + private void setupMenu() { + for (int i = 0; i < 9 * 3; i++) { + this.playMenu.setItem(i, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM)); + } + + if (this.plugin.getTournamentManager().getTournaments().size() >= 1 && this.plugin.getTournamentManager().getTournament().getTournamentState() == TournamentState.WAITING) { + // 11 13 15 + // Play Menu + + playMenu.setItem(10, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.IRON_SWORD) + .name(CC.DARK_RED + "Queue Unranked") + .lore("") + .lore(CC.GRAY + "Casual 1v1's matches") + .lore(CC.GRAY + "with no loss penalty.") + .lore("") + .lore(CC.RED + "Players: " + CC.RESET + PracticeCache.getInstance().getUnrankedSoloPlayers()) + .lore("") + .lore(CC.GREEN + "Click to play!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + + //player.openInventory(plugin.getQueueJoinMenu().getUnrankedMenu().getCurrentPage()); + } + }); + playMenu.setItem(12, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.DARK_RED + "Queue Ranked") + .lore("") + .lore(CC.GRAY + "Casual 1v1's matches with") + .lore(CC.GRAY + "a ranked aspect to them. This") + .lore(CC.GRAY + "includes ELO.") + .lore("") + .lore(CC.RED + "Players: " + CC.RESET + PracticeCache.getInstance().getRankedSoloPlayers()) + .lore("") + .lore(CC.GREEN + "Click to play!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + player.closeInventory(); + + if (!player.hasPermission("practice.donors.*") && profile.getUnrankedWins() < 10) { + player.sendMessage(ChatColor.RED + "You must win " + (10 - profile.getUnrankedWins()) + " Unranked Matches to join this queue."); + return; + } + + //player.openInventory(plugin.getQueueJoinMenu().getRankedMenu().getCurrentPage()); + } + }); + + playMenu.setItem(14, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_CHESTPLATE) + .name(CC.DARK_RED + "TeamFight") + .lore("") + .lore(CC.GRAY + "Fight with other factions") + .lore(CC.GRAY + "capping a koth to win the") + .lore(CC.GRAY + "the match.") + .lore(CC.GRAY + "switching to " + CC.YELLOW + "Bard" + CC.GRAY + ", " + CC.RED + "Archer" + CC.GRAY + ", " + CC.AQUA + "Diamond " + CC.GRAY + "kit.") + .lore("") + .lore(CC.YELLOW + CC.BOLD + "NEW") + .lore("") + .lore(CC.GREEN + "Click to play!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + + player.sendMessage(CC.GREEN + "getFaction::TEST"); + } + }); + + playMenu.setItem(16, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.GOLD_SWORD) + .name(CC.DARK_RED + "Tournament") + .lore("") + .lore(CC.GRAY + "An tournament as been started") + .lore("") + //.lore(CC.GOLD + "Players: " + CC.RESET + tournament.getPlayers().size() + "/" + tournament.getSize()) + .lore("") + .lore(CC.GOLD + "Click here to join!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + player.performCommand("tournament join"); + } + }); + } else { + // Play Menu + playMenu.setItem(11, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.IRON_SWORD) + .name(CC.DARK_RED + "Queue Unranked") + .lore("") + .lore(CC.GRAY + "Casual 1v1's matches") + .lore(CC.GRAY + "with no loss penalty.") + .lore("") + //.lore(CC.RED + "Players: " + CC.RESET + PracticeCache.getInstance().getUnrankedSoloPlayers()) + .lore("") + .lore(CC.GREEN + "Click to play!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.closeInventory(); + + //player.openInventory(plugin.getQueueJoinMenu().getUnrankedMenu().getCurrentPage()); + } + }); + playMenu.setItem(13, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_SWORD) + .name(CC.DARK_RED + "Queue Ranked") + .lore("") + .lore(CC.GRAY + "Casual 1v1's matches with") + .lore(CC.GRAY + "a ranked aspect to them. This") + .lore(CC.GRAY + "includes ELO.") + .lore("") + .lore(CC.RED + "Players: " + CC.RESET + PracticeCache.getInstance().getRankedSoloPlayers()) + .lore("") + .lore(CC.GREEN + "Click to play!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + Profile profile = plugin.getProfileManager().getProfileData(player.getUniqueId()); + + player.closeInventory(); + + if (!player.hasPermission("practice.donors.*") && profile.getUnrankedWins() < 10) { + player.sendMessage(ChatColor.RED + "You must win " + (10 - profile.getUnrankedWins()) + " Unranked Matches to join this queue."); + return; + } + + //player.openInventory(plugin.getQueueJoinMenu().getRankedMenu().getCurrentPage()); + } + }); + playMenu.setItem(15, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.DIAMOND_CHESTPLATE) + .name(CC.DARK_RED + "TeamFight") + .lore("") + .lore(CC.GRAY + "Fight with other factions") + .lore(CC.GRAY + "capping a koth to win the") + .lore(CC.GRAY + "the match.") + .lore(CC.GRAY + "switching to " + CC.YELLOW + "Bard" + CC.GRAY + ", " + CC.RED + "Archer" + CC.GRAY + ", " + CC.AQUA + "Diamond " + CC.GRAY + "kit.") + .lore("") + .lore(CC.YELLOW + CC.BOLD + "NEW") + .lore("") + .lore(CC.GREEN + "Click to play!") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + + player.sendMessage(CC.GREEN + "getFaction::TEST"); + } + }); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/queue/menu/play/QueueMenu.java b/Practice/src/main/java/me/devkevin/practice/queue/menu/play/QueueMenu.java new file mode 100644 index 0000000..9eaba06 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/queue/menu/play/QueueMenu.java @@ -0,0 +1,207 @@ +package me.devkevin.practice.queue.menu.play; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.leaderboard.Leaderboard; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.stream.Collectors; + +import static me.devkevin.practice.util.PlayerUtil.PLACEHOLDER_ITEM; + +/** + * Copyright 12/12/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class QueueMenu { + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI unrankedMenu = new InventoryUI(CC.GRAY + "Play Unranked Queue", 5); + private final InventoryUI rankedMenu = new InventoryUI(CC.GRAY + "Play Ranked Queue", 5); + + public QueueMenu() { + this.setupMenu(); + plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, this::updateInventories, 20L, 20L); + } + + private void setupMenu() { + for (int i = 0; i < 9 * 5; i++) { + this.unrankedMenu.setItem(i, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM)); + this.rankedMenu.setItem(i, new InventoryUI.EmptyClickableItem(PLACEHOLDER_ITEM)); + } + + Collection kits = plugin.getKitManager().getKits(); + for (Kit kit : kits) { + if (kit.isEnabled()) { + this.unrankedMenu.setItem(kit.getPriority(), new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + + if (profile.isBusy()) { + player.sendMessage(CC.RED + "You cannot queue right now."); + return; + } + + if (LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).isFrozen()) { + player.sendMessage(CC.RED + "You cannot queue while you're frozen."); + } + + addToQueue( + player, + Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()), + kit, + QueueType.UN_RANKED); + } + }); + if (kit.isRanked()) { + this.rankedMenu.setItem(kit.getPriority(), new InventoryUI.AbstractClickableItem(kit.getIcon()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + if (profile == null) { + return; + } + + if (profile.isBusy()) { + player.sendMessage(CC.RED + "You cannot queue right now."); + return; + } + + if (LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).isFrozen()) { + player.sendMessage(CC.RED + "You cannot queue while you're frozen."); + } + + addToQueue( + player, + Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()), + kit, + QueueType.RANKED); + } + }); + } + } + } + } + + private void updateInventories() { + for (int i = 0; i < 9 * 5; i++) { + InventoryUI.ClickableItem unrankedItem = this.unrankedMenu.getItem(i); + if (unrankedItem != null) { + if (unrankedItem.getItemStack() != PLACEHOLDER_ITEM) { + unrankedItem.setItemStack(this.updateQueueLore(unrankedItem.getItemStack(), QueueType.UN_RANKED)); + } else { + unrankedItem.setItemStack(PLACEHOLDER_ITEM); + } + this.unrankedMenu.setItem(i, unrankedItem); + } + + InventoryUI.ClickableItem rankedItem = this.rankedMenu.getItem(i); + if (rankedItem != null) { + if (rankedItem.getItemStack() != PLACEHOLDER_ITEM) { + rankedItem.setItemStack(this.updateQueueLore(rankedItem.getItemStack(), QueueType.RANKED)); + } else { + rankedItem.setItemStack(PLACEHOLDER_ITEM); + } + this.rankedMenu.setItem(i, rankedItem); + } + } + } + + public void addToQueue(Player player, Profile profile, Kit kit, QueueType queueType) { + if (kit != null) { + this.plugin.getQueue().addPlayer(player, profile, kit.getName(), queueType); + } + } + + private ItemStack updateQueueLore(ItemStack itemStack, QueueType queueType) { + if (itemStack == null) { + return null; + } + + String ladder; + + if (itemStack.hasItemMeta() && itemStack.getItemMeta().hasDisplayName()) { + ladder = ChatColor.stripColor(itemStack.getItemMeta().getDisplayName()); + if (ladder.contains(" ")) { + ladder = ladder.split(" ")[1]; + } + ladder = ladder.replaceAll("[^a-zA-Z]+", ""); + } else { + return null; + } + + int unrankedQueueSize = this.plugin.getQueue().getQueueSize(ladder, QueueType.UN_RANKED); + int unrankedInGameSize = this.plugin.getMatchManager().getFighters(ladder, QueueType.UN_RANKED); + + int rankedQueueSize = this.plugin.getQueue().getQueueSize(ladder, QueueType.RANKED); + int rankedInGameSize = this.plugin.getMatchManager().getFighters(ladder, QueueType.RANKED); + + ArrayList lore = new ArrayList<>(); + + if (!queueType.isRanked()) { + lore.add(CC.GRAY + "\u25CF " + CC.YELLOW + "In queue: " + CC.GOLD + unrankedQueueSize); + lore.add(CC.GRAY + "\u25CF " + CC.YELLOW + "In match: " + CC.GOLD + unrankedInGameSize); + + lore.add(""); + + int i = 0; + for (Leaderboard winStreak : plugin.getLeaderboardManager().getKitLeaderboards(plugin.getKitManager().getKit(ladder)).stream().sorted(Comparator.comparingInt(Leaderboard::getWinStreak).reversed()).limit(3).collect(Collectors.toList())) { + if (winStreak != null) { + if (winStreak.getUuid() != null) { + lore.add(CC.GRAY + (i + 1) + ". " + CC.YELLOW + CC.I + winStreak.getName() + CC.GRAY + " - " + CC.GOLD + winStreak.getWinStreak()); + i++; + } + } + } + } else { + lore.add(CC.GRAY + "\u25CF " + CC.YELLOW + "In queue: " + CC.GOLD + rankedQueueSize); + lore.add(CC.GRAY + "\u25CF " + CC.YELLOW + "In match: " + CC.GOLD + rankedInGameSize); + + lore.add(""); + + int i = 0; + for (Leaderboard leaderboard : plugin.getLeaderboardManager().getSortedKitLeaderboards(plugin.getKitManager().getKit(ladder), "elo").stream().limit(3).collect(Collectors.toList())) { + if (leaderboard != null) { + if (leaderboard.getUuid() != null) { + lore.add(CC.GRAY + (i + 1) + ". " + CC.YELLOW + CC.I + leaderboard.getName() + CC.GRAY + " - " + CC.GOLD + leaderboard.getElo()); + i++; + } + } + } + } + lore.add(""); + lore.add(CC.YELLOW + "Click here to play " + CC.GOLD + ladder + CC.YELLOW + "."); + + switch (queueType) { + case UN_RANKED: + return ItemUtil.updateLoreAndAmount(itemStack, Math.min(unrankedInGameSize, 64), lore.toArray(new String[0])); + case RANKED: + return ItemUtil.updateLoreAndAmount(itemStack, Math.min(rankedInGameSize, 64), lore.toArray(new String[0])); + } + + return itemStack; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/staff/StaffMode.java b/Practice/src/main/java/me/devkevin/practice/staff/StaffMode.java new file mode 100644 index 0000000..a13ddda --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/staff/StaffMode.java @@ -0,0 +1,34 @@ +package me.devkevin.practice.staff; + +import lombok.Getter; +import club.inverted.chatcolor.CC; +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import org.bukkit.entity.Player; + +/** + * Copyright 05/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class StaffMode { + + @Getter private final Practice plugin = Practice.getInstance(); + + private void giveStaffModeItems(Player player) { + player.closeInventory(); + player.getInventory().setContents(this.plugin.getHotbarItem().getStaffModeItems()); + player.updateInventory(); + } + + public void staffMode(Player player) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + + profile.setState(ProfileState.STAFF); + + giveStaffModeItems(player); + + player.sendMessage(CC.GREEN + "You have joined to Staff Mode."); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/titles/Titles.java b/Practice/src/main/java/me/devkevin/practice/titles/Titles.java new file mode 100644 index 0000000..5609a09 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/titles/Titles.java @@ -0,0 +1,77 @@ +package me.devkevin.practice.titles; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; +import java.util.List; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 11/02/2023 @ 1:34 + * Tiles / me.devkevin.practice.titles / Practice + */ +@Getter +@RequiredArgsConstructor +public enum Titles { + + NONE(CC.YELLOW + "Not Placed", 0, 25), + + // 25 to 25 + BRONZE(CC.YELLOW + "Bronze", 25, 50), + BRONZE_I(CC.YELLOW + "Bronze I", 50, 75), + BRONZE_II(CC.YELLOW + "Bronze II", 75, 100), + BRONZE_III(CC.YELLOW + "Bronze III", 100, 125), + BRONZE_IV(CC.YELLOW + "Bronze IV", 125, 150), + BRONZE_V(CC.YELLOW + "Bronze V", 150, 175), + + // 50 to 50 + IRON(CC.YELLOW + "Iron", 175, 225), + IRON_I(CC.YELLOW + "Iron I", 225, 275), + IRON_II(CC.YELLOW + "Iron II", 275, 325), + IRON_III(CC.YELLOW + "Iron III", 325, 375), + IRON_IV(CC.YELLOW + "Iron IV", 375, 425), + IRON_V(CC.YELLOW + "Iron V", 425, 475), + + // 75 to 75 + GOLD(CC.YELLOW + "Gold", 475, 550), + GOLD_I(CC.YELLOW + "Gold I", 550, 625), + GOLD_II(CC.YELLOW + "Gold II", 625, 700), + GOLD_III(CC.YELLOW + "Gold III", 700, 775), + GOLD_IV(CC.YELLOW + "Gold IV", 775, 850), + GOLD_V(CC.YELLOW + "Gold V", 850, 925), + + // 100 to 100 + EMERALD(CC.YELLOW + "Emerald", 925, 1025), + EMERALD_I(CC.YELLOW + "Emerald I", 1025, 1125), + EMERALD_II(CC.YELLOW + "Emerald II", 1125, 1225), + EMERALD_III(CC.YELLOW + "Emerald III", 1225, 1325), + EMERALD_IV(CC.YELLOW + "Emerald IV", 1325, 1425), + EMERALD_V(CC.YELLOW + "Emerald V", 1425, 1525), + + // 125 to 125 + DIAMOND(CC.YELLOW + "Diamond", 1525, 1650), + DIAMOND_I(CC.YELLOW + "Diamond I", 1650, 1775), + DIAMOND_II(CC.YELLOW + "Diamond II", 1775, 1900), + DIAMOND_III(CC.YELLOW + "Diamond III", 1900, 2025), + DIAMOND_IV(CC.YELLOW + "Diamond IV", 2025, 2150), + DIAMOND_V(CC.YELLOW + "Diamond V", 2150, 2275), + + // 150 to 150 + MASTER(CC.YELLOW + "Master", 2275, 2425), + MASTER_I(CC.YELLOW + "Master I", 2425, 2575), + MASTER_II(CC.YELLOW + "Master II", 2575, 2725), + MASTER_III(CC.YELLOW + "Master III", 2725, 2875), + MASTER_IV(CC.YELLOW + "Master IV", 2875, 3025), + MASTER_V(CC.YELLOW + "Master V", 3025, 3175), + + GRAND_MASTER(CC.YELLOW + "Grand Master", 3175, 9999999) + ; + + public static final List titles = Arrays.asList(values()); + + private final String name; + private final int minimumWins; + private final int maximumWins; +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/Tournament.java b/Practice/src/main/java/me/devkevin/practice/tournament/Tournament.java new file mode 100644 index 0000000..6b624e6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/Tournament.java @@ -0,0 +1,120 @@ +package me.devkevin.practice.tournament; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.tournament.state.TournamentState; +import me.devkevin.practice.tournament.team.MatchRandomTeam; +import me.devkevin.practice.tournament.team.TournamentTeam; +import org.bukkit.Sound; +import org.bukkit.entity.Player; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter @RequiredArgsConstructor +public class Tournament { + private final Practice plugin = Practice.getInstance(); + + private final Set players = new HashSet<>(); + private final Set matches = new HashSet<>(); + private final List aliveTeams = new ArrayList<>(); + private final Map playerTeams = new ConcurrentHashMap<>(); + @Setter private Player host; + private final int id; + private final int teamSize; + private final int size; + private final String kitName; + @Setter private TournamentState tournamentState = TournamentState.WAITING; + @Setter private int currentRound = 1; + @Setter private int countdown = 31; + + public MatchRandomTeam getRandomTeam() { + List teams = this.getAliveTeams(); + Collections.shuffle(teams); + TournamentTeam teamA; + TournamentTeam teamB; + for (int i = 0; i < teams.size(); i += 2) { + teamA = teams.get(i); + if (teams.size() > i + 1) { + teamB = teams.get(i + 1); + return new MatchRandomTeam(teamA, teamB); + } else { + for (UUID playerUUID : teamA.getAlivePlayers()) { + Player player = this.plugin.getServer().getPlayer(playerUUID); + player.sendMessage(CC.translate("&cYou have been skipped to the next round because there were no opponents for you this round.")); + } + } + } + + return null; + } + + public void addPlayer(UUID uuid) { + this.players.add(uuid); + } + + public void addAliveTeam(TournamentTeam team) { + this.aliveTeams.add(team); + } + + public void killTeam(TournamentTeam team) { + this.aliveTeams.remove(team); + } + + public void setPlayerTeam(UUID uuid, TournamentTeam team) { + this.playerTeams.put(uuid, team); + } + + public TournamentTeam getPlayerTeam(UUID uuid) { + return this.playerTeams.get(uuid); + } + + public void removePlayer(UUID uuid) { + this.players.remove(uuid); + } + + public void addMatch(UUID uuid) { + this.matches.add(uuid); + } + + public void removeMatch(UUID uuid) { + this.matches.remove(uuid); + } + + public boolean isTeamTournament() { + return this.teamSize > 1; + } + + public void broadcast(String message) { + for (UUID uuid : this.players) { + Player player = this.plugin.getServer().getPlayer(uuid); + + player.sendMessage(message); + } + } + + public void broadcastWithSound(String message, Sound sound) { + for (UUID uuid : this.players) { + Player player = this.plugin.getServer().getPlayer(uuid); + + player.sendMessage(message); + player.playSound(player.getLocation(), sound, 10, 1); + } + } + + public int decrementCountdown() { + if (countdown <= 0) { + return 0; + } + + return --this.countdown; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/command/TournamentCommand.java b/Practice/src/main/java/me/devkevin/practice/tournament/command/TournamentCommand.java new file mode 100644 index 0000000..45bb9a6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/command/TournamentCommand.java @@ -0,0 +1,277 @@ +package me.devkevin.practice.tournament.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.landcore.player.rank.Rank; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.command.PracticeCommand; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.profile.state.ProfileState; +import me.devkevin.practice.tournament.Tournament; +import me.devkevin.practice.tournament.state.TournamentState; +import me.devkevin.practice.util.Clickable; +import me.devkevin.practice.util.command.Command; +import me.devkevin.practice.util.command.CommandArgs; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TournamentCommand extends PracticeCommand { + private final Practice plugin = Practice.getInstance(); + + @Override @Command(name = "tournament", usage = "&cUsage: /tournament [args]") + public void onCommand(CommandArgs command) { + Player player = command.getPlayer(); + String[] args = command.getArgs(); + + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (args.length == 0) { + if (coreProfile.hasStaff()) { + player.sendMessage(" "); + player.sendMessage(CC.translate("&e&lTournament Help&7:")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament host")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament stop")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament alert")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament forcestart")); + player.sendMessage(" "); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament join")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament leave")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament status")); + player.sendMessage(" "); + } else { + player.sendMessage(" "); + player.sendMessage(CC.translate("&e&lTournament Help&7:")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament join")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament leave")); + player.sendMessage(CC.translate(" &7" + PracticeLang.VERTICAL_BAR + " &e/tournament status")); + player.sendMessage(" "); + } + return; + } + + if (coreProfile.hasRank(Rank.ADMIN)) { + switch (args[0].toLowerCase()) { + case "host": + player.openInventory(this.plugin.getTournamentHostMenu().getInventoryUI().getCurrentPage()); + break; + case "stop": + if (args.length == 1) { + Tournament tournament = this.plugin.getTournamentManager().getTournament(); + if (tournament != null) { + try { + tournament.getPlayers().forEach(uuid -> { + Player tournamentPlayer = this.plugin.getServer().getPlayer(uuid); + if (tournamentPlayer != null) { + this.plugin.getTournamentManager().leaveTournament(player); + } + }); + } catch (Exception ignored) { + } + + tournament.getPlayers().clear(); + tournament.getMatches().clear(); + + this.plugin.getTournamentManager().removeTournament(); + player.sendMessage(CC.RED + "Successfully stopped tournament!"); + } else { + player.sendMessage(CC.RED + "This tournament does not exist."); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament stop"); + } + break; + case "alert": + if (args.length == 1) { + Tournament tournament = this.plugin.getTournamentManager().getTournament(); + if (tournament != null) { + String toSend = CC.translate("&e" + tournament.getKitName() + + " &8[&e" + tournament.getTeamSize() + "v&e" + tournament.getTeamSize() + "&8]" + + " &7is starting soon. " + "&a[Click to Join]"); + + Clickable clickable = new Clickable(toSend, CC.translate("&7Click to join this tournament."), "/tournament join"); + + Bukkit.getServer().getOnlinePlayers() + .stream().filter(tournamentPlayer -> !tournament.getPlayers().contains(tournamentPlayer.getUniqueId())) + .collect(Collectors.toList()).forEach(clickable::sendToPlayer); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament alert"); + } + break; + case "forcestart": + if (args.length == 1) { + Tournament tournament = this.plugin.getTournamentManager().getTournament(); + if (tournament != null) { + if (tournament.getTournamentState() == TournamentState.WAITING) { + tournament.setCountdown(11); + tournament.setTournamentState(TournamentState.STARTING); + } else if (tournament.getTournamentState() == TournamentState.STARTING || tournament.getTournamentState() == TournamentState.FIGHTING) { + player.sendMessage(CC.translate("&cYou cannot force-start the tournament because it has already started!")); + } + } else { + player.sendMessage(CC.translate("&cThere are no available tournaments.")); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament forcestart"); + } + break; + case "join": + if (joinTournamentArg(args, player, profile)) return; + break; + case "leave": + if (args.length == 1) { + boolean inTournament = this.plugin.getTournamentManager().isInTournament(player.getUniqueId()); + if (inTournament) { + this.leaveTournament(player); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament leave"); + } + break; + case "status": + if (statusTournamentArg(args, player)) return; + break; + default: + break; + } + } else { + switch (args[0].toLowerCase()) { + case "join": + if (joinTournamentArg(args, player, profile)) return; + break; + case "leave": + if (args.length == 1) { + boolean inTournament = this.plugin.getTournamentManager().isInTournament(player.getUniqueId()); + if (inTournament) { + this.leaveTournament(player); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament leave"); + } + break; + case "status": + if (statusTournamentArg(args, player)) return; + break; + default: + break; + } + } + } + + private boolean statusTournamentArg(String[] args, Player player) { + if (args.length == 1) { + if (this.plugin.getTournamentManager().getTournaments().size() == 0) { + player.sendMessage(CC.RED + "There is no available tournaments."); + return true; + } + + for (Tournament tournament : this.plugin.getTournamentManager().getTournaments().values()) { + if (tournament == null) { + player.sendMessage(CC.RED + "This tournament doesn't exist."); + return true; + } + + player.sendMessage(CC.DARK_GRAY + CC.STRIKETHROUGH + "----------------------------------------------------"); + player.sendMessage(" "); + player.sendMessage(CC.translate("&eTournament &7(&e" + tournament.getTeamSize() + "v&e" + tournament.getTeamSize() + "&7) &e" + tournament.getKitName())); + + if (tournament.getMatches().size() == 0) { + player.sendMessage(CC.RED + "There are no available tournament matches."); + player.sendMessage(" "); + player.sendMessage(CC.DARK_GRAY + CC.STRIKETHROUGH + "----------------------------------------------------"); + return true; + } + + for (UUID matchUUID : tournament.getMatches()) { + Match match = this.plugin.getMatchManager().getMatchFromUUID(matchUUID); + + MatchTeam teamA = match.getTeams().get(0); + MatchTeam teamB = match.getTeams().get(1); + + boolean teamAParty = teamA.getAlivePlayers().size() > 1; + boolean teamBParty = teamB.getAlivePlayers().size() > 1; + String teamANames = (teamAParty ? LandCore.getInstance().getProfileManager().getProfile(teamA.getLeader()).getGrant().getRank().getColor() + teamA.getLeaderName() + "'s Party" : LandCore.getInstance().getProfileManager().getProfile(teamA.getLeader()).getGrant().getRank().getColor() + teamA.getLeaderName()); + String teamBNames = (teamBParty ? LandCore.getInstance().getProfileManager().getProfile(teamB.getLeader()).getGrant().getRank().getColor() + teamB.getLeaderName() + "'s Party" : LandCore.getInstance().getProfileManager().getProfile(teamB.getLeader()).getGrant().getRank().getColor() + teamB.getLeaderName()); + + Clickable clickable = new Clickable(CC.translate("&f&a" + teamANames + "&7 vs &c" + teamBNames + " &f&a[Click to Spectate]"), + CC.GRAY + "Click to spectate", + "/spectate " + teamA.getLeaderName()); + + clickable.sendToPlayer(player); + } + + player.sendMessage(" "); + player.sendMessage(CC.DARK_GRAY + CC.STRIKETHROUGH + "----------------------------------------------------"); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament status"); + } + + return false; + } + + private boolean joinTournamentArg(String[] args, Player player, Profile profile) { + if (args.length == 1) { + if (profile.getState() != ProfileState.SPAWN) { + player.sendMessage(PracticeLang.ERROR_STATE); + return true; + } + + if (this.plugin.getTournamentManager().isInTournament(player.getUniqueId())) { + player.sendMessage(CC.RED + "You are currently in a tournament."); + return true; + } + + Tournament tournament = this.plugin.getTournamentManager().getTournament(); + if (tournament != null) { + if (tournament.isTeamTournament()) { + if (this.plugin.getPartyManager().getParty(player.getUniqueId()) == null) { + player.sendMessage(CC.RED + "The party size must be of " + tournament.getTeamSize() + " players."); + return true; + } + } + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (party != null && party.getMembers().size() != tournament.getTeamSize()) { + player.sendMessage(CC.RED + "The party size must be of " + tournament.getTeamSize() + " players."); + return true; + } + + if (tournament.getSize() > tournament.getPlayers().size()) { + if ((tournament.getTournamentState() == TournamentState.WAITING || tournament.getTournamentState() == TournamentState.STARTING) && tournament.getCurrentRound() == 1) { + this.plugin.getTournamentManager().joinTournament(0, player); + } else { + player.sendMessage(CC.RED + "Sorry! The tournament already started."); + } + } else { + player.sendMessage(CC.RED + "Sorry! The tournament is already full."); + } + } else { + player.sendMessage(CC.RED + "There are no tournaments being hosted currently!"); + } + } else { + player.sendMessage(CC.RED + "Usage: /tournament join"); + } + return false; + } + + private void leaveTournament(Player player) { + Tournament tournament = this.plugin.getTournamentManager().getTournament(player.getUniqueId()); + if (tournament != null) { + this.plugin.getTournamentManager().leaveTournament(player); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/host/TournamentHostMenu.java b/Practice/src/main/java/me/devkevin/practice/tournament/host/TournamentHostMenu.java new file mode 100644 index 0000000..2840237 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/host/TournamentHostMenu.java @@ -0,0 +1,116 @@ +package me.devkevin.practice.tournament.host; + +import club.inverted.chatcolor.CC; +import lombok.Getter; +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.ItemBuilder; +import me.devkevin.practice.util.ItemUtil; +import me.devkevin.practice.util.inventory.InventoryUI; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +/** + * Copyright 20/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class TournamentHostMenu { + private final Practice plugin = Practice.getInstance(); + + private final InventoryUI inventoryUI = new InventoryUI(CC.DARK_GRAY + "Start a tournament", 4); + + public TournamentHostMenu() { + new BukkitRunnable() { + @Override + public void run() { + setItems(); + } + }.runTaskLater(plugin, 30L); + } + + private void setItems() { + this.inventoryUI.setItem(0, new InventoryUI.AbstractClickableItem(new ItemBuilder(Material.BED) + .name(CC.RED + "Back to General") + .build()) { + @Override + public void onClick(InventoryClickEvent event) { + Player player = (Player)event.getWhoClicked(); + + player.openInventory(plugin.getGeneralSettingMenu().getGeneralMenu().getCurrentPage()); + } + }); + + plugin.getKitManager().getKits().forEach(kit -> { + + if (kit.isEnabled()) { + inventoryUI.setItem(kit.getPriority(), new InventoryUI.ClickableItem() { + private final ItemStack def = ItemUtil.renameItem(ItemUtil.reloreItem(kit.getIcon().getData().toItemStack(), + CC.GRAY + "Click to host tournament"), kit.getName()); + private ItemStack itemStack = def.clone(); + + @Override + public void onClick(InventoryClickEvent event) { + InventoryUI inventoryUI = new InventoryUI(CC.GRAY + "Select team size", 1); + + for (int i = 1; i < 5; i++) { + int finalI = i; + inventoryUI.addItem(new InventoryUI.ClickableItem() { + private final ItemStack def = ItemUtil.renameItem(ItemUtil.reloreItem( + new ItemStack(Material.NAME_TAG), + CC.GREEN + "Teamsize: " + CC.GRAY + finalI), + CC.GRAY + kit.getName()); + private ItemStack itemStack = def.clone(); + + @Override + public void onClick(InventoryClickEvent event) { + if (!plugin.getTournamentManager().getTournaments().isEmpty()) { + event.getWhoClicked().sendMessage(CC.RED + "There already is an ongoing tournament."); + event.getWhoClicked().closeInventory(); + return; + } + plugin.getTournamentManager().createTournament(event.getWhoClicked(), finalI, 150, kit.getName()); + } + + @Override + public ItemStack getItemStack() { + return itemStack; + } + + @Override + public void setItemStack(ItemStack itemStack) { + this.itemStack = itemStack; + } + + @Override + public ItemStack getDefaultItemStack() { + return def; + } + }); + } + + event.getWhoClicked().openInventory(inventoryUI.getCurrentPage()); + } + + @Override + public ItemStack getItemStack() { + return this.itemStack; + } + + @Override + public void setItemStack(ItemStack itemStack) { + this.itemStack = itemStack; + } + + @Override + public ItemStack getDefaultItemStack() { + return def; + } + }); + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/manager/TournamentManager.java b/Practice/src/main/java/me/devkevin/practice/tournament/manager/TournamentManager.java new file mode 100644 index 0000000..0343ac4 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/manager/TournamentManager.java @@ -0,0 +1,249 @@ +package me.devkevin.practice.tournament.manager; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.tournament.Tournament; +import me.devkevin.practice.tournament.runnable.TournamentRunnable; +import me.devkevin.practice.tournament.state.TournamentState; +import me.devkevin.practice.tournament.team.TournamentTeam; +import me.devkevin.practice.util.TeamUtil; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TournamentManager { + private final Practice plugin = Practice.getInstance(); + + private final Map tournamentPlayers = new HashMap<>(); + private final Map tournamentMatches = new HashMap<>(); + private final Map tournaments = new HashMap<>(); + + public boolean isInTournament(UUID uuid) { + return this.tournamentPlayers.containsKey(uuid); + } + + public Tournament getTournament(UUID uuid) { + Integer id = this.tournamentPlayers.get(uuid); + if (id == null) { + return null; + } + return this.tournaments.get(id); + } + + public Tournament getTournamentFromMatch(UUID uuid) { + Integer id = this.tournamentMatches.get(uuid); + if (id == null) { + return null; + } + + return this.tournaments.get(id); + } + + public void createTournament(CommandSender sender, int teamSize, int size, String kitName) { + Tournament tournament = new Tournament(0, teamSize, size, kitName); + this.tournaments.put(0, tournament); + new TournamentRunnable(tournament).runTaskTimerAsynchronously(this.plugin, 20L, 20L); + + sender.sendMessage(CC.translate("&7Successfully created &e" + teamSize + "v" + teamSize + " &6" + kitName + " &7tournament. (Max players: &e" + size + "&7)")); + + if (sender instanceof Player) { + Player player = (Player)sender; + tournament.setHost(player); + new BukkitRunnable() { + @Override + public void run() { + if (tournament.getCountdown() >= 5 && tournament.getTournamentState() == TournamentState.WAITING) { + player.performCommand("tournament start"); + } + } + }.runTaskTimer(this.plugin, 0L, 30L); + } + } + + private void playerLeft(Tournament tournament, Player player) { + TournamentTeam team = tournament.getPlayerTeam(player.getUniqueId()); + tournament.removePlayer(player.getUniqueId()); + player.sendMessage(CC.translate("&cYou left the tournament.")); + + this.tournamentPlayers.remove(player.getUniqueId()); + this.plugin.getProfileManager().sendToSpawn(player); + + tournament.broadcast(CC.translate("&8[&eTournament&8] " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + "" + " &cleft the tournament. &8(&7"+ tournament.getPlayers().size() + "/" + tournament.getSize() + "&8)")); + + if (team != null) { + team.killPlayer(player.getUniqueId()); + if (team.getAlivePlayers().size() == 0) { + tournament.killTeam(team); + if (tournament.getAliveTeams().size() == 1) { + TournamentTeam tournamentTeam = tournament.getAliveTeams().get(0); + String names = TeamUtil.getNames(tournamentTeam); + + Bukkit.broadcastMessage(CC.translate("&6" + names + " &7won the &7" + tournament.getTeamSize() + "v" + tournament.getTeamSize() +" &e" + tournament.getKitName() + " &7Tournament!")); + + for (UUID uuid : tournamentTeam.getAlivePlayers()) { + this.tournamentPlayers.remove(uuid); + Player tournamentPlayer = this.plugin.getServer().getPlayer(uuid); + this.plugin.getProfileManager().sendToSpawn(tournamentPlayer); + } + + removeTournament(); + } + } else if (team.getLeader().equals(player.getUniqueId())) { + team.setLeader(team.getAlivePlayers().get(0)); + } + } + } + + private void teamEliminated(Tournament tournament, TournamentTeam winnerTeam, TournamentTeam losingTeam) { + for (UUID playerUUID : losingTeam.getPlayers()) { + Player player = this.plugin.getServer().getPlayer(playerUUID); + if (player != null) { + tournament.removePlayer(player.getUniqueId()); + player.sendMessage(CC.translate("&8[&eTournament&8] &cYou have been eliminated from the Tournament. You can see the status with /tournament status")); + + this.tournamentPlayers.remove(player.getUniqueId()); + } + } + + if (!tournament.isTeamTournament()) { + tournament.broadcast(CC.translate("&8[&eTournament&8] " + LandCore.getInstance().getProfileManager().getProfile(losingTeam.getLeader()).getGrant().getRank().getColor() + losingTeam.getLeaderName() + " &7has been eliminated by " + LandCore.getInstance().getProfileManager().getProfile(winnerTeam.getLeader()).getGrant().getRank().getColor() + winnerTeam.getLeaderName() + "&7.")); + } else { + tournament.broadcast(CC.translate("&8[&eTournament&8] " + LandCore.getInstance().getProfileManager().getProfile(losingTeam.getLeader()).getGrant().getRank().getColor() + losingTeam.getLeaderName() + "&7's party &7has been eliminated by " + LandCore.getInstance().getProfileManager().getProfile(winnerTeam.getLeader()).getGrant().getRank().getColor() + winnerTeam.getLeaderName() + "&7's party.")); + } + tournament.broadcast(CC.translate("&8[&eTournament&8] &e" + tournament.getPlayers().size() + " &7remaining out of &e" + tournament.getSize())); + } + + public void leaveTournament(Player player) { + Tournament tournament = this.getTournament(player.getUniqueId()); + if (tournament == null) { + return; + } + + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (party != null && tournament.getTournamentState() != TournamentState.FIGHTING) { + if (this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + for (UUID memberUUID : party.getMembers()) { + Player member = this.plugin.getServer().getPlayer(memberUUID); + this.playerLeft(tournament, member); + } + } else { + player.sendMessage(CC.translate("&cYou are not the leader of the party.")); + } + } else { + this.playerLeft(tournament, player); + } + } + + private void playerJoined(Tournament tournament, Player player) { + tournament.addPlayer(player.getUniqueId()); + + this.tournamentPlayers.put(player.getUniqueId(), tournament.getId()); + this.plugin.getProfileManager().sendToSpawn(player); + + tournament.broadcast(CC.translate("&8[&eTournament&8] " + LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()).getGrant().getRank().getColor() + player.getName() + " &ajoined the tournament. &8(&7"+ tournament.getPlayers().size() + "/" + tournament.getSize() + "&8)")); + } + + public void joinTournament(Integer id, Player player) { + Tournament tournament = this.tournaments.get(id); + Party party = this.plugin.getPartyManager().getParty(player.getUniqueId()); + if (party != null) { + if (this.plugin.getPartyManager().isLeader(player.getUniqueId())) { + if ((party.getMembers().size() + tournament.getPlayers().size()) <= tournament.getSize()) { + if (party.getMembers().size() != tournament.getTeamSize() || party.getMembers().size() == 1) { + player.sendMessage(CC.RED + "The party size must be of " + tournament.getTeamSize() + " players."); + } else { + for (UUID memberUUID : party.getMembers()) { + Player member = this.plugin.getServer().getPlayer(memberUUID); + this.playerJoined(tournament, member); + } + } + } else { + player.sendMessage(CC.RED + "Sorry! The tournament is already full."); + } + } else { + player.sendMessage(CC.translate("&cYou are not the leader of the party.")); + } + } else { + this.playerJoined(tournament, player); + } + + if (tournament.getPlayers().size() == tournament.getSize()) { + tournament.setTournamentState(TournamentState.STARTING); + } + } + + public Tournament getTournament() { + return this.tournaments.get(0); + } + + public void removeTournament() { + Tournament tournament = this.tournaments.get(0); + if (tournament == null) { + return; + } + + this.tournaments.remove(0); + } + + public void addTournamentMatch(UUID matchId) { + this.tournamentMatches.put(matchId, 0); + } + + public void removeTournamentMatch(Match match) { + Tournament tournament = this.getTournamentFromMatch(match.getMatchId()); + if (tournament == null) { + return; + } + + tournament.removeMatch(match.getMatchId()); + this.tournamentMatches.remove(match.getMatchId()); + + MatchTeam losingTeam = match.getWinningTeamId() == 0 ? match.getTeams().get(1) : match.getTeams().get(0); + TournamentTeam losingTournamentTeam = tournament.getPlayerTeam(losingTeam.getLeader()); + + MatchTeam winningTeam = match.getTeams().get(match.getWinningTeamId()); + TournamentTeam winningTournamentTeam = tournament.getPlayerTeam(winningTeam.getLeader()); + + if (losingTournamentTeam != null) { + tournament.killTeam(losingTournamentTeam); + this.teamEliminated(tournament, winningTournamentTeam, losingTournamentTeam); + } + + if (tournament.getMatches().size() == 0) { + if (tournament.getAliveTeams().size() > 1) { + tournament.setTournamentState(TournamentState.STARTING); + tournament.setCurrentRound(tournament.getCurrentRound() + 1); + tournament.setCountdown(11); + } else { + String names = TeamUtil.getNames(winningTournamentTeam); + Bukkit.broadcastMessage(CC.translate("&6" + names + " &7won the &7" + tournament.getTeamSize() + "v" + tournament.getTeamSize() +" &e" + tournament.getKitName() + " &7Tournament!")); + + for (UUID playerUUID : winningTournamentTeam.getAlivePlayers()) { + this.tournamentPlayers.remove(playerUUID); + Player tournamentPlayer = this.plugin.getServer().getPlayer(playerUUID); + this.plugin.getProfileManager().sendToSpawn(tournamentPlayer); + } + + removeTournament(); + } + } + } + + public Map getTournaments() { + return tournaments; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/runnable/TournamentRunnable.java b/Practice/src/main/java/me/devkevin/practice/tournament/runnable/TournamentRunnable.java new file mode 100644 index 0000000..6c94097 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/runnable/TournamentRunnable.java @@ -0,0 +1,145 @@ +package me.devkevin.practice.tournament.runnable; + +import club.inverted.chatcolor.CC; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import lombok.RequiredArgsConstructor; +import me.devkevin.landcore.LandCore; +import me.devkevin.practice.Practice; +import me.devkevin.practice.PracticeLang; +import me.devkevin.practice.kit.Kit; +import me.devkevin.practice.match.Match; +import me.devkevin.practice.match.MatchTeam; +import me.devkevin.practice.party.Party; +import me.devkevin.practice.profile.Profile; +import me.devkevin.practice.queue.QueueType; +import me.devkevin.practice.tournament.Tournament; +import me.devkevin.practice.tournament.state.TournamentState; +import me.devkevin.practice.tournament.team.TournamentTeam; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@RequiredArgsConstructor +public class TournamentRunnable extends BukkitRunnable { + private final Practice plugin = Practice.getInstance(); + private final Tournament tournament; + + @Override + public void run() { + if (!this.plugin.getTournamentManager().getTournaments().isEmpty()) { + if (this.tournament.getTournamentState() == TournamentState.STARTING) { + int countdown = this.tournament.decrementCountdown(); + if (countdown == 0) { + if (this.tournament.getCurrentRound() == 1) { + Set players = Sets.newConcurrentHashSet(this.tournament.getPlayers()); + if (!tournament.isTeamTournament()) { + List currentTeam = null; + for (UUID player : players) { + if (currentTeam == null) { + currentTeam = new ArrayList<>(); + } + currentTeam.add(player); + if (currentTeam.size() == this.tournament.getTeamSize()) { + TournamentTeam team = new TournamentTeam(currentTeam.get(0), currentTeam); + this.tournament.addAliveTeam(team); + for (UUID teammate : team.getPlayers()) { + tournament.setPlayerTeam(teammate, team); + } + currentTeam = null; + } + } + } else { + for (UUID player : players) { + if (this.plugin.getPartyManager().isLeader(player)) { + Party party = this.plugin.getPartyManager().getParty(player); + if (party != null) { + TournamentTeam team = new TournamentTeam(party.getLeader(), Lists.newArrayList(party.getMembers())); + this.tournament.addAliveTeam(team); + for (UUID member : party.getMembers()) { + if (tournament.getPlayerTeam(member) == null) { + tournament.setPlayerTeam(member, team); + } + } + } + } + } + } + } + + List teams = this.tournament.getAliveTeams(); + Collections.shuffle(teams); + for (int i = 0; i < teams.size(); i += 2) { + TournamentTeam teamA = teams.get(i); + if (teams.size() > i + 1) { + TournamentTeam teamB = teams.get(i + 1); + for (UUID playerUUID : teamA.getAlivePlayers()) { + this.removeSpectator(playerUUID); + } + for (UUID playerUUID : teamB.getAlivePlayers()) { + this.removeSpectator(playerUUID); + } + + MatchTeam matchTeamA = new MatchTeam(teamA.getLeader(), new ArrayList<>(teamA.getAlivePlayers()), 0); + MatchTeam matchTeamB = new MatchTeam(teamB.getLeader(), new ArrayList<>(teamB.getAlivePlayers()), 1); + + + Kit kit = this.plugin.getKitManager().getKit(this.tournament.getKitName()); + Match match = new Match(this.plugin.getArenaManager().getRandomArena(kit, null), kit, QueueType.UN_RANKED, matchTeamA, matchTeamB); + + Player leaderA = this.plugin.getServer().getPlayer(teamA.getLeader()); + Player leaderB = this.plugin.getServer().getPlayer(teamB.getLeader()); + + match.broadcastMessage(CC.translate("&7Tournament match starting! " + LandCore.getInstance().getProfileManager().getProfile(leaderA.getUniqueId()).getGrant().getRank().getColor() + leaderA.getName() + " &7vs " + LandCore.getInstance().getProfileManager().getProfile(leaderB.getUniqueId()).getGrant().getRank().getColor() + leaderB.getName())); + + this.plugin.getServer().getScheduler().runTask(this.plugin, () -> { + this.plugin.getMatchManager().createMatch(match); + this.tournament.addMatch(match.getMatchId()); + this.plugin.getTournamentManager().addTournamentMatch(match.getMatchId()); + }); + } else { + for (UUID playerUUID : teamA.getAlivePlayers()) { + Player player = this.plugin.getServer().getPlayer(playerUUID); + player.sendMessage(CC.translate("&cYou have been skipped to the next round because there were no opponents for you this round.")); + } + } + } + + tournament.broadcast(" "); + tournament.broadcast(CC.translate("&e&lTournament")); + tournament.broadcast(CC.translate(" &a" + PracticeLang.VERTICAL_BAR + " &eKit: &7" + tournament.getKitName())); + tournament.broadcast(CC.translate(" &a" + PracticeLang.VERTICAL_BAR + " &eType: &7" + tournament.getTeamSize() + "v" + tournament.getTeamSize())); + tournament.broadcast(CC.translate(" &a" + PracticeLang.VERTICAL_BAR + " &ePlayers: &7" + tournament.getPlayers().size())); + tournament.broadcast(CC.translate(" &a" + PracticeLang.VERTICAL_BAR + " &eStarting Round: &7" + tournament.getCurrentRound())); + + + this.tournament.setTournamentState(TournamentState.FIGHTING); + } else if ((countdown % 5 == 0 || countdown < 5) && countdown > 0) { + this.tournament.broadcastWithSound(CC.translate("&8[&eTournament&8] &6Round &e#" + this.tournament.getCurrentRound() +" &7is starting in &e" + countdown + "&7."), Sound.NOTE_PLING); + } + } + } else { + this.cancel(); + } + } + + private void removeSpectator(UUID uuid) { + Player player = this.plugin.getServer().getPlayer(uuid); + if (player != null) { + Profile profile = this.plugin.getProfileManager().getProfileData(player.getUniqueId()); + if (profile.isSpectating()) { + this.plugin.getMatchManager().removeSpectator(player); + if (!profile.getCachedPlayer().isEmpty()) { + profile.getCachedPlayer().clear(); + } + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/state/TournamentState.java b/Practice/src/main/java/me/devkevin/practice/tournament/state/TournamentState.java new file mode 100644 index 0000000..4c75f46 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/state/TournamentState.java @@ -0,0 +1,12 @@ +package me.devkevin.practice.tournament.state; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public enum TournamentState { + WAITING, + STARTING, + FIGHTING +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/team/MatchRandomTeam.java b/Practice/src/main/java/me/devkevin/practice/tournament/team/MatchRandomTeam.java new file mode 100644 index 0000000..752f67b --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/team/MatchRandomTeam.java @@ -0,0 +1,14 @@ +package me.devkevin.practice.tournament.team; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter @AllArgsConstructor +public class MatchRandomTeam { + TournamentTeam team1, team2; +} diff --git a/Practice/src/main/java/me/devkevin/practice/tournament/team/TournamentTeam.java b/Practice/src/main/java/me/devkevin/practice/tournament/team/TournamentTeam.java new file mode 100644 index 0000000..dea2fba --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/tournament/team/TournamentTeam.java @@ -0,0 +1,39 @@ +package me.devkevin.practice.tournament.team; + +import lombok.Getter; +import me.devkevin.practice.match.team.KillableTeam; +import me.devkevin.practice.party.Party; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class TournamentTeam extends KillableTeam { + private final Map playerNames = new HashMap<>(); + + public TournamentTeam(UUID leader, List players) { + super(leader, players); + + for (UUID playerUUID : players) { + Party party = this.plugin.getPartyManager().getParty(playerUUID); + if (party == null) { + this.playerNames.put(playerUUID, this.plugin.getServer().getPlayer(playerUUID).getName()); + } + } + } + + public void broadcastMessage(String message) { + this.alivePlayers().forEach(player -> player.sendMessage(message)); + } + + public String getPlayerName(UUID uuid) { + return this.playerNames.get(uuid); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/Animation.java b/Practice/src/main/java/me/devkevin/practice/util/Animation.java new file mode 100644 index 0000000..3c5a309 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Animation.java @@ -0,0 +1,85 @@ +package me.devkevin.practice.util; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import lombok.Getter; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Copyright 05/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@Getter +public class Animation { + + @Getter + private static final Map> animations = Maps.newHashMap(); + + private final List lines = Lists.newArrayList(); + private final String name; + private final UUID uuid; + private final long seconds; + private long current; + private int index; + private String lineCurrent; + + public Animation(String name, UUID uuid, int seconds){ + this.name = name; + this.uuid = uuid; + this.seconds = seconds * 20L; + + Map map = Maps.newHashMap(); + + map.put(name, this); + + if(!animations.containsKey(uuid)){ + animations.put(uuid, map); + }else{ + animations.get(uuid).put(name, this); + } + } + + public Animation(String name, UUID uuid, long seconds){ + this.name = name; + this.uuid = uuid; + this.seconds = seconds; + + Map map = Maps.newHashMap(); + + map.put(name, this); + + if(!animations.containsKey(uuid)){ + animations.put(uuid, map); + }else{ + animations.get(uuid).put(name, this); + } + } + + public String getLine() { + if (lineCurrent == null || lineCurrent.equals("")){ + return lineCurrent = lines.get(0); + } + if (current == seconds) { + int newIndex = ++index; + if(newIndex >= lines.size()){ + newIndex = 0; + index = 0; + } + current = 0; + lineCurrent = lines.get(newIndex); + } + current++; + return lineCurrent; + } + + public static Animation getAnimation(UUID uuid, String name){ + if (animations.get(uuid) == null){ + return null; + } + return animations.get(uuid).get(name); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/BlockUtil.java b/Practice/src/main/java/me/devkevin/practice/util/BlockUtil.java new file mode 100644 index 0000000..f35f5f8 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/BlockUtil.java @@ -0,0 +1,280 @@ +package me.devkevin.practice.util; + +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; + +import java.util.HashSet; +import java.util.Set; + +/** + * Copyright 11/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class BlockUtil { + + private static Set blockSolidPassSet; + private static Set blockStairsSet; + private static Set blockLiquidsSet; + private static Set blockWebsSet; + private static Set blockIceSet; + private static Set blockCarpetSet; + + static { + BlockUtil.blockSolidPassSet = new HashSet(); + BlockUtil.blockStairsSet = new HashSet(); + BlockUtil.blockLiquidsSet = new HashSet(); + BlockUtil.blockWebsSet = new HashSet(); + BlockUtil.blockIceSet = new HashSet(); + BlockUtil.blockCarpetSet = new HashSet(); + BlockUtil.blockSolidPassSet.add((byte) 0); + BlockUtil.blockSolidPassSet.add((byte) 6); + BlockUtil.blockSolidPassSet.add((byte) 8); + BlockUtil.blockSolidPassSet.add((byte) 9); + BlockUtil.blockSolidPassSet.add((byte) 10); + BlockUtil.blockSolidPassSet.add((byte) 11); + BlockUtil.blockSolidPassSet.add((byte) 27); + BlockUtil.blockSolidPassSet.add((byte) 28); + BlockUtil.blockSolidPassSet.add((byte) 30); + BlockUtil.blockSolidPassSet.add((byte) 31); + BlockUtil.blockSolidPassSet.add((byte) 32); + BlockUtil.blockSolidPassSet.add((byte) 37); + BlockUtil.blockSolidPassSet.add((byte) 38); + BlockUtil.blockSolidPassSet.add((byte) 39); + BlockUtil.blockSolidPassSet.add((byte) 40); + BlockUtil.blockSolidPassSet.add((byte) 50); + BlockUtil.blockSolidPassSet.add((byte) 51); + BlockUtil.blockSolidPassSet.add((byte) 55); + BlockUtil.blockSolidPassSet.add((byte) 59); + BlockUtil.blockSolidPassSet.add((byte) 63); + BlockUtil.blockSolidPassSet.add((byte) 66); + BlockUtil.blockSolidPassSet.add((byte) 68); + BlockUtil.blockSolidPassSet.add((byte) 69); + BlockUtil.blockSolidPassSet.add((byte) 70); + BlockUtil.blockSolidPassSet.add((byte) 72); + BlockUtil.blockSolidPassSet.add((byte) 75); + BlockUtil.blockSolidPassSet.add((byte) 76); + BlockUtil.blockSolidPassSet.add((byte) 77); + BlockUtil.blockSolidPassSet.add((byte) 78); + BlockUtil.blockSolidPassSet.add((byte) 83); + BlockUtil.blockSolidPassSet.add((byte) 90); + BlockUtil.blockSolidPassSet.add((byte) 104); + BlockUtil.blockSolidPassSet.add((byte) 105); + BlockUtil.blockSolidPassSet.add((byte) 115); + BlockUtil.blockSolidPassSet.add((byte) 119); + BlockUtil.blockSolidPassSet.add((byte) (-124)); + BlockUtil.blockSolidPassSet.add((byte) (-113)); + BlockUtil.blockSolidPassSet.add((byte) (-81)); + BlockUtil.blockStairsSet.add((byte) 53); + BlockUtil.blockStairsSet.add((byte) 67); + BlockUtil.blockStairsSet.add((byte) 108); + BlockUtil.blockStairsSet.add((byte) 109); + BlockUtil.blockStairsSet.add((byte) 114); + BlockUtil.blockStairsSet.add((byte) (-128)); + BlockUtil.blockStairsSet.add((byte) (-122)); + BlockUtil.blockStairsSet.add((byte) (-121)); + BlockUtil.blockStairsSet.add((byte) (-120)); + BlockUtil.blockStairsSet.add((byte) (-100)); + BlockUtil.blockStairsSet.add((byte) (-93)); + BlockUtil.blockStairsSet.add((byte) (-92)); + BlockUtil.blockStairsSet.add((byte) (-76)); + BlockUtil.blockStairsSet.add((byte) 126); + BlockUtil.blockStairsSet.add((byte) (-74)); + BlockUtil.blockStairsSet.add((byte) 44); + BlockUtil.blockStairsSet.add((byte) 78); + BlockUtil.blockStairsSet.add((byte) 99); + BlockUtil.blockStairsSet.add((byte) (-112)); + BlockUtil.blockStairsSet.add((byte) (-115)); + BlockUtil.blockStairsSet.add((byte) (-116)); + BlockUtil.blockStairsSet.add((byte) (-105)); + BlockUtil.blockStairsSet.add((byte) (-108)); + BlockUtil.blockStairsSet.add((byte) 100); + BlockUtil.blockLiquidsSet.add((byte) 8); + BlockUtil.blockLiquidsSet.add((byte) 9); + BlockUtil.blockLiquidsSet.add((byte) 10); + BlockUtil.blockLiquidsSet.add((byte) 11); + BlockUtil.blockWebsSet.add((byte) 30); + BlockUtil.blockIceSet.add((byte) 79); + BlockUtil.blockIceSet.add((byte) (-82)); + BlockUtil.blockCarpetSet.add((byte) (-85)); + } + + public static boolean isStandingOn(Player player, Material material) { + Block legs = player.getLocation().getBlock(); + Block head = legs.getRelative(BlockFace.UP); + return legs.getType() == material || head.getType() == material; + + } + + public static boolean isSameLocation(final Location location, final Location check) { + return location.getWorld().getName().equalsIgnoreCase(check.getWorld().getName()) && location.getBlockX() == check.getBlockX() && location.getBlockY() == check.getBlockY() && location.getBlockZ() == check.getBlockZ(); + } + + public static boolean isOnStairs(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockStairsSet, down); + } + + public static boolean isOnLiquid(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockLiquidsSet, down); + } + + public static boolean isOnWeb(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockWebsSet, down); + } + + public static boolean isOnIce(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockIceSet, down); + } + + public static boolean isOnCarpet(final Location location, final int down) { + return isUnderBlock(location, BlockUtil.blockCarpetSet, down); + } + + private static boolean isUnderBlock(final Location location, final Set itemIDs, final int down) { + final double posX = location.getX(); + final double posZ = location.getZ(); + final double fracX = (posX % 1.0 > 0.0) ? Math.abs(posX % 1.0) : (1.0 - Math.abs(posX % 1.0)); + final double fracZ = (posZ % 1.0 > 0.0) ? Math.abs(posZ % 1.0) : (1.0 - Math.abs(posZ % 1.0)); + final int blockX = location.getBlockX(); + final int blockY = location.getBlockY() - down; + final int blockZ = location.getBlockZ(); + final World world = location.getWorld(); + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ).getTypeId())) { + return true; + } + if (fracX < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ).getTypeId())) { + return true; + } + if (fracZ < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + } + } else if (fracX > 0.7) { + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ).getTypeId())) { + return true; + } + if (fracZ < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (itemIDs.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (itemIDs.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + } + } else if (fracZ < 0.3) { + if (itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7 && itemIDs.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + return false; + } + + public static boolean isOnGround(final Location location, final int down) { + final double posX = location.getX(); + final double posZ = location.getZ(); + final double fracX = (posX % 1.0 > 0.0) ? Math.abs(posX % 1.0) : (1.0 - Math.abs(posX % 1.0)); + final double fracZ = (posZ % 1.0 > 0.0) ? Math.abs(posZ % 1.0) : (1.0 - Math.abs(posZ % 1.0)); + final int blockX = location.getBlockX(); + final int blockY = location.getBlockY() - down; + final int blockZ = location.getBlockZ(); + final World world = location.getWorld(); + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ).getTypeId())) { + return true; + } + if (fracX < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ).getTypeId())) { + return true; + } + if (fracZ < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + } + } else if (fracX > 0.7) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ).getTypeId())) { + return true; + } + if (fracZ < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX - 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX + 1, blockY, blockZ + 1).getTypeId())) { + return true; + } + } + } else if (fracZ < 0.3) { + if (!BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ - 1).getTypeId())) { + return true; + } + } else if (fracZ > 0.7 && !BlockUtil.blockSolidPassSet.contains((byte) world.getBlockAt(blockX, blockY, blockZ + 1).getTypeId())) { + return true; + } + return false; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/BukkitReflection.java b/Practice/src/main/java/me/devkevin/practice/util/BukkitReflection.java new file mode 100644 index 0000000..709a39d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/BukkitReflection.java @@ -0,0 +1,118 @@ +package me.devkevin.practice.util; + +import org.bukkit.Bukkit; +import org.bukkit.Server; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Copyright 09/09/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class BukkitReflection { + + private static final String CRAFT_BUKKIT_PACKAGE; + private static final String NET_MINECRAFT_SERVER_PACKAGE; + + private static final Class CRAFT_SERVER_CLASS; + private static final Method CRAFT_SERVER_GET_HANDLE_METHOD; + + private static final Class PLAYER_LIST_CLASS; + private static final Field PLAYER_LIST_MAX_PLAYERS_FIELD; + + private static final Class CRAFT_PLAYER_CLASS; + private static final Method CRAFT_PLAYER_GET_HANDLE_METHOD; + + private static final Class ENTITY_PLAYER_CLASS; + private static final Field ENTITY_PLAYER_PING_FIELD; + + private static final Class CRAFT_ITEM_STACK_CLASS; + private static final Method CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD; + private static final Class ENTITY_ITEM_STACK_CLASS; + private static final Method ENTITY_ITEM_STACK_GET_NAME; + + private static final Class SPIGOT_CONFIG_CLASS; + private static final Field SPIGOT_CONFIG_BUNGEE_FIELD; + + static { + try { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]; + + CRAFT_BUKKIT_PACKAGE = "org.bukkit.craftbukkit." + version + "."; + NET_MINECRAFT_SERVER_PACKAGE = "net.minecraft.server.v1_8_R3." + version + "."; + + CRAFT_SERVER_CLASS = Class.forName(CRAFT_BUKKIT_PACKAGE + "CraftServer"); + CRAFT_SERVER_GET_HANDLE_METHOD = CRAFT_SERVER_CLASS.getDeclaredMethod("getHandle"); + CRAFT_SERVER_GET_HANDLE_METHOD.setAccessible(true); + + PLAYER_LIST_CLASS = Class.forName(NET_MINECRAFT_SERVER_PACKAGE + "PlayerList"); + PLAYER_LIST_MAX_PLAYERS_FIELD = PLAYER_LIST_CLASS.getDeclaredField("maxPlayers"); + PLAYER_LIST_MAX_PLAYERS_FIELD.setAccessible(true); + + CRAFT_PLAYER_CLASS = Class.forName(CRAFT_BUKKIT_PACKAGE + "entity.CraftPlayer"); + CRAFT_PLAYER_GET_HANDLE_METHOD = CRAFT_PLAYER_CLASS.getDeclaredMethod("getHandle"); + CRAFT_PLAYER_GET_HANDLE_METHOD.setAccessible(true); + + ENTITY_PLAYER_CLASS = Class.forName(NET_MINECRAFT_SERVER_PACKAGE + "EntityPlayer"); + ENTITY_PLAYER_PING_FIELD = ENTITY_PLAYER_CLASS.getDeclaredField("ping"); + ENTITY_PLAYER_PING_FIELD.setAccessible(true); + + CRAFT_ITEM_STACK_CLASS = Class.forName(CRAFT_BUKKIT_PACKAGE + "inventory.CraftItemStack"); + CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD = + CRAFT_ITEM_STACK_CLASS.getDeclaredMethod("asNMSCopy", ItemStack.class); + CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD.setAccessible(true); + + ENTITY_ITEM_STACK_CLASS = Class.forName(NET_MINECRAFT_SERVER_PACKAGE + "ItemStack"); + ENTITY_ITEM_STACK_GET_NAME = ENTITY_ITEM_STACK_CLASS.getDeclaredMethod("getName"); + + SPIGOT_CONFIG_CLASS = Class.forName("org.spigotmc.SpigotConfig"); + SPIGOT_CONFIG_BUNGEE_FIELD = SPIGOT_CONFIG_CLASS.getDeclaredField("bungee"); + SPIGOT_CONFIG_BUNGEE_FIELD.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + + throw new RuntimeException("Failed to initialize Bukkit/NMS Reflection"); + } + } + + public static int getPing(Player player) { + try { + int ping = ENTITY_PLAYER_PING_FIELD.getInt(CRAFT_PLAYER_GET_HANDLE_METHOD.invoke(player)); + + return ping > 0 ? ping : 0; + } catch (Exception e) { + return 1; + } + } + + public static void setMaxPlayers(Server server, int slots) { + try { + PLAYER_LIST_MAX_PLAYERS_FIELD.set(CRAFT_SERVER_GET_HANDLE_METHOD.invoke(server), slots); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static String getItemStackName(ItemStack itemStack) { + try { + return (String) ENTITY_ITEM_STACK_GET_NAME.invoke(CRAFT_ITEM_STACK_AS_NMS_COPY_METHOD.invoke(itemStack, itemStack)); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + public static boolean isBungeeServer() { + try { + return (boolean) SPIGOT_CONFIG_BUNGEE_FIELD.get(null); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ByteBufUtils.java b/Practice/src/main/java/me/devkevin/practice/util/ByteBufUtils.java new file mode 100644 index 0000000..c614b3c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ByteBufUtils.java @@ -0,0 +1,155 @@ +package me.devkevin.practice.util; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.experimental.UtilityClass; +import org.apache.commons.io.Charsets; +import org.apache.commons.io.IOUtils; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; + +import java.io.*; +import java.util.UUID; +import java.util.function.Consumer; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +/** + * Copyright 31/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@UtilityClass +public class ByteBufUtils { + + // IO // + + public void writeGzipped(File file, Consumer writer) { + try { + OutputStream fileOutputStream = new GZIPOutputStream(new FileOutputStream(file)); + ByteBuf buffer = Unpooled.buffer(); + + writer.accept(buffer); + + byte[] bytes = new byte[buffer.readableBytes()]; + buffer.getBytes(buffer.readerIndex(), bytes); + + fileOutputStream.write(bytes); + fileOutputStream.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + public ByteBuf readGzipped(File file) { + try (InputStream fileInputStream = new GZIPInputStream(new FileInputStream(file))) { + byte[] data = IOUtils.toByteArray(fileInputStream); + return Unpooled.wrappedBuffer(data); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + + // VarInt // + + public static int readVarInt(ByteBuf in) { + int out = 0; + int bytes = 0; + byte bIn; + + while (true) { + bIn = in.readByte(); + + out |= (bIn & 0x7F) << (bytes++ * 7); + + // 5 is the max size of a VarInt. + if (bytes > 5) { + throw new RuntimeException("VarInt too big"); + } + + if ((bIn & 0x80) != 0x80) { + break; + } + } + + return out; + } + + public static void writeVarInt(int value, ByteBuf out) { + int part; + + while (true) { + part = value & 0x7F; + value >>>= 7; + + if (value != 0) { + part |= 0x80; + } + + out.writeByte(part); + + if (value == 0) { + break; + } + } + } + + // String // + + public static String readString(ByteBuf in) { + int len = readVarInt(in); + byte[] b = new byte[len]; + in.readBytes(b); + + return new String(b, Charsets.UTF_8); + } + + public static void writeString(String value, ByteBuf out) { + byte[] b = value.getBytes(Charsets.UTF_8); + + writeVarInt(b.length, out); + out.writeBytes(b); + } + + // UUID // + + public static UUID readUuid(ByteBuf in) { + long mostSig = in.readLong(); + long leastSig = in.readLong(); + + return new UUID(mostSig, leastSig); + } + + public static void writeUuid(UUID value, ByteBuf out) { + out.writeLong(value.getMostSignificantBits()); + out.writeLong(value.getLeastSignificantBits()); + } + + // Our weird simplistic item stack // + // we just store data, type, and has enchants + + public static ItemStack readSimplisticItem(ByteBuf in) { + ItemStack result = new ItemStack( + Material.getMaterial(readVarInt(in)), + in.readByte() + ); + + if (in.readBoolean()) { + result.addUnsafeEnchantment(Enchantment.DURABILITY, 1); + } + + return result; + } + + public static void writeSimplisticItem(ItemStack value, ByteBuf out) { + if (value == null) { + value = new ItemStack(Material.AIR); + } + + writeVarInt(value.getTypeId(), out); + out.writeByte(value.getData().getData()); + out.writeBoolean(value.getEnchantments().size() != 0); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ChatComponentBuilder.java b/Practice/src/main/java/me/devkevin/practice/util/ChatComponentBuilder.java new file mode 100644 index 0000000..6228226 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ChatComponentBuilder.java @@ -0,0 +1,216 @@ +package me.devkevin.practice.util; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.*; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; + +public class ChatComponentBuilder extends ComponentBuilder { + + private static Field partsField; + private static Field currField; + + static { + try { + currField = ComponentBuilder.class.getDeclaredField("current"); + partsField = ComponentBuilder.class.getDeclaredField("parts"); + + currField.setAccessible(true); + partsField.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + } + + public ChatComponentBuilder(String text) { + super(""); + this.parse(text); + } + + public TextComponent getCurrent() { + try { + return (TextComponent) currField.get(this); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + public void setCurrent(TextComponent tc) { + try { + currField.set(this, tc); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + public List getParts() { + try { + return (List) partsField.get(this); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + return null; + } + + public ChatComponentBuilder setCurrentHoverEvent(HoverEvent hoverEvent) { + this.getCurrent().setHoverEvent(hoverEvent); + + return this; + } + + public ChatComponentBuilder setCurrentClickEvent(ClickEvent clickEvent) { + this.getCurrent().setClickEvent(clickEvent); + + return this; + } + + public ChatComponentBuilder attachToEachPart(HoverEvent hoverEvent) { + for (Object part : getParts()) { + TextComponent component = (TextComponent) part; + + if (component.getHoverEvent() == null) { + component.setHoverEvent(hoverEvent); + } + } + + this.getCurrent().setHoverEvent(hoverEvent); + + return this; + } + + public ChatComponentBuilder attachToEachPart(ClickEvent clickEvent) { + for (Object part : getParts()) { + TextComponent component = (TextComponent) part; + + if (component.getClickEvent() == null) { + component.setClickEvent(clickEvent); + } + } + + this.getCurrent().setClickEvent(clickEvent); + + return this; + } + + public ChatComponentBuilder parse(String text) { + String regex = "[&§]{1}([a-fA-Fl-oL-O0-9-r]){1}"; + text = text.replaceAll(regex, "§$1"); + + if (!Pattern.compile(regex).matcher(text).find()) { + if (getParts().isEmpty() && getCurrent() != null && getCurrent().getText().isEmpty()) { + getCurrent().setText(text); + } else { + this.append(text); + } + + return this; + } + + String[] words = text.split(regex); + int index = words[0].length(); + + for (String word : words) { + try { + if (index != words[0].length()) { + if (getParts().isEmpty() && getCurrent() != null && getCurrent().getText().isEmpty()) { + getCurrent().setText(word); + } else { + this.append(word); + } + + ChatColor color = ChatColor.getByChar(text.charAt(index - 1)); + + if (color == ChatColor.BOLD) { + this.bold(true); + } else if (color == ChatColor.STRIKETHROUGH) { + this.strikethrough(true); + } else if (color == ChatColor.MAGIC) { + this.obfuscated(true); + } else if (color == ChatColor.UNDERLINE) { + this.underlined(true); + } else if (color == ChatColor.RESET) { + this.bold(false); + this.strikethrough(false); + this.obfuscated(false); + this.underlined(false); + } else { + this.color(color); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + + index += word.length() + 2; + } + + return this; + } + + public ChatComponentBuilder append(BaseComponent[] components) { + for (BaseComponent component : components) { + append((TextComponent) component); + } + + return this; + } + + public ChatComponentBuilder append(TextComponent textComponent) { + if (textComponent == null) { + return this; + } + + String text = textComponent.getText(); + ChatColor color = textComponent.getColor(); + boolean bold = textComponent.isBold(); + boolean underline = textComponent.isUnderlined(); + boolean italic = textComponent.isUnderlined(); + boolean strike = textComponent.isStrikethrough(); + HoverEvent he = textComponent.getHoverEvent(); + ClickEvent ce = textComponent.getClickEvent(); + + append(text); + color(color); + underlined(underline); + italic(italic); + strikethrough(strike); + event(he); + event(ce); + + if (textComponent.getExtra() != null) { + for (BaseComponent bc : textComponent.getExtra()) { + if (bc instanceof TextComponent) { + append((TextComponent) bc); + } + } + } + + return this; + } + + @Override + public BaseComponent[] create() { + List components = new ArrayList<>(getParts()); + components.add(getCurrent()); + + TextComponent first = components.get(0); + + if (first.getText().isEmpty()) { + components.remove(0); + } + + TextComponent last = components.get(components.size() - 1); + + if (last.getText().isEmpty()) { + components.remove(components.size() - 1); + } + + return components.toArray(new BaseComponent[components.size()]); + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/Circle.java b/Practice/src/main/java/me/devkevin/practice/util/Circle.java new file mode 100644 index 0000000..4cdea50 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Circle.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.util; + +import org.bukkit.Location; + +import java.util.ArrayList; +import java.util.List; + +/** + * Copyright 20/10/2019 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class Circle { + + public static List getCircle(Location center, float radius, int amount) { + List list = new ArrayList<>(); + for (int i = 0; i < amount; i++) { + double a = 2 * Math.PI / amount * i; + double x = Math.cos(a) * radius; + double z = Math.sin(a) * radius; + list.add(center.clone().add(x, 0, z)); + } + return list; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/Clickable.java b/Practice/src/main/java/me/devkevin/practice/util/Clickable.java new file mode 100644 index 0000000..95080fb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Clickable.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import lombok.NoArgsConstructor; +import net.md_5.bungee.api.chat.*; +import org.bukkit.entity.Player; + +/** + * Copyright 10/06/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@NoArgsConstructor +public class Clickable { + + private List components = new ArrayList<>(); + + public Clickable(String msg) { + TextComponent message = new TextComponent(msg); + + this.components.add(message); + } + + public Clickable(String msg, String hoverMsg, String clickString) { + this.add(msg, hoverMsg, clickString); + } + + public TextComponent add(String msg, String hoverMsg, String clickString) { + TextComponent message = new TextComponent(msg); + + if (hoverMsg != null) { + message.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(hoverMsg).create())); + } + + if (clickString != null) { + message.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, clickString)); + } + + this.components.add(message); + + return message; + } + + public void add(String message) { + this.components.add(new TextComponent(message)); + } + + public void sendToPlayer(Player player) { + player.sendMessage(this.asComponents()); + } + + public TextComponent[] asComponents() { + return this.components.toArray(new TextComponent[0]); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/Color.java b/Practice/src/main/java/me/devkevin/practice/util/Color.java new file mode 100644 index 0000000..6fe8418 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Color.java @@ -0,0 +1,23 @@ +package me.devkevin.practice.util; + +import org.bukkit.ChatColor; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Copyright 04/06/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class Color { + + public static String translate( String str ){ + return ChatColor.translateAlternateColorCodes('&', str); + } + + + public static List translate(List list){ + return list.stream().map(Color::translate).collect(Collectors.toList()); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter.java b/Practice/src/main/java/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter.java new file mode 100644 index 0000000..639119c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter.java @@ -0,0 +1,69 @@ +package me.devkevin.practice.util; + +import com.google.gson.*; +import com.google.gson.reflect.TypeToken; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.ConfigurationSerialization; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.LinkedHashMap; +import java.util.Map; +/** + * Copyright 29/04/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ConfigurationSerializableTypeAdapter implements JsonDeserializer, JsonSerializer { + + private static final Type type = new TypeToken>() {}.getType(); + + private static ConfigurationSerializable deserializeObject(Map deserialized) { + LinkedHashMap conversion = new LinkedHashMap<>(deserialized.size()); + for (Map.Entry entry : deserialized.entrySet()) { + if (entry.getValue() instanceof Map && ((Map) (entry.getValue())).containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY)) { + Map raw = (Map) entry.getValue(); + Map typed = new LinkedHashMap<>(raw.size()); + for (Map.Entry child : raw.entrySet()) { + typed.put(child.getKey().toString(), fixObject(child.getKey().toString(), child.getValue())); + } + conversion.put(entry.getKey(), deserializeObject(typed)); + } else { + conversion.put(entry.getKey(), fixObject(entry.getKey(), entry.getValue())); + } + } + return ConfigurationSerialization.deserializeObject(conversion); + } + + private static Object fixObject(String key, Object object) { + if (object instanceof Double) { + return ((Double) object).intValue(); + } + return object; + } + + @Override + public ConfigurationSerializable deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + LinkedHashMap deserialized = context.deserialize(json, type); + if (deserialized.containsKey(ConfigurationSerialization.SERIALIZED_TYPE_KEY)) { + return deserializeObject(deserialized); + } else { + Method method = ((Class) typeOfT).getDeclaredMethod("deserialize", Map.class); + return (ConfigurationSerializable) method.invoke(null, deserialized); + } + } catch (Exception e) { + System.out.println("Currently In Block " + json.toString()); + throw new JsonParseException("Could not deserialize " + typeOfT + ".", e); + } + } + + @Override + public JsonElement serialize(ConfigurationSerializable src, Type typeOfSrc, JsonSerializationContext context) { + Map values = new LinkedHashMap<>(); + values.put(ConfigurationSerialization.SERIALIZED_TYPE_KEY, ConfigurationSerialization.getAlias(src.getClass())); + values.putAll(src.serialize()); + return context.serialize(values); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/Cooldown.java b/Practice/src/main/java/me/devkevin/practice/util/Cooldown.java new file mode 100644 index 0000000..363dfc5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Cooldown.java @@ -0,0 +1,163 @@ +package me.devkevin.practice.util; + +import java.text.DecimalFormat; +import java.util.UUID; + +/** + * Copyright 03/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class Cooldown { + + private UUID uniqueId; + + private long start; + + private long expire; + + private boolean notified; + + public Cooldown(int time) { + long duration = (1000 * time); + this.uniqueId = UUID.randomUUID(); + this.start = System.currentTimeMillis(); + this.expire = this.start + duration; + if (duration == 0L) { + 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 >= 0L); + } + + public String getTimeLeft() { + if (getRemaining() >= 60000L) { + return millisToRoundedTime(getRemaining()); + } + + return millisToSeconds(getRemaining()); + } + + public String getTimeMilisLeft() { + return millisToSeconds(getRemaining()); + } + + public String getContextLeft() { + return "second" + ((getRemaining() / 1000L > 1L) ? "s" : ""); + } + + public UUID getUniqueId() { + return this.uniqueId; + } + + public long getStart() { + return this.start; + } + + public long getExpire() { + return this.expire; + } + + public boolean isNotified() { + return this.notified; + } + + public void setUniqueId(UUID uniqueId) { + this.uniqueId = uniqueId; + } + + public void setStart(long start) { + this.start = start; + } + + public void setExpire(long expire) { + this.expire = expire; + } + + public void setNotified(boolean notified) { + this.notified = notified; + } + + public boolean equals(Object o) { + if (o == this) { + return true; + } + if (!(o instanceof Cooldown)) { + return false; + } + + Cooldown other = (Cooldown) o; + if (!other.canEqual(this)) { + return false; + } + + Object this$uniqueId = getUniqueId(); + Object other$uniqueId = other.getUniqueId(); + if (this$uniqueId == null) { + if (other$uniqueId == null) { + return (getStart() == other.getStart() && getExpire() == other.getExpire() && isNotified() == other.isNotified()); + } + } else if (this$uniqueId.equals(other$uniqueId)) { + return (getStart() == other.getStart() && getExpire() == other.getExpire() && isNotified() == other.isNotified()); + } + + return false; + } + + protected boolean canEqual(Object other) { + return other instanceof Cooldown; + } + + public int hashCode() { + int PRIME = 59; + int result = 1; + Object $uniqueId = getUniqueId(); + result = result * 59 + (($uniqueId == null) ? 43 : $uniqueId.hashCode()); + long $start = getStart(); + result = result * 59 + (int) ($start >>> 32L ^ $start); + long $expire = getExpire(); + result = result * 59 + (int) ($expire >>> 32L ^ $expire); + result = result * 59 + (isNotified() ? 79 : 97); + + return result; + } + + public String toString() { + return "Cooldown(uniqueId=" + getUniqueId() + ", start=" + getStart() + ", expire=" + getExpire() + ", notified=" + isNotified() + ")"; + } + + private String millisToSeconds(long millis) { + return new DecimalFormat("#0.0").format(((float) millis / 1000.0F)); + } + + private String millisToRoundedTime(long millis) { + millis++; + 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; + + minutes++; + if (years > 0L) return years + " year" + ((years == 1L) ? "" : "s"); + if (months > 0L) return months + " month" + ((months == 1L) ? "" : "s"); + if (weeks > 0L) return weeks + " week" + ((weeks == 1L) ? "" : "s"); + if (days > 0L) return days + " day" + ((days == 1L) ? "" : "s"); + if (hours > 0L) return hours + " hour" + ((hours == 1L) ? "" : "s"); + if (minutes > 0L) return minutes + " minute" + ((minutes == 1L) ? "" : "s"); + + return seconds + " second" + ((seconds == 1L) ? "" : "s"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/DateTimeFormats.java b/Practice/src/main/java/me/devkevin/practice/util/DateTimeFormats.java new file mode 100644 index 0000000..db04156 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/DateTimeFormats.java @@ -0,0 +1,56 @@ +package me.devkevin.practice.util; + +import org.apache.commons.lang.time.FastDateFormat; + +import java.time.*; +import java.text.*; +import java.util.*; + +/** + * Copyright 16/11/2019 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DateTimeFormats +{ + public static final TimeZone SERVER_TIME_ZONE; + public static final ZoneId SERVER_ZONE_ID; + public static final FastDateFormat DAY_MTH_HR_MIN_SECS; + public static final FastDateFormat DAY_MTH_YR_HR_MIN_AMPM; + public static final FastDateFormat DAY_MTH_HR_MIN_AMPM; + public static final FastDateFormat HR_MIN_AMPM; + public static final FastDateFormat HR_MIN_AMPM_TIMEZONE; + public static final FastDateFormat HR_MIN; + public static final FastDateFormat MIN_SECS; + public static final FastDateFormat KOTH_FORMAT; + public static final FastDateFormat PALACE_FORMAT; + public static final ThreadLocal REMAINING_SECONDS; + public static final ThreadLocal REMAINING_SECONDS_TRAILING; + + static { + SERVER_TIME_ZONE = TimeZone.getTimeZone("EST"); + SERVER_ZONE_ID = DateTimeFormats.SERVER_TIME_ZONE.toZoneId(); + DAY_MTH_HR_MIN_SECS = FastDateFormat.getInstance("dd/MM HH:mm:ss", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + DAY_MTH_YR_HR_MIN_AMPM = FastDateFormat.getInstance("MM/dd/yy hh:mma", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + DAY_MTH_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM hh:mma", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + HR_MIN_AMPM = FastDateFormat.getInstance("hh:mma", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + HR_MIN_AMPM_TIMEZONE = FastDateFormat.getInstance("hh:mma z", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + HR_MIN = FastDateFormat.getInstance("hh:mm", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + MIN_SECS = FastDateFormat.getInstance("mm:ss", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + KOTH_FORMAT = FastDateFormat.getInstance("m:ss", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + PALACE_FORMAT = FastDateFormat.getInstance("m:ss", DateTimeFormats.SERVER_TIME_ZONE, Locale.ENGLISH); + REMAINING_SECONDS = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.#"); + } + }; + REMAINING_SECONDS_TRAILING = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.0"); + } + }; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/DateUtil.java b/Practice/src/main/java/me/devkevin/practice/util/DateUtil.java new file mode 100644 index 0000000..5c5fcef --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/DateUtil.java @@ -0,0 +1,39 @@ +package me.devkevin.practice.util; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; + +/** + * Copyright 06/06/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class DateUtil { + + static String stringDateFormat = "MMMM d, yyyy"; + private static DateFormat dateFormat = new SimpleDateFormat(stringDateFormat); + + public static String getFormattedDate(long value) { + Date date = new Date(value); + return dateFormat.format(date).replaceAll(",", "th,"); + } + + public static String getTodayDate() { + Date todayDate = new Date(); + DateFormat todayDateFormat = new SimpleDateFormat("MMM dd, yyyy"); + todayDateFormat.setTimeZone(TimeZone.getTimeZone("US/Eastern")); + String strTodayDate = todayDateFormat.format(todayDate); + return strTodayDate; + } + + public static String getCurrentTime() { + DateFormat dateFormat = new SimpleDateFormat("hh:mm a"); + Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("US/Eastern")); + dateFormat.setTimeZone(cal.getTimeZone()); + String currentTime = dateFormat.format(cal.getTime()); + return currentTime; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/EffectUtils.java b/Practice/src/main/java/me/devkevin/practice/util/EffectUtils.java new file mode 100644 index 0000000..a37ff8e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/EffectUtils.java @@ -0,0 +1,87 @@ +package me.devkevin.practice.util; + +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Copyright 09/04/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class EffectUtils { + + public static String serializeEffects(Collection effects) { + StringBuilder builder = new StringBuilder(); + for (PotionEffect potionEffect : effects) { + builder.append(serializePotionEffect(potionEffect)); + builder.append(";"); + } + + return builder.toString(); + } + + public static Collection deserializeEffects(String source) { + if (!source.contains(":")) { + return null; + } + Collection effects = new ArrayList<>(); + String[] split = source.split(";"); + + for (String piece : split) { + effects.add(deserializePotionEffect(piece)); + } + + return effects; + } + + public static String serializePotionEffect(PotionEffect potionEffect) { + StringBuilder builder = new StringBuilder(); + + if (potionEffect == null) { + return "null"; + } + + String name = potionEffect.getType().getName(); + builder.append("n@").append(name); + + String duration = String.valueOf(potionEffect.getDuration()); + builder.append(":d@").append(duration); + + String amplifier = String.valueOf(potionEffect.getAmplifier()); + builder.append(":a@").append(amplifier); + + return builder.toString(); + } + + public static PotionEffect deserializePotionEffect(String source) { + String name = ""; + String duration = ""; + String amplifier = ""; + + if (source.equals("null")) { + return null; + } + + String[] split = source.split(":"); + for (String effectInfo : split) { + String[] itemAttribute = effectInfo.split("@"); + String s2 = itemAttribute[0]; + + if (s2.equalsIgnoreCase("n")) { + name = itemAttribute[1]; + } + if (s2.equalsIgnoreCase("d")) { + duration = itemAttribute[1]; + } + if (s2.equalsIgnoreCase("a")) { + amplifier = itemAttribute[1]; + } + } + + return new PotionEffect(PotionEffectType.getByName(name), Integer.parseInt(duration), Integer.parseInt(amplifier)); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/EntityUtils.java b/Practice/src/main/java/me/devkevin/practice/util/EntityUtils.java new file mode 100644 index 0000000..10cb9d9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/EntityUtils.java @@ -0,0 +1,112 @@ +package me.devkevin.practice.util; + +import lombok.experimental.UtilityClass; +import org.bukkit.entity.EntityType; + +import java.util.EnumMap; +import java.util.Map; + +/** + * Copyright 01/05/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@UtilityClass +public class EntityUtils { + + private final Map displayNames = new EnumMap<>(EntityType.class); + private int currentFakeEntityId = -1; + + public int getFakeEntityId() { + return currentFakeEntityId--; + } + + static { + displayNames.put(EntityType.ARROW, "Arrow"); + displayNames.put(EntityType.BAT, "Bat"); + displayNames.put(EntityType.BLAZE, "Blaze"); + displayNames.put(EntityType.BOAT, "Boat"); + displayNames.put(EntityType.CAVE_SPIDER, "Cave Spider"); + displayNames.put(EntityType.CHICKEN, "Chicken"); + displayNames.put(EntityType.COMPLEX_PART, "Complex Part"); + displayNames.put(EntityType.COW, "Cow"); + displayNames.put(EntityType.CREEPER, "Creeper"); + displayNames.put(EntityType.DROPPED_ITEM, "Item"); + displayNames.put(EntityType.EGG, "Egg"); + displayNames.put(EntityType.ENDER_CRYSTAL, "Ender Crystal"); + displayNames.put(EntityType.ENDER_DRAGON, "Ender Dragon"); + displayNames.put(EntityType.ENDER_PEARL, "Ender Pearl"); + displayNames.put(EntityType.ENDER_SIGNAL, "Ender Signal"); + displayNames.put(EntityType.ENDERMAN, "Enderman"); + displayNames.put(EntityType.EXPERIENCE_ORB, "Experience Orb"); + displayNames.put(EntityType.FALLING_BLOCK, "Falling Block"); + displayNames.put(EntityType.FIREBALL, "Fireball"); + displayNames.put(EntityType.FIREWORK, "Firework"); + displayNames.put(EntityType.FISHING_HOOK, "Fishing Rod Hook"); + displayNames.put(EntityType.GHAST, "Ghast"); + displayNames.put(EntityType.GIANT, "Giant"); + displayNames.put(EntityType.HORSE, "Horse"); + displayNames.put(EntityType.IRON_GOLEM, "Iron Golem"); + displayNames.put(EntityType.ITEM_FRAME, "Item Frame"); + displayNames.put(EntityType.LEASH_HITCH, "Lead Hitch"); + displayNames.put(EntityType.LIGHTNING, "Lightning"); + displayNames.put(EntityType.MAGMA_CUBE, "Magma Cube"); + displayNames.put(EntityType.MINECART, "Minecart"); + displayNames.put(EntityType.MINECART_CHEST, "Chest Minecart"); + displayNames.put(EntityType.MINECART_FURNACE, "Furnace Minecart"); + displayNames.put(EntityType.MINECART_HOPPER, "Hopper Minecart"); + displayNames.put(EntityType.MINECART_MOB_SPAWNER, "Spawner Minecart"); + displayNames.put(EntityType.MINECART_TNT, "TNT Minecart"); + displayNames.put(EntityType.OCELOT, "Ocelot"); + displayNames.put(EntityType.PAINTING, "Painting"); + displayNames.put(EntityType.PIG, "Pig"); + displayNames.put(EntityType.PIG_ZOMBIE, "Zombie Pigman"); + displayNames.put(EntityType.PLAYER, "Player"); + displayNames.put(EntityType.PRIMED_TNT, "TNT"); + displayNames.put(EntityType.SHEEP, "Sheep"); + displayNames.put(EntityType.SILVERFISH, "Silverfish"); + displayNames.put(EntityType.SKELETON, "Skeleton"); + displayNames.put(EntityType.SLIME, "Slime"); + displayNames.put(EntityType.SMALL_FIREBALL, "Fireball"); + displayNames.put(EntityType.SNOWBALL, "Snowball"); + displayNames.put(EntityType.SNOWMAN, "Snowman"); + displayNames.put(EntityType.SPIDER, "Spider"); + displayNames.put(EntityType.SPLASH_POTION, "Potion"); + displayNames.put(EntityType.SQUID, "Squid"); + displayNames.put(EntityType.THROWN_EXP_BOTTLE, "Experience Bottle"); + displayNames.put(EntityType.UNKNOWN, "Custom"); + displayNames.put(EntityType.VILLAGER, "Villager"); + displayNames.put(EntityType.WEATHER, "Weather"); + displayNames.put(EntityType.WITCH, "Witch"); + displayNames.put(EntityType.WITHER, "Wither"); + displayNames.put(EntityType.WITHER_SKULL, "Wither Skull"); + displayNames.put(EntityType.WOLF, "Wolf"); + displayNames.put(EntityType.ZOMBIE, "Zombie"); + } + + /** + * Gets the display name of a given entity type. + * + * @param type The entity type to lookup. + * @return The display name of the provided entity type. + */ + public String getName(EntityType type) { + return (displayNames.get(type)); + } + + public EntityType parse(String input) { + for (Map.Entry entry : displayNames.entrySet()) { + if (entry.getValue().replace(" ", "").equalsIgnoreCase(input)) { + return entry.getKey(); + } + } + + for (EntityType type : EntityType.values()) { + if (input.equalsIgnoreCase(type.toString())) { + return type; + } + } + + return null; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/GsonFactory.java b/Practice/src/main/java/me/devkevin/practice/util/GsonFactory.java new file mode 100644 index 0000000..7374dbe --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/GsonFactory.java @@ -0,0 +1,449 @@ +package me.devkevin.practice.util; + +import com.google.gson.*; +import com.google.gson.annotations.Expose; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; +import net.minecraft.server.v1_8_R3.MojangsonParseException; +import net.minecraft.server.v1_8_R3.MojangsonParser; +import net.minecraft.server.v1_8_R3.NBTBase; +import net.minecraft.server.v1_8_R3.NBTTagCompound; +import org.bukkit.*; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.configuration.serialization.ConfigurationSerialization; +import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_8_R3.util.CraftMagicNumbers; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.io.IOException; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Type; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +/* * + * Created by Joshua Bell (RingOfStorms) + * + * Post explaining here: [URL]http://bukkit.org/threads/gsonfactory-gson-that-works-on-itemstack-potioneffect-location-objects.331161/[/URL] + * */ +public class GsonFactory { + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD}) + public static @interface Ignore {} + + /* + - I want to not use Bukkit parsing for most objects... it's kind of clunky + - Instead... I want to start using any of Mojang's tags + - They're really well documented + built into MC, and handled by them. + - Rather than kill your old code, I'm going to write TypeAdapaters using Mojang's stuff. + */ + + private static final Gson g = new Gson(); + + private final static String CLASS_KEY = "SERIAL-ADAPTER-CLASS-KEY"; + + private static Gson prettyGson; + private static Gson compactGson; + + /** + * Returns a Gson instance for use anywhere with new line pretty printing + *

+ * Use @GsonIgnore in order to skip serialization and deserialization + *

+ * @return a Gson instance + */ + public static Gson getPrettyGson () { + if (prettyGson == null) + prettyGson = new GsonBuilder().addSerializationExclusionStrategy(new ExposeExclusion()) + .addDeserializationExclusionStrategy(new ExposeExclusion()) + .registerTypeHierarchyAdapter(ItemStack.class, new ItemStackGsonAdapter()) + .registerTypeHierarchyAdapter(ConfigurationSerializable.class, new ConfigurationSerializableTypeAdapter()) + .registerTypeAdapter(PotionEffect.class, new PotionEffectGsonAdapter()) + .registerTypeAdapter(Location.class, new LocationGsonAdapter()) + .registerTypeAdapter(Date.class, new DateGsonAdapter()) + .setPrettyPrinting() + .disableHtmlEscaping() + .create(); + return prettyGson; + } + + /** + * Returns a Gson instance for use anywhere with one line strings + *

+ * Use @GsonIgnore in order to skip serialization and deserialization + *

+ * @return a Gson instance + */ + public static Gson getCompactGson () { + if(compactGson == null) + compactGson = new GsonBuilder().addSerializationExclusionStrategy(new ExposeExclusion()) + .addDeserializationExclusionStrategy(new ExposeExclusion()) + .registerTypeHierarchyAdapter(ItemStack.class, new ItemStackGsonAdapter()) + .registerTypeHierarchyAdapter(ConfigurationSerializable.class, new ConfigurationSerializableTypeAdapter()) + .registerTypeAdapter(PotionEffect.class, new PotionEffectGsonAdapter()) + .registerTypeAdapter(Location.class, new LocationGsonAdapter()) + .registerTypeAdapter(Date.class, new DateGsonAdapter()) + .disableHtmlEscaping() + .create(); + return compactGson; + } + + /** + * Creates a new instance of Gson for use anywhere + *

+ * Use @GsonIgnore in order to skip serialization and deserialization + *

+ * @return a Gson instance + */ + public static Gson getNewGson(boolean prettyPrinting) { + GsonBuilder builder = new GsonBuilder().addSerializationExclusionStrategy(new ExposeExclusion()) + .addDeserializationExclusionStrategy(new ExposeExclusion()) + .registerTypeHierarchyAdapter(ItemStack.class, new NewItemStackAdapter()) + .disableHtmlEscaping(); + if (prettyPrinting) + builder.setPrettyPrinting(); + return builder.create(); + } + + private static Map recursiveSerialization (ConfigurationSerializable o) { + Map originalMap = o.serialize(); + Map map = new HashMap<>(); + for(Entry entry : originalMap.entrySet()) { + Object o2 = entry.getValue(); + if(o2 instanceof ConfigurationSerializable) { + ConfigurationSerializable serializable = (ConfigurationSerializable) o2; + Map newMap = recursiveSerialization(serializable); + newMap.put(CLASS_KEY, ConfigurationSerialization.getAlias(serializable.getClass())); + map.put(entry.getKey(), newMap); + } + } + map.put(CLASS_KEY, ConfigurationSerialization.getAlias(o.getClass())); + return map; + } + + private static Map recursiveDoubleToInteger (Map originalMap) { + Map map = new HashMap<>(); + for(Entry entry : originalMap.entrySet()) { + Object o = entry.getValue(); + if(o instanceof Double) { + Double d = (Double) o; + Integer i = d.intValue(); + map.put(entry.getKey(), i); + }else if(o instanceof Map) { + Map subMap = (Map) o; + map.put(entry.getKey(), recursiveDoubleToInteger(subMap)); + }else{ + map.put(entry.getKey(), o); + } + } + return map; + } + + private static class ExposeExclusion implements ExclusionStrategy { + @Override + public boolean shouldSkipField(FieldAttributes fieldAttributes) { + final Ignore ignore = fieldAttributes.getAnnotation(Ignore.class); + if(ignore != null) + return true; + final Expose expose = fieldAttributes.getAnnotation(Expose.class); + return expose != null && (!expose.serialize() || !expose.deserialize()); + } + + @Override + public boolean shouldSkipClass(Class aClass) { + return false; + } + } + + private static String nbtToString(NBTBase base) { + return base.toString().replace(",}", "}").replace(",]", "]").replaceAll("[0-9]+\\:", ""); + } + + private static net.minecraft.server.v1_8_R3.ItemStack removeSlot(ItemStack item) { + if (item == null) + return null; + net.minecraft.server.v1_8_R3.ItemStack nmsi = CraftItemStack.asNMSCopy(item); + if (nmsi == null) + return null; + NBTTagCompound nbtt = nmsi.getTag(); + if (nbtt != null) { + nbtt.remove("Slot"); + nmsi.setTag(nbtt); + } + return nmsi; + } + + private static ItemStack removeSlotNBT (ItemStack item) { + if (item == null) + return null; + net.minecraft.server.v1_8_R3.ItemStack nmsi = CraftItemStack.asNMSCopy(item); + if (nmsi == null) + return null; + NBTTagCompound nbtt = nmsi.getTag(); + if(nbtt != null) { + nbtt.remove("Slot"); + nmsi.setTag(nbtt); + } + return CraftItemStack.asBukkitCopy(nmsi); + } + + private static class NewItemStackAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, ItemStack itemStack) throws IOException { + if (itemStack == null) { + jsonWriter.nullValue(); + return; + } + net.minecraft.server.v1_8_R3.ItemStack item = removeSlot(itemStack); + if (item == null) { + jsonWriter.nullValue(); + return; + } + try { + jsonWriter.beginObject(); + jsonWriter.name("type"); + + jsonWriter.value(itemStack.getType().toString()); //I hate using this - but + jsonWriter.name("amount"); + + jsonWriter.value(itemStack.getAmount()); + jsonWriter.name("data"); + + + jsonWriter.value(itemStack.getDurability()); + jsonWriter.name("tag"); + + if (item != null && item.getTag() != null) { + jsonWriter.value(nbtToString(item.getTag())); + } else + jsonWriter.value(""); + jsonWriter.endObject(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + @Override + public ItemStack read(JsonReader jsonReader) throws IOException { + if (jsonReader.peek() == JsonToken.NULL) { + return null; + } + jsonReader.beginObject(); + jsonReader.nextName(); + Material type = Material.getMaterial(jsonReader.nextString()); + jsonReader.nextName(); + int amount = jsonReader.nextInt(); + jsonReader.nextName(); + int data = jsonReader.nextInt(); + net.minecraft.server.v1_8_R3.ItemStack item = new net.minecraft.server.v1_8_R3.ItemStack(CraftMagicNumbers.getItem(type), amount, data); + jsonReader.nextName(); + String next = jsonReader.nextString(); + if (next.startsWith("{")) { + NBTTagCompound compound = null; + try { + compound = MojangsonParser.parse(ChatColor.translateAlternateColorCodes('&', next)); + } catch (MojangsonParseException e) { + e.printStackTrace(); + } + item.setTag(compound); + } + jsonReader.endObject(); + return CraftItemStack.asBukkitCopy(item); + } + } + + private static class ItemStackGsonAdapter extends TypeAdapter { + + private static Type seriType = new TypeToken>(){}.getType(); + + @Override + public void write(JsonWriter jsonWriter, ItemStack itemStack) throws IOException { + if(itemStack == null) { + jsonWriter.nullValue(); + return; + } + jsonWriter.value(getRaw(removeSlotNBT(itemStack))); + } + + @Override + public ItemStack read(JsonReader jsonReader) throws IOException { + if(jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + return null; + } + return fromRaw(jsonReader.nextString()); + } + + private String getRaw (ItemStack item) { + Map serial = item.serialize(); + + if(serial.get("meta") != null) { + ItemMeta itemMeta = item.getItemMeta(); + + Map originalMeta = itemMeta.serialize(); + Map meta = new HashMap<>(); + for(Entry entry : originalMeta.entrySet()) + meta.put(entry.getKey(), entry.getValue()); + Object o; + for(Entry entry : meta.entrySet()) { + o = entry.getValue(); + if(o instanceof ConfigurationSerializable) { + ConfigurationSerializable serializable = (ConfigurationSerializable) o; + Map serialized = recursiveSerialization(serializable); + meta.put(entry.getKey(), serialized); + } + } + serial.put("meta", meta); + } + + return g.toJson(serial); + } + + private ItemStack fromRaw (String raw) { + Map keys = g.fromJson(raw, seriType); + + if(keys.get("amount") != null) { + Double d = (Double) keys.get("amount"); + Integer i = d.intValue(); + keys.put("amount", i); + } + + ItemStack item; + try { + item = ItemStack.deserialize(keys); + }catch(Exception e) { + return null; + } + + if(item == null) + return null; + + if(keys.containsKey("meta")) { + Map itemmeta = (Map) keys.get("meta"); + itemmeta = recursiveDoubleToInteger(itemmeta); + ItemMeta meta = (ItemMeta) ConfigurationSerialization.deserializeObject(itemmeta, ConfigurationSerialization.getClassByAlias("ItemMeta")); + item.setItemMeta(meta); + } + + return item; + } + } + + private static class PotionEffectGsonAdapter extends TypeAdapter { + + private static Type seriType = new TypeToken>(){}.getType(); + + private static String TYPE = "effect"; + private static String DURATION = "duration"; + private static String AMPLIFIER = "amplifier"; + private static String AMBIENT = "ambient"; + + @Override + public void write(JsonWriter jsonWriter, PotionEffect potionEffect) throws IOException { + if(potionEffect == null) { + jsonWriter.nullValue(); + return; + } + jsonWriter.value(getRaw(potionEffect)); + } + + @Override + public PotionEffect read(JsonReader jsonReader) throws IOException { + if(jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + return null; + } + return fromRaw(jsonReader.nextString()); + } + + private String getRaw (PotionEffect potion) { + Map serial = potion.serialize(); + + return g.toJson(serial); + } + + private PotionEffect fromRaw (String raw) { + Map keys = g.fromJson(raw, seriType); + return new PotionEffect(PotionEffectType.getById(((Double) keys.get(TYPE)).intValue()), ((Double) keys.get(DURATION)).intValue(), ((Double) keys.get(AMPLIFIER)).intValue(), (Boolean) keys.get(AMBIENT)); + } + } + + private static class LocationGsonAdapter extends TypeAdapter { + + private static Type seriType = new TypeToken>(){}.getType(); + + private static String UUID = "uniqueId"; + private static String X = "x"; + private static String Y = "y"; + private static String Z = "z"; + private static String YAW = "yaw"; + private static String PITCH = "pitch"; + + @Override + public void write(JsonWriter jsonWriter, Location location) throws IOException { + if(location == null) { + jsonWriter.nullValue(); + return; + } + jsonWriter.value(getRaw(location)); + } + + @Override + public Location read(JsonReader jsonReader) throws IOException { + if(jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + return null; + } + return fromRaw(jsonReader.nextString()); + } + + private String getRaw (Location location) { + Map serial = new HashMap<>(); + serial.put(UUID, location.getWorld().getUID().toString()); + serial.put(X, Double.toString(location.getX())); + serial.put(Y, Double.toString(location.getY())); + serial.put(Z, Double.toString(location.getZ())); + serial.put(YAW, Float.toString(location.getYaw())); + serial.put(PITCH, Float.toString(location.getPitch())); + return g.toJson(serial); + } + + private Location fromRaw (String raw) { + Map keys = g.fromJson(raw, seriType); + World w = Bukkit.getWorld(java.util.UUID.fromString((String) keys.get(UUID))); + return new Location(w, Double.parseDouble((String) keys.get(X)), Double.parseDouble((String) keys.get(Y)), Double.parseDouble((String) keys.get(Z)), + Float.parseFloat((String) keys.get(YAW)), Float.parseFloat((String) keys.get(PITCH))); + } + } + + private static class DateGsonAdapter extends TypeAdapter { + @Override + public void write(JsonWriter jsonWriter, Date date) throws IOException { + if(date == null) { + jsonWriter.nullValue(); + return; + } + jsonWriter.value(date.getTime()); + } + + @Override + public Date read(JsonReader jsonReader) throws IOException { + if(jsonReader.peek() == JsonToken.NULL) { + jsonReader.nextNull(); + return null; + } + return new Date(jsonReader.nextLong()); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/InventoryUtil.java b/Practice/src/main/java/me/devkevin/practice/util/InventoryUtil.java new file mode 100644 index 0000000..6cbce97 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/InventoryUtil.java @@ -0,0 +1,205 @@ +package me.devkevin.practice.util; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.util.io.BukkitObjectInputStream; +import org.bukkit.util.io.BukkitObjectOutputStream; +import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +/** + * Copyright 02/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +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[0]); + } + + 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 isEnchanted = item.getEnchantments(); + if (isEnchanted.size() > 0) { + for (Map.Entry enchantment : isEnchanted.entrySet()) { + builder.append(":e@").append(enchantment.getKey().getId()).append("@").append(enchantment.getValue()); + } + } + + if (item.hasItemMeta()) { + ItemMeta imeta = item.getItemMeta(); + if (imeta.hasDisplayName()) { + builder.append(":dn@").append(imeta.getDisplayName()); + } + + if (imeta.hasLore()) { + builder.append(":l@").append(imeta.getLore()); + } + } + + 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 s2 = itemAttribute[0]; + + switch (s2) { + case "t": + item = new ItemStack(Material.getMaterial(Integer.parseInt(itemAttribute[1]))); + meta = item.getItemMeta(); + break; + case "d": + if (item != null) { + item.setDurability(Short.parseShort(itemAttribute[1])); + break; + } + break; + case "a": + if (item != null) { + item.setAmount(Integer.parseInt(itemAttribute[1])); + break; + } + break; + case "e": + if (item != null) { + item.addUnsafeEnchantment(Enchantment.getById(Integer.parseInt(itemAttribute[1])), Integer.parseInt(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; + } + } + + if (meta != null && (meta.hasDisplayName() || meta.hasLore())) { + item.setItemMeta(meta); + } + + return item; + } + + private static int in = 0; + private static int bk = 0; + + public static String itemToBase64(ItemStack[] items) throws IllegalStateException { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream); + dataOutput.writeInt(items.length); + for (ItemStack item : items) { + dataOutput.writeObject(item); + } + dataOutput.close(); + return Base64Coder.encodeLines(outputStream.toByteArray()); + } catch (Exception e) { + throw new IllegalStateException("Unable to save item stacks.", e); + } + } + + public static ItemStack[] itemFromBase64(String data) throws IOException { + try { + ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64Coder.decodeLines(data)); + BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream); + ItemStack[] items = new ItemStack[dataInput.readInt()]; + for (int i = 0; i < items.length; i++) { + items[i] = (ItemStack) dataInput.readObject(); + } + + dataInput.close(); + return items; + } catch (ClassNotFoundException e) { + throw new IOException("Unable to decode class type.", e); + } + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/ItemBuilder.java b/Practice/src/main/java/me/devkevin/practice/util/ItemBuilder.java new file mode 100644 index 0000000..cc4006e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ItemBuilder.java @@ -0,0 +1,179 @@ +package me.devkevin.practice.util; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import org.apache.commons.codec.binary.Base64; +import org.bukkit.ChatColor; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.event.Listener; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.material.MaterialData; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class ItemBuilder implements Listener { + + private final ItemStack is; + + public ItemBuilder(final Material mat) { + is = new ItemStack(mat); + } + + public ItemBuilder(final ItemStack is) { + this.is = is; + } + + public ItemBuilder amount(final int amount) { + is.setAmount(amount); + + return this; + } + + public ItemBuilder name(final String name) { + final ItemMeta meta = is.getItemMeta(); + meta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder lore(final String name) { + final ItemMeta meta = is.getItemMeta(); + List lore = meta.getLore(); + if (lore == null) { + lore = new ArrayList<>(); + } + + lore.add(name); + meta.setLore(lore); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder lore(final 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(final int durability) { + is.setDurability((short) durability); + + return this; + } + + public ItemBuilder head(String url) { + SkullMeta headMeta = (SkullMeta) is.getItemMeta(); + GameProfile profile = new GameProfile(UUID.randomUUID(), null); + byte[] encodedData = Base64.encodeBase64(String.format("{textures:{SKIN:{url:\"%s\"}}}", url).getBytes()); + profile.getProperties().put("textures", new Property("textures", new String(encodedData))); + Field profileField; + + try { + profileField = headMeta.getClass().getDeclaredField("profile"); + profileField.setAccessible(true); + profileField.set(headMeta, profile); + } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e1) { + e1.printStackTrace(); + } + + is.setItemMeta(headMeta); + return this; + } + + public ItemBuilder owner(String owner) { + if (this.is.getType() == Material.SKULL_ITEM) { + SkullMeta meta = (SkullMeta) this.is.getItemMeta(); + meta.setOwner(owner); + this.is.setItemMeta(meta); + return this; + } + + throw new IllegalArgumentException("setOwner() only applicable for Skull Item"); + } + + @SuppressWarnings("deprecation") + public ItemBuilder data(final int data) { + is.setData(new MaterialData(is.getType(), (byte) data)); + + return this; + } + + public ItemBuilder unbreakable(boolean unbreakable) { + is.getItemMeta().spigot().setUnbreakable(unbreakable); + return this; + } + + public ItemBuilder enchantment(final Enchantment enchantment, final int level) { + is.addUnsafeEnchantment(enchantment, level); + return this; + } + + public ItemBuilder enchantment(final Enchantment enchantment) { + is.addUnsafeEnchantment(enchantment, 1); + return this; + } + + public ItemBuilder hideFlags() { + final ItemMeta meta = is.getItemMeta(); + meta.addItemFlags(ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_ATTRIBUTES); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder type(final Material material) { + is.setType(material); + return this; + } + + public ItemBuilder clearLore() { + final ItemMeta meta = is.getItemMeta(); + meta.setLore(new ArrayList<>()); + is.setItemMeta(meta); + + return this; + } + + public ItemBuilder clearEnchantments() { + for (final Enchantment e : is.getEnchantments().keySet()) { + is.removeEnchantment(e); + } + + return this; + } + + public ItemBuilder color(Color color) { + if (is.getType() == Material.LEATHER_BOOTS || is.getType() == Material.LEATHER_CHESTPLATE + || is.getType() == Material.LEATHER_HELMET || is.getType() == Material.LEATHER_LEGGINGS) { + LeatherArmorMeta meta = (LeatherArmorMeta) is.getItemMeta(); + meta.setColor(color); + is.setItemMeta(meta); + + return this; + } else { + throw new IllegalArgumentException("color() only applicable for leather armor!"); + } + } + + public ItemStack build() { + return is; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/util/ItemMaker.java b/Practice/src/main/java/me/devkevin/practice/util/ItemMaker.java new file mode 100644 index 0000000..480b249 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ItemMaker.java @@ -0,0 +1,114 @@ +package me.devkevin.practice.util; + +import club.inverted.chatcolor.CC; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.Color; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.LeatherArmorMeta; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Copyright 25/04/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ItemMaker { + + private ItemStack itemStack; + private ItemMeta itemMeta; + + private Map enchantments = new HashMap<>(); + + + public ItemMaker(Material material) { + this.itemStack = new ItemStack(material); + this.itemMeta = itemStack.getItemMeta(); + } + + public ItemMaker(ItemStack itemStack) { + this.itemStack = itemStack; + this.itemMeta = itemStack.getItemMeta(); + } + + public ItemMaker setOwner(String name) { + SkullMeta meta = (SkullMeta) itemMeta; + meta.setOwner(name); + itemMeta.setDisplayName(name); + return this; + } + + public ItemMaker setAmount(int amount) { + itemStack.setAmount(amount); + return this; + } + + public ItemMaker setDisplayName(String name) { + itemMeta.setDisplayName(CC.translate(name)); + return this; + } + + public ItemMaker setDurability(int durability) { + itemStack.setDurability((short) durability); + return this; + } + + public ItemMaker addLore(String lore) { + Object object = itemMeta.getLore(); + if (object == null) object = new ArrayList<>(); + + ((List) object).add(CC.translate(lore)); + itemMeta.setLore((List) object); + return this; + } + + public ItemMaker addLore(List lore) { + itemMeta.setLore(CC.translate(lore)); + return this; + } + + public ItemMaker addLore(String... lore) { + List strings = new ArrayList<>(); + for (String string : lore) { + strings.add(CC.translate(string)); + } + itemMeta.setLore(strings); + return this; + } + + public ItemMaker setEnchant(Enchantment enchantment, int level) { + enchantments.put(enchantment, level); + return this; + } + + public ItemMaker setUnbreakable(boolean unbreakable) { + itemMeta.spigot().setUnbreakable(unbreakable); + return this; + } + + public ItemMaker setColor(Color color) { + if (itemStack.getType() != null && itemStack.getType().name().contains("LEATHER")) { + LeatherArmorMeta armorMeta = (LeatherArmorMeta) itemMeta; + armorMeta.setColor(color); + } + return this; + } + + public ItemStack create() { + if (itemMeta != null) { + itemStack.setItemMeta(itemMeta); + } + + for (Enchantment enchantment : enchantments.keySet()) { + itemStack.addEnchantment(enchantment, enchantments.get(enchantment)); + } + + return itemStack; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ItemStackUtil.java b/Practice/src/main/java/me/devkevin/practice/util/ItemStackUtil.java new file mode 100644 index 0000000..23ac9ab --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ItemStackUtil.java @@ -0,0 +1,113 @@ +package me.devkevin.practice.util; + +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Map; + +/** + * Copyright 14/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ItemStackUtil { + + public static ItemStack createItem(Material material, String name) { + ItemStack is = new ItemStack(material); + if(material == Material.AIR) return is; + ItemMeta itemMeta = is.getItemMeta(); + itemMeta.setDisplayName(name); + is.setItemMeta(itemMeta); + return is; + } + + public static ItemStack createItem(Material material, String name, byte dur) { + ItemStack is = new ItemStack(material); + if(material == Material.AIR) return is; + ItemMeta itemMeta = is.getItemMeta(); + itemMeta.setDisplayName(name); + is.setItemMeta(itemMeta); + is.setDurability(dur); + return is; + } + + public static void removeItems(Inventory inventory, ItemStack item, int amount){ + int size = inventory.getSize(); + for (int slot = 0; slot < size; slot++){ + ItemStack is = inventory.getItem(slot); + if ((is != null) && (item.getType() == is.getType() && item.getDurability() == is.getDurability())){ + 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 createPlayerSkull(String name){ + ItemStack item = new ItemStack(Material.SKULL_ITEM, 1, (short) 3); + SkullMeta im = (SkullMeta) item.getItemMeta(); + im.setOwner(ChatColor.stripColor(name)); + im.setDisplayName(name); + item.setItemMeta(im); + return item; + } + + public static String itemToString(ItemStack is) { + if(is == null) is = new ItemStack(Material.AIR); + String enchantments = ""; + String comma = ""; + for(Map.Entry e : is.getEnchantments().entrySet()) { + enchantments += comma; + enchantments += e.getKey().getName() + "-" + e.getValue(); + comma = ";"; + } + if(enchantments != null && !enchantments.equals("")) { + return is.getType() + "/" + is.getDurability() + "/" + is.getAmount() + "/" + enchantments; + } + return is.getType() + "/" + is.getDurability() + "/" + is.getAmount(); + } + + public static ItemStack fromString(String string) { + try{ + String[] s = string.split("/"); + if(string == null || !(s.length >= 3)) { + return new ItemStack(Material.AIR); + } + ItemStack is = new ItemStack(Material.getMaterial(s[0])); + is.setDurability(Short.parseShort(s[1])); + is.setAmount(Integer.parseInt(s[2])); + if(s.length > 3) { + for(String enchantment : s[3].split(";")) { + String[] ench = enchantment.split("-"); + is.addUnsafeEnchantment(Enchantment.getByName(ench[0]), Integer.parseInt(ench[1])); + } + } + return is; + }catch(Exception e) {} + return new ItemStack(Material.AIR); + } + + public static ItemStack[] getContents(Player p) { + for(int i = 0; i < p.getInventory().getSize(); i++) { + if(p.getInventory().getItem(i) == null) { + p.getInventory().setItem(i, new ItemStack(Material.AIR)); + } + } + return p.getInventory().getContents(); + } + +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ItemUtil.java b/Practice/src/main/java/me/devkevin/practice/util/ItemUtil.java new file mode 100644 index 0000000..f41d98d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ItemUtil.java @@ -0,0 +1,173 @@ +package me.devkevin.practice.util; + +import org.bukkit.Material; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.SkullMeta; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +/** + * Copyright 10/06/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public final class ItemUtil { + + private ItemUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + public static ItemStack createItem(Material material, String name) { + ItemStack item = new ItemStack(material); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createItem(Material material, String name, int amount) { + ItemStack item = new ItemStack(material, amount); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createUnbreakableItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createNoFlagsItem(Material material, String name, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_UNBREAKABLE, ItemFlag.HIDE_ATTRIBUTES); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack createPlayerHead(Material material, String name, String playerHead, int amount, short damage) { + ItemStack item = new ItemStack(material, amount, damage); + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_ENCHANTS, ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + + if (item.getType() == Material.SKULL_ITEM) { + SkullMeta skullMeta = (SkullMeta) item.getItemMeta(); + skullMeta.setOwner(playerHead); + item.setItemMeta(skullMeta); + + return item; + } + + return item; + } + + public static ItemStack setUnbreakable(ItemStack item) { + ItemMeta meta = item.getItemMeta(); + + meta.spigot().setUnbreakable(true); + meta.addItemFlags(ItemFlag.HIDE_UNBREAKABLE); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack renameItem(ItemStack item, String name) { + ItemMeta meta = item.getItemMeta(); + + meta.setDisplayName(name); + item.setItemMeta(meta); + + return item; + } + + public static ItemStack updateAmount(ItemStack item, int amount) { + if (amount == 0) { + amount = 1; + } + item.setAmount(amount); + + return item; + } + + public static ItemStack updateLoreAndAmount(ItemStack item, int amount, String... lore) { + if (amount == 0) amount = 1; + item.setAmount(amount); + + return reloreItem(ReloreType.OVERWRITE, item, lore); + } + + public static ItemStack reloreItem(ItemStack item, String... lores) { + return reloreItem(ReloreType.OVERWRITE, item, lores); + } + + public static ItemStack reloreItem(ReloreType type, ItemStack item, String... lores) { + ItemMeta meta = item.getItemMeta(); + + List lore = meta.getLore(); + if (lore == null) { + lore = new LinkedList<>(); + } + + switch (type) { + case APPEND: + lore.addAll(Arrays.asList(lores)); + meta.setLore(lore); + break; + case PREPEND: + 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 enum ReloreType { + OVERWRITE, PREPEND, APPEND + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/MathUtil.java b/Practice/src/main/java/me/devkevin/practice/util/MathUtil.java new file mode 100644 index 0000000..a36e460 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/MathUtil.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.util; + +import org.bukkit.Location; + +import java.math.BigDecimal; + +/** + * Copyright 02/05/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class MathUtil { + + public static String convertTicksToMinutes(int ticks) { + long minute = (long) ticks / 1200L; + long second = (long) ticks / 20L - (minute * 60L); + + String secondString = Math.round(second) + ""; + + if (second < 10) { + secondString = 0 + secondString; + } + String minuteString = Math.round(minute) + ""; + + if (minute == 0) { + minuteString = 0 + ""; + } + + return minuteString + ":" + secondString; + } + + public static String convertToRomanNumeral(int number) { + switch (number) { + case 1: + return "I"; + case 2: + return "II"; + } + + return null; + } + + public static double roundToHalves(double d) { + return Math.round(d * 2.0D) / 2.0D; + } + + public static double roundInt(int numberA, int numberB, int i) { + return numberA == 0 || numberB == 0 ? 0.0 : ((double)numberA / (double)numberB + 1.0 - (double)((int)((double)numberA / (double)numberB)) == 1.0 ? (double)numberA / (double)numberB : BigDecimal.valueOf((double)numberA / (double)numberB).setScale(i, 4).doubleValue()); + } + + public static Location getMiddle(Location a, Location b){ + + double x = (a.getBlockX() + b.getBlockX()) /2; + double y = a.getBlockY(); + double z = (a.getBlockZ() + b.getBlockZ()) /2; + + return new Location(a.getWorld(), x,y,z); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/NPCUtil.java b/Practice/src/main/java/me/devkevin/practice/util/NPCUtil.java new file mode 100644 index 0000000..3cf30d3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/NPCUtil.java @@ -0,0 +1,206 @@ +package me.devkevin.practice.util; + +/** + * Copyright 17/12/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ + +import club.inverted.chatcolor.CC; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import me.devkevin.practice.Practice; +import net.minecraft.server.v1_8_R3.*; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClientBuilder; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; +import org.bukkit.craftbukkit.v1_8_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_8_R3.scoreboard.CraftScoreboard; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class NPCUtil { + + public static Practice plugin = Practice.getInstance(); + + private static final Map> entityMap = new ConcurrentHashMap<>(); + protected static final Map signatureMap = new ConcurrentHashMap<>(); + protected static final Map valueMap = new ConcurrentHashMap<>(); + + public static void create(Player player, String value, String signature, Location location) { + MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); + WorldServer world = ((CraftWorld) Bukkit.getWorlds().get(0)).getHandle(); + + UUID uuid = UUID.randomUUID(); + String name = UUID.randomUUID().toString().replace("-", "").substring(0, 14); + + EntityPlayer npc = new EntityPlayer(server, world, new GameProfile(uuid, CC.translate("&6" + player.getName())), new PlayerInteractManager(world)); + + /*for (Leaderboard leaderboard : plugin.getLeaderboardManager().getLeaderboards()) { + + Leaderboard player1Name = plugin.getLeaderboardManager().getSortedKitLeaderboards(leaderboard.getKit()).get(0); + Leaderboard player2Name = plugin.getLeaderboardManager().getSortedKitLeaderboards(leaderboard.getKit()).get(1); + Leaderboard player3Name = plugin.getLeaderboardManager().getSortedKitLeaderboards(leaderboard.getKit()).get(2); + + npc.setCustomName(CoreAPI.INSTANCE.getPlayerData(player1Name.getUuid()).getHighestRank().getColor() + player1Name.getPlayerName() + CC.translate("&7[&a" + player1Name.getPlayerElo() + "&7]")); + npc.setCustomName(CoreAPI.INSTANCE.getPlayerData(player2Name.getUuid()).getHighestRank().getColor() + player2Name.getPlayerName() + CC.translate("&7[&a" + player2Name.getPlayerElo() + "&7]")); + npc.setCustomName(CoreAPI.INSTANCE.getPlayerData(player3Name.getUuid()).getHighestRank().getColor() + player3Name.getPlayerName() + CC.translate("&7[&a" + player3Name.getPlayerElo() + "&7]")); + + npc.setCustomNameVisible(true); + }*/ + + npc.setLocation(location.getX(), location.getY(), location.getZ(), (float) location.getYaw(), (float) location.getPitch()); + npc.getProfile().getProperties().removeAll("textures"); + + DataWatcher watcher = npc.getDataWatcher(); + watcher.watch(10, (byte) 127); + + PacketPlayOutEntityMetadata metadata = new PacketPlayOutEntityMetadata(npc.getId(), watcher, true); + + npc.getProfile().getProperties().put("textures", new Property("textures", value, signature)); + + PacketPlayOutEntityHeadRotation rotation = + new PacketPlayOutEntityHeadRotation(npc, (byte) ((npc.yaw * 256.0F) / 360.0F)); + + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + + connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, npc)); + connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc)); + connection.sendPacket(rotation); + connection.sendPacket(metadata); + + ScoreboardTeam team = new ScoreboardTeam(((CraftScoreboard)player.getScoreboard()).getHandle(), name); + ChatMessage chatMessage1 = new ChatMessage(""); + ChatMessage chatMessage2 = new ChatMessage(""); + team.setPrefix(CC.translate(chatMessage1.getText())); + team.setSuffix(CC.translate(chatMessage2.getText())); + team.setNameTagVisibility(ScoreboardTeamBase.EnumNameTagVisibility.NEVER); + connection.sendPacket(new PacketPlayOutScoreboardTeam(team, 0)); + + ArrayList playerToAdd = new ArrayList<>(); + playerToAdd.add(npc.getName()); + connection.sendPacket(new PacketPlayOutScoreboardTeam(team, playerToAdd, 3)); + + EntityBat bat = new EntityBat(((CraftWorld) player.getPlayer().getWorld()).getHandle()); + + bat.setCustomName(CC.GOLD + player.getName()); + bat.setCustomNameVisible(true); + bat.setInvisible(true); + + bat.setPosition(location.getX(), location.getY(), location.getZ()); + bat.persistent = true; + + connection.sendPacket(new PacketPlayOutSpawnEntityLiving(bat)); + + bat.mount(npc); + + connection.sendPacket(new PacketPlayOutAttachEntity(0, bat, npc)); + + Bukkit.getScheduler().scheduleSyncRepeatingTask(Practice.getInstance(), new BukkitRunnable() { + @Override + public void run() { + for (Player player : Bukkit.getServer().getOnlinePlayers()) { + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + + Location location = npc.getBukkitEntity().getLocation(); + location = location.setDirection(player.getLocation().subtract(location).toVector()); + + float yaw = location.getYaw(); + float pitch = location.getPitch(); + + connection.sendPacket(new PacketPlayOutEntity.PacketPlayOutEntityLook(npc.getId(), (byte) ((yaw % 360.) * 256 / 360), (byte) ((pitch % 360.) * 256 / 360), false)); + connection.sendPacket(new PacketPlayOutEntityHeadRotation(npc, (byte) ((yaw % 360.) * 256 / 360))); + } + } + }, 1L, 1L); + + TaskUtil.runLater(() -> { + connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, npc)); + connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, ((CraftPlayer) player).getHandle())); + }, 40L); + + List entities = entityMap.getOrDefault(player.getUniqueId(), new ArrayList<>()); + + entities.add(bat); + entities.add(npc); + + entityMap.put(player.getUniqueId(), entities); + } + + public static void createOffline(String playerName, String textureValue, String textureSignature, Location location) { + GameProfile profile = new GameProfile(UUID.randomUUID(), playerName); + profile.getProperties().put("textures", new Property("textures", textureValue, textureSignature)); + + WorldServer world = ((CraftWorld) location.getWorld()).getHandle(); + EntityPlayer npc = new EntityPlayer(MinecraftServer.getServer(), world, profile, new PlayerInteractManager(world)); + npc.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + + PacketPlayOutPlayerInfo addPlayerPacket = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, npc); + PacketPlayOutNamedEntitySpawn spawnPacket = new PacketPlayOutNamedEntitySpawn(npc); + + for (Player player : Bukkit.getOnlinePlayers()) { + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + connection.sendPacket(addPlayerPacket); + connection.sendPacket(spawnPacket); + } + } + + public static void delete(Player player) { + PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; + + List map = entityMap.getOrDefault(player.getUniqueId(), new ArrayList<>()); + + for (Entity entity : map) { + PacketPlayOutEntityDestroy packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entity.getId()); + + connection.sendPacket(packetPlayOutEntityDestroy); + } + + entityMap.put(player.getUniqueId(), new ArrayList<>()); + } + + public static String[] getSkinFromMojang(UUID name) { + if (signatureMap.containsKey(name) && valueMap.containsKey(name)) { + + return new String[]{valueMap.get(name), signatureMap.get(name)}; + } + + try { + CloseableHttpClient client = HttpClientBuilder.create().build(); + + HttpGet request = new HttpGet("https://sessionserver.mojang.com/session/minecraft/profile/" + name.toString().replace("-", "") + "?unsigned=false"); + + CloseableHttpResponse response = client.execute(request); + + if (response.getStatusLine().getStatusCode() == 200) { + JsonObject object = new Gson().fromJson(new InputStreamReader(response.getEntity().getContent()), JsonObject.class); + + String value = object.get("properties").getAsJsonArray().get(0).getAsJsonObject().get("value").getAsString(); + String signature = object.get("properties").getAsJsonArray().get(0).getAsJsonObject().get("signature").getAsString(); + + return new String[]{value, signature}; + } + + } catch (IOException e) { + throw new RuntimeException(e); + } + + return null; + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/PacketUtils.java b/Practice/src/main/java/me/devkevin/practice/util/PacketUtils.java new file mode 100644 index 0000000..64a41ad --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/PacketUtils.java @@ -0,0 +1,84 @@ +package me.devkevin.practice.util; + +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.lang.reflect.Constructor; + +/** + * Copyright 19/02/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@UtilityClass +public class PacketUtils { + + public static void sendPacket(Player player, Object packet) { + try { + Object handle = player.getClass().getMethod("getHandle").invoke(player); + Object playerConnection = handle.getClass().getField("playerConnection").get(handle); + playerConnection.getClass().getMethod("sendPacket", getNMSClass("Packet")).invoke(playerConnection, packet); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public Class getNMSClass(String name) { + String version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + try { + return Class.forName("net.minecraft.server.v1_8_R3." + version + "." + name); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + return null; + } + } + + public void sendTitle(Player player, String title, String subtitle, Integer fadeIn, Integer stay, Integer fadeOut) { + try { + Object e; + Object chatTitle; + Object chatSubtitle; + Constructor subtitleConstructor; + Object titlePacket; + Object subtitlePacket; + + if (title != null) { + title = ChatColor.translateAlternateColorCodes('&', title); + title = title.replaceAll("%player%", player.getDisplayName()); + // Times packets + e = getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0].getField("TIMES").get(null); + chatTitle = getNMSClass("IChatBaseComponent").getDeclaredClasses()[0].getMethod("a", new Class[]{String.class}).invoke(null, "{\"text\":\"" + title + "\"}"); + subtitleConstructor = getNMSClass("PacketPlayOutTitle").getConstructor(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0], getNMSClass("IChatBaseComponent"), Integer.TYPE, Integer.TYPE, Integer.TYPE); + titlePacket = subtitleConstructor.newInstance(e, chatTitle, fadeIn, stay, fadeOut); + sendPacket(player, titlePacket); + + e = getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0].getField("TITLE").get(null); + chatTitle = getNMSClass("IChatBaseComponent").getDeclaredClasses()[0].getMethod("a", new Class[]{String.class}).invoke(null, "{\"text\":\"" + title + "\"}"); + subtitleConstructor = getNMSClass("PacketPlayOutTitle").getConstructor(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0], getNMSClass("IChatBaseComponent")); + titlePacket = subtitleConstructor.newInstance(e, chatTitle); + sendPacket(player, titlePacket); + } + + if (subtitle != null) { + subtitle = ChatColor.translateAlternateColorCodes('&', subtitle); + subtitle = subtitle.replaceAll("%player%", player.getDisplayName()); + // Times packets + e = getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0].getField("TIMES").get(null); + chatSubtitle = getNMSClass("IChatBaseComponent").getDeclaredClasses()[0].getMethod("a", new Class[]{String.class}).invoke(null, "{\"text\":\"" + title + "\"}"); + subtitleConstructor = getNMSClass("PacketPlayOutTitle").getConstructor(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0], getNMSClass("IChatBaseComponent"), Integer.TYPE, Integer.TYPE, Integer.TYPE); + subtitlePacket = subtitleConstructor.newInstance(e, chatSubtitle, fadeIn, stay, fadeOut); + sendPacket(player, subtitlePacket); + + e = getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0].getField("SUBTITLE").get(null); + chatSubtitle = getNMSClass("IChatBaseComponent").getDeclaredClasses()[0].getMethod("a", new Class[]{String.class}).invoke(null, "{\"text\":\"" + subtitle + "\"}"); + subtitleConstructor = getNMSClass("PacketPlayOutTitle").getConstructor(getNMSClass("PacketPlayOutTitle").getDeclaredClasses()[0], getNMSClass("IChatBaseComponent"), Integer.TYPE, Integer.TYPE, Integer.TYPE); + subtitlePacket = subtitleConstructor.newInstance(e, chatSubtitle, fadeIn, stay, fadeOut); + sendPacket(player, subtitlePacket); + } + } catch (Exception var11) { + var11.printStackTrace(); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/Pair.java b/Practice/src/main/java/me/devkevin/practice/util/Pair.java new file mode 100644 index 0000000..3f378cb --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Pair.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.util; + +/** + * Copyright 23/05/2021 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public final class Pair { + public final FIRST first; + + + public final SECOND second; + + + public Pair(FIRST first, SECOND second) { + this.first = first; + this.second = second; + } + + public int hashCode() { + return 17 * (first != null ? first.hashCode() : 0) + 17 * (second != null ? second.hashCode() : 0); + } + + + public boolean equals(Object o) { + if (!(o instanceof Pair)) { + return false; + } + + Pair that = (Pair) o; + return (equal(first, first)) && (equal(second, second)); + } + + private static boolean equal(Object a, Object b) { + return (a == b) || ((a != null) && (a.equals(b))); + } + + public String toString() { + return String.format("{%s,%s}", new Object[]{first, second}); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/PlayerUtil.java b/Practice/src/main/java/me/devkevin/practice/util/PlayerUtil.java new file mode 100644 index 0000000..3e68f8f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/PlayerUtil.java @@ -0,0 +1,330 @@ +package me.devkevin.practice.util; + +import me.devkevin.landcore.nametag.impl.InternalNametag; +import me.devkevin.practice.Practice; +import me.devkevin.practice.profile.Profile; +import net.minecraft.server.v1_8_R3.*; +import org.bukkit.Material; +import org.bukkit.*; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Firework; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.FireworkMeta; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +/** + * Copyright 10/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class PlayerUtil { + + private static Field SPAWN_PACKET_ID_FIELD; + private static Field STATUS_PACKET_ID_FIELD; + private static Field STATUS_PACKET_STATUS_FIELD; + + public static void playDeathAnimation(Player player) { + int entityId = EntityUtils.getFakeEntityId(); + PacketPlayOutNamedEntitySpawn spawnPacket = new PacketPlayOutNamedEntitySpawn(((CraftPlayer) player).getHandle()); + PacketPlayOutEntityStatus statusPacket = new PacketPlayOutEntityStatus(); + + try { + SPAWN_PACKET_ID_FIELD.set(spawnPacket, entityId); + STATUS_PACKET_ID_FIELD.set(statusPacket, entityId); + STATUS_PACKET_STATUS_FIELD.set(statusPacket, (byte) 3); + int radius = MinecraftServer.getServer().getPlayerList().d(); + Set sentTo = new HashSet<>(); + + for (Entity entity : player.getNearbyEntities(radius, radius, radius)) { + if (entity instanceof Player) { + Player watcher = (Player) entity; + if (!watcher.getUniqueId().equals(player.getUniqueId())) { + ((CraftPlayer) watcher).getHandle().playerConnection.sendPacket(spawnPacket); + ((CraftPlayer) watcher).getHandle().playerConnection.sendPacket(statusPacket); + sentTo.add(watcher); + } + } + } + + Bukkit.getScheduler().runTaskLater(Practice.getInstance(), () -> { + for (Player watcher : sentTo) { + ((CraftPlayer) watcher).getHandle().playerConnection.sendPacket(new PacketPlayOutEntityDestroy(entityId)); + } + }, 40L); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static void hideOrShowPlayer(Player player, Player target, boolean hide) { + CraftPlayer craftPlayer = (CraftPlayer) target.getPlayer(); + + if (hide) { + player.hidePlayer(target); + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, craftPlayer.getHandle())); + } else { + player.showPlayer(target); + } + } + + public final static ItemStack PLACEHOLDER_ITEM = new ItemBuilder(Material.STAINED_GLASS_PANE) + .durability(7) + .name("&a") + .lore(" ") + .hideFlags() + .build(); + + public static void setFirstSlotOfType(Player player, Material type, ItemStack itemStack) { + for (int i = 0; i < player.getInventory().getContents().length; i++) { + ItemStack item = player.getInventory().getContents()[i]; + if (item == null || item.getType() == type || item.getType() == Material.AIR) { + player.getInventory().setItem(i, itemStack); + break; + } + } + } + + public static boolean isInventoryEmpty(Inventory inv) { + ItemStack[] contents; + for (int length = (contents = inv.getContents()).length, i = 0; i < length; ++i) { + final ItemStack item = contents[i]; + if (item != null && item.getType() != Material.AIR) { + return false; + } + } + + return true; + } + + public static void lockPos(Player player, int seconds) { + player.setFlying(false); + player.setSprinting(false); + player.setWalkSpeed(0.0F); + player.setFoodLevel(0); + + player.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, 20 * seconds, 250)); + player.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, 20 * seconds, 250)); + + Bukkit.getServer().getScheduler().runTaskLater(Practice.getInstance(), () -> { + player.setFlying(false); + player.setSprinting(true); + player.setWalkSpeed(0.2F); + player.setFoodLevel(20); + }, seconds * 20L); + } + + public static void reset(Player player) { + reset(player, true); + } + + public static void reset(Player player, boolean resetHeldSlot) { + Profile profile = Practice.getInstance().getProfileManager().getProfileData(player.getUniqueId()); + + switch (profile.getState()) { + case SPAWN: + InternalNametag.reloadPlayer(player); + InternalNametag.reloadOthersFor(player); + break; + case EDITING: + Bukkit.getOnlinePlayers().forEach(p -> { + player.hidePlayer(p); + p.hidePlayer(player); + }); + break; + } + + + if (!player.hasMetadata("frozen")) { + player.setWalkSpeed(0.2F); + player.setFlySpeed(0.1F); + } + + player.setHealth(20.0D); + player.setFoodLevel(20); + player.setSaturation(12.8F); + player.setMaximumNoDamageTicks(20); + player.setFireTicks(0); + player.setFallDistance(0.0F); + player.setLevel(0); + player.setExp(0.0F); + player.setWalkSpeed(0.2F); + player.setFlySpeed(0.2F); + player.getInventory().setHeldItemSlot(0); + player.setAllowFlight(false); + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + player.spigot().setCollidesWithEntities(true); + player.closeInventory(); + player.setGameMode(GameMode.SURVIVAL); + player.getActivePotionEffects().stream().map(PotionEffect::getType).forEach(player::removePotionEffect); + ((CraftPlayer) player).getHandle().getDataWatcher().watch(9, (byte) 0); // removes players arrows on body + + if (resetHeldSlot) { + player.getInventory().setHeldItemSlot(0); + } + + player.updateInventory(); + } + + public static int getPing(Player player) { + return ((CraftPlayer)player).getHandle().ping; + } + + public static String toNiceString(String string) { + string = ChatColor.stripColor(string).replace('_', ' ').toLowerCase(); + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < string.toCharArray().length; i++) { + char c = string.toCharArray()[i]; + if (i > 0) { + char prev = string.toCharArray()[i - 1]; + if (prev == ' ' || prev == '[' || prev == '(') { + if (i == string.toCharArray().length - 1 || c != 'x' || + !Character.isDigit(string.toCharArray()[i + 1])) { + c = Character.toUpperCase(c); + } + } + } else { + if (c != 'x' || !Character.isDigit(string.toCharArray()[i + 1])) { + c = Character.toUpperCase(c); + } + } + sb.append(c); + } + + return sb.toString(); + } + + public static void sendMessage(String message, Player... players) { + for (Player player : players) { + player.sendMessage(message); + } + } + + public static void sendMessage(String message, Set players) { + for (Player player : players) { + player.sendMessage(message); + } + } + + public static void sendFirework(FireworkEffect effect, Location location) { + Firework f = location.getWorld().spawn(location, Firework.class); + FireworkMeta fm = f.getFireworkMeta(); + fm.addEffect(effect); + f.setFireworkMeta(fm); + + try { + Class entityFireworkClass = getClass("net.minecraft.server.v1_8_R3.", "EntityFireworks"); + Class craftFireworkClass = getClass("org.bukkit.craftbukkit.", "entity.CraftFirework"); + Object firework = craftFireworkClass.cast(f); + Method handle = firework.getClass().getMethod("getHandle"); + Object entityFirework = handle.invoke(firework); + Field expectedLifespan = entityFireworkClass.getDeclaredField("expectedLifespan"); + Field ticksFlown = entityFireworkClass.getDeclaredField("ticksFlown"); + ticksFlown.setAccessible(true); + ticksFlown.setInt(entityFirework, expectedLifespan.getInt(entityFirework) - 1); + ticksFlown.setAccessible(false); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + private static Class getClass(String prefix, String nmsClassString) throws ClassNotFoundException { + String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3] + "."; + String name = prefix + version + nmsClassString; + Class nmsClass = Class.forName(name); + return nmsClass; + } + + public static String getBridgesScore(int point, boolean friend) { + String icon = "⬤"; + String color = friend ? "&9" : "&c"; + String defaultString = "&7"; + + String text = icon + icon + icon + icon + icon; + switch (point) { + case 1: + text = color + icon + defaultString + icon + icon + icon + icon; + break; + case 2: + text = color + icon + icon + defaultString + icon + icon + icon; + break; + case 3: + text = color + icon + icon + icon + defaultString + icon + icon; + break; + case 4: + text = color + icon + icon + icon + icon + defaultString + icon; + break; + case 5: + text = color + text; + break; + } + + return defaultString + text; + } + + public static String getBedWarsScore(boolean bed, boolean friend) { + String alive = "&a&l✓"; + String dead = "&c&l✗"; + + String text = alive; + if (!bed) { + text = "&c" + dead; + } + + return "&a" + text; + } + + public static String getBattleRushScore(int point, boolean friend) { + String icon = "⬤"; + String color = friend ? "&9" : "&c"; + String defaultString = "&7"; + + String text = icon + icon + icon; + switch (point) { + case 1: + text = color + icon + defaultString + icon + icon; + break; + case 2: + text = color + icon + icon + defaultString + icon; + break; + case 3: + text = color + text; + break; + } + + return defaultString + text; + } + + + static { + try { + STATUS_PACKET_ID_FIELD = PacketPlayOutEntityStatus.class.getDeclaredField("a"); + STATUS_PACKET_ID_FIELD.setAccessible(true); + + STATUS_PACKET_STATUS_FIELD = PacketPlayOutEntityStatus.class.getDeclaredField("b"); + STATUS_PACKET_STATUS_FIELD.setAccessible(true); + + SPAWN_PACKET_ID_FIELD = PacketPlayOutNamedEntitySpawn.class.getDeclaredField("a"); + SPAWN_PACKET_ID_FIELD.setAccessible(true); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("deprecation") + public static UUID getUUIDByName(String name) { + OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(name); + return offlinePlayer.getUniqueId(); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ProgressBar.java b/Practice/src/main/java/me/devkevin/practice/util/ProgressBar.java new file mode 100644 index 0000000..4742f9e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ProgressBar.java @@ -0,0 +1,24 @@ +package me.devkevin.practice.util; + +import com.google.common.base.Strings; +import org.bukkit.ChatColor; + +/** + * Copyright 12/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class ProgressBar { + + public static String getBar(int current, int total) { + return ProgressBar.getProgressBar(current, total, 40, '\u258e', ChatColor.GREEN, ChatColor.GRAY); + } + + public static String getProgressBar(int current, int max, int totalBars, char symbol, ChatColor completedColor, ChatColor notCompletedColor) { + float percent = (float) current / max; + int progressBars = (int) (totalBars * percent); + + return Strings.repeat("" + completedColor + symbol, progressBars) + + Strings.repeat("" + notCompletedColor + symbol, totalBars - progressBars); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/ReflectionUtils.java b/Practice/src/main/java/me/devkevin/practice/util/ReflectionUtils.java new file mode 100644 index 0000000..c706d97 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/ReflectionUtils.java @@ -0,0 +1,25 @@ +package me.devkevin.practice.util; + +import lombok.experimental.UtilityClass; + +import java.lang.reflect.Field; + +/** + * Copyright 31/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +@UtilityClass +public class ReflectionUtils { + + public static void setField(Object obj, String field, Object value) { + try { + Field fieldObject = obj.getClass().getDeclaredField(field); + + fieldObject.setAccessible(true); + fieldObject.set(obj, value); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/TaskUtil.java b/Practice/src/main/java/me/devkevin/practice/util/TaskUtil.java new file mode 100644 index 0000000..c107ab3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TaskUtil.java @@ -0,0 +1,27 @@ +package me.devkevin.practice.util; + +import me.devkevin.practice.Practice; + +/** + * Copyright 15/08/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TaskUtil { + + public static void run(Runnable runnable) { + Practice.getInstance().getServer().getScheduler().runTask(Practice.getInstance(), runnable); + } + + public static void runTimer(Runnable runnable, long delay, long timer) { + Practice.getInstance().getServer().getScheduler().runTaskTimer(Practice.getInstance(), runnable, delay, timer); + } + + public static void runLater(Runnable runnable, long delay) { + Practice.getInstance().getServer().getScheduler().runTaskLater(Practice.getInstance(), runnable, delay); + } + + public static void runAsync(Runnable runnable) { + Practice.getInstance().getServer().getScheduler().runTaskAsynchronously(Practice.getInstance(), runnable); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/Tasks.java b/Practice/src/main/java/me/devkevin/practice/util/Tasks.java new file mode 100644 index 0000000..c535315 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/Tasks.java @@ -0,0 +1,21 @@ +package me.devkevin.practice.util; + +import me.devkevin.practice.Practice; +import org.bukkit.Bukkit; + +/** + * Copyright 19/01/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class Tasks { + + public static void runAsyncTimer(final Callable callable, final long delay, final long interval) { + Bukkit.getScheduler().runTaskTimerAsynchronously(Practice.getInstance(), callable::call, delay, interval); + } + + public interface Callable { + void call(); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/TeamUtil.java b/Practice/src/main/java/me/devkevin/practice/util/TeamUtil.java new file mode 100644 index 0000000..a4028b3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TeamUtil.java @@ -0,0 +1,42 @@ +package me.devkevin.practice.util; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.match.team.KillableTeam; +import me.devkevin.practice.tournament.team.TournamentTeam; +import org.bukkit.entity.Player; + +import java.util.UUID; + +/** + * Copyright 19/03/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TeamUtil { + + public static String getNames(KillableTeam team) { + String names = ""; + + for (int i = 0; i < team.getPlayers().size(); i++) { + UUID teammateUUID = team.getPlayers().get(i); + Player teammate = Practice.getInstance().getServer().getPlayer(teammateUUID); + String name = ""; + + if (teammate == null) { + if (team instanceof TournamentTeam) { + name = ((TournamentTeam) team).getPlayerName(teammateUUID); + } + } else { + name = teammate.getName(); + } + + int players = team.getPlayers().size(); + + if (teammate != null) { + names += name + (((players - 1) == i) ? "" : ((players - 2) == i) ? (players > 2 ? "," : "") + " & " : ", "); + } + } + + return names; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/TimeUtil.java b/Practice/src/main/java/me/devkevin/practice/util/TimeUtil.java new file mode 100644 index 0000000..4033060 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TimeUtil.java @@ -0,0 +1,53 @@ +package me.devkevin.practice.util; + +/** + * Copyright 28/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TimeUtil { + + public static String millisToTimer(long millis) { + final long seconds = millis / 1000L; + if (seconds > 3600L) { + return String.format("%02d:%02d:%02d", seconds / 3600L, seconds % 3600L / 60L, seconds % 60L); + } + return String.format("%02d:%02d", seconds / 60L, seconds % 60L); + } + + public static String convertToFormat(long delay) { + + if (delay == 0L) { + return "None"; + } + + return TimeUtil.formatTime(Math.abs((delay - System.currentTimeMillis()))); + } + + public static String formatTime(long millis) { + int sec = (int) (millis / 1000 % 60); + int min = (int) (millis / 60000 % 60); + int hr = (int) (millis / 3600000 % 24); + return ((hr > 0) ? String.format("%02d:", hr) : "") + String.format("%02d:%02d", min, sec); + } + + public static String formatIntoDetailedString(int secs) { + if (secs == 0) + return "0 seconds"; + int remainder = secs % 86400; + int days = secs / 86400; + int hours = remainder / 3600; + int minutes = remainder / 60 - hours * 60; + int seconds = remainder % 3600 - minutes * 60; + String fDays = (days > 0) ? (" " + days + " day" + ((days > 1) ? "s" : "")) : ""; + String fHours = (hours > 0) ? (" " + hours + " hour" + ((hours > 1) ? "s" : "")) : ""; + String fMinutes = (minutes > 0) ? (" " + minutes + " minute" + ((minutes > 1) ? "s" : "")) : ""; + String fSeconds = (seconds > 0) ? (" " + seconds + " second" + ((seconds > 1) ? "s" : "")) : ""; + return (fDays + fHours + fMinutes + fSeconds).trim(); + } + + public static String formatLongIntoDetailedString(long secs) { + int unconvertedSeconds = (int) secs; + return formatIntoDetailedString(unconvertedSeconds); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/TimeUtils.java b/Practice/src/main/java/me/devkevin/practice/util/TimeUtils.java new file mode 100644 index 0000000..e0a1ad3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TimeUtils.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.util; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Calendar; +import java.util.Date; +import java.util.function.Supplier; + +/** + * Copyright 03/01/2022 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public final class TimeUtils { + + private static final ThreadLocal MMSS_BUILDER = ThreadLocal.withInitial((Supplier) StringBuilder::new); + + public static String formatIntoMMSS(int secs) { + final int seconds = secs % 60; + secs -= seconds; + long minutesCount = secs / 60; + final long minutes = minutesCount % 60L; + minutesCount -= minutes; + final long hours = minutesCount / 60L; + final StringBuilder result = MMSS_BUILDER.get(); + result.setLength(0); + if (hours > 0L) { + if (hours < 10L) { + result.append("0"); + } + result.append(hours); + result.append(":"); + } + if (minutes < 10L) { + result.append("0"); + } + result.append(minutes); + result.append(":"); + if (seconds < 10) { + result.append("0"); + } + result.append(seconds); + return result.toString(); + } + + public static String nowDate() { + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm:ss"); + LocalDateTime now = LocalDateTime.now(); + return dtf.format(now); + } + + public static String dateToString(Date date) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(date); + + return calendar.getTime().toString(); + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/TimerHashMap.java b/Practice/src/main/java/me/devkevin/practice/util/TimerHashMap.java new file mode 100644 index 0000000..9fe124c --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TimerHashMap.java @@ -0,0 +1,120 @@ +package me.devkevin.practice.util; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 12/03/2023 @ 1:04 + * TimerHashMap / me.devkevin.practice.util / Practice + */ +public class TimerHashMap implements Map, TimerHashMapHandler { + + private final HashMap timestamps = new HashMap<>(); + private final HashMap store = new HashMap<>(); + private final long ttl; + + public TimerHashMap(TimeUnit ttlUnit, long ttlValue) { + this.ttl = ttlUnit.toNanos(ttlValue); + } + + @Override + public V get(Object key) { + V value = this.store.get(key); + if (value != null && this.expired(key, value)) { + this.store.remove(key); + this.timestamps.remove(key); + return null; + } + return value; + } + + private boolean expired(Object key, V value) { + return System.nanoTime() - this.timestamps.get(key) > this.ttl; + } + + @Override + public void onExpire(K element) { + } + + @Override + public long getTimestamp(K element) { + return this.timestamps.get(element); + } + + @Override + public V put(K key, V value) { + this.timestamps.put(key, System.nanoTime()); + return this.store.put(key, value); + } + + @Override + public int size() { + return this.store.size(); + } + + @Override + public boolean isEmpty() { + return this.store.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + V value = this.store.get(key); + if (value != null && this.expired(key, value)) { + this.store.remove(key); + this.timestamps.remove(key); + return false; + } + return this.store.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return this.store.containsValue(value); + } + + @Override + public V remove(Object key) { + this.timestamps.remove(key); + return this.store.remove(key); + } + + @Override + public void putAll(Map m) { + for ( Entry e : m.entrySet()) { + this.put(e.getKey(), e.getValue()); + } + } + + @Override + public void clear() { + this.timestamps.clear(); + this.store.clear(); + } + + @Override + public Set keySet() { + this.clearExpired(); + return Collections.unmodifiableSet(this.store.keySet()); + } + + @Override + public Collection values() { + this.clearExpired(); + return Collections.unmodifiableCollection(this.store.values()); + } + + @Override + public Set> entrySet() { + this.clearExpired(); + return Collections.unmodifiableSet(this.store.entrySet()); + } + + private void clearExpired() { + for (K k : this.store.keySet()) { + this.get(k); + } + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/TimerHashMapHandler.java b/Practice/src/main/java/me/devkevin/practice/util/TimerHashMapHandler.java new file mode 100644 index 0000000..7260d33 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TimerHashMapHandler.java @@ -0,0 +1,13 @@ +package me.devkevin.practice.util; + +/** + * @author DevKevin (devkevinggg@gmail.com) + * 12/03/2023 @ 1:05 + * TimerHashMapHandler / me.devkevin.practice.util / Practice + */ +public interface TimerHashMapHandler { + + public void onExpire(E var1); + + public long getTimestamp(E var1); +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/TtlHandler.java b/Practice/src/main/java/me/devkevin/practice/util/TtlHandler.java new file mode 100644 index 0000000..db97cf5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TtlHandler.java @@ -0,0 +1,12 @@ +package me.devkevin.practice.util; + +/** + * Copyright 29/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public interface TtlHandler { + + void onExpire(E p0); + long getTimestamp(E p0); +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/TtlHashMap.java b/Practice/src/main/java/me/devkevin/practice/util/TtlHashMap.java new file mode 100644 index 0000000..9668f41 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/TtlHashMap.java @@ -0,0 +1,122 @@ +package me.devkevin.practice.util; + +import java.util.*; +import java.util.concurrent.TimeUnit; + +/** + * Copyright 29/04/2020 Kevin Acaymo + * Use and or redistribution of compiled JAR file and or source code is permitted only if given + * explicit permission from original author: Kevin Acaymo + */ +public class TtlHashMap implements Map, TtlHandler { + + private final HashMap timestamps; + private final HashMap store; + private final long ttl; + + public TtlHashMap(TimeUnit ttlUnit, long ttlValue) { + this.timestamps = new HashMap<>(); + this.store = new HashMap<>(); + this.ttl = ttlUnit.toNanos(ttlValue); + } + + @Override + public V get(Object key) { + V value = this.store.get(key); + if (value != null && this.expired(key, value)) { + this.store.remove(key); + this.timestamps.remove(key); + return null; + } + return value; + } + + private boolean expired(Object key, V value) { + return System.nanoTime() - this.timestamps.get(key) > this.ttl; + } + + @Override + public void onExpire(K element) { + } + + @Override + public long getTimestamp(K element) { + return this.timestamps.get(element); + } + + @Override + public V put(K key, V value) { + this.timestamps.put(key, System.nanoTime()); + return this.store.put(key, value); + } + + @Override + public int size() { + return this.store.size(); + } + + @Override + public boolean isEmpty() { + return this.store.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + V value = this.store.get(key); + if (value != null && this.expired(key, value)) { + this.store.remove(key); + this.timestamps.remove(key); + return false; + } + return this.store.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return this.store.containsValue(value); + } + + @Override + public V remove(Object key) { + this.timestamps.remove(key); + return this.store.remove(key); + } + + @Override + public void putAll(Map m) { + for (Entry e : m.entrySet()) { + this.put(e.getKey(), e.getValue()); + } + } + + @Override + public void clear() { + this.timestamps.clear(); + this.store.clear(); + } + + @Override + public Set keySet() { + this.clearExpired(); + return Collections.unmodifiableSet(this.store.keySet()); + } + + @Override + public Collection values() { + this.clearExpired(); + return Collections.unmodifiableCollection(this.store.values()); + } + + @Override + public Set> entrySet() { + this.clearExpired(); + return Collections.unmodifiableSet(this.store.entrySet()); + } + + private void clearExpired() { + for (K k : this.store.keySet()) { + this.get(k); + } + } +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/command/BukkitCommand.java b/Practice/src/main/java/me/devkevin/practice/util/command/BukkitCommand.java new file mode 100644 index 0000000..3a0863d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/command/BukkitCommand.java @@ -0,0 +1,92 @@ +package me.devkevin.practice.util.command; + +import org.apache.commons.lang.Validate; +import org.bukkit.command.CommandException; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.plugin.Plugin; + +import java.util.List; + +/** + * Command Framework - BukkitCommand
+ * An implementation of Bukkit's Command class allowing for registering of + * commands without plugin.yml + * + * @author minnymin3 + * + */ +public class BukkitCommand extends org.bukkit.command.Command { + + private final Plugin owningPlugin; + private CommandExecutor executor; + protected BukkitCompleter completer; + + protected BukkitCommand(String label, CommandExecutor executor, Plugin owner) { + super(label); + this.executor = executor; + this.owningPlugin = owner; + this.usageMessage = ""; + } + + @Override + public boolean execute(CommandSender sender, String commandLabel, String[] args) { + boolean success = false; + + if (!owningPlugin.isEnabled()) { + return false; + } + + if (!testPermission(sender)) { + return true; + } + + try { + success = executor.onCommand(sender, this, commandLabel, args); + } catch (Throwable ex) { + throw new CommandException("Error while executing '" + commandLabel + "' in plugin " + + owningPlugin.getDescription().getFullName(), ex); + } + + if (!success && usageMessage.length() > 0) { + for (String line : usageMessage.replace("", commandLabel).split("\n")) { + sender.sendMessage(line); + } + } + + return success; + } + + @Override + public List tabComplete(CommandSender sender, String alias, String[] args) + throws CommandException, IllegalArgumentException { + Validate.notNull(sender, "The player is not valid."); + Validate.notNull(args, "Invalid arguments."); + Validate.notNull(alias, "Sub-command is not valid."); + + List completions = null; + try { + if (completer != null) { + completions = completer.onTabComplete(sender, this, alias, args); + } + if (completions == null && executor instanceof TabCompleter) { + completions = ((TabCompleter) executor).onTabComplete(sender, this, alias, args); + } + } catch (Throwable ex) { + StringBuilder message = new StringBuilder(); + message.append("Error while executing '/").append(alias).append(' '); + for (String arg : args) { + message.append(arg).append(' '); + } + message.deleteCharAt(message.length() - 1).append("' in plugin ") + .append(owningPlugin.getDescription().getFullName()); + throw new CommandException(message.toString(), ex); + } + + if (completions == null) { + return super.tabComplete(sender, alias, args); + } + return completions; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/command/BukkitCompleter.java b/Practice/src/main/java/me/devkevin/practice/util/command/BukkitCompleter.java new file mode 100644 index 0000000..cbc5793 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/command/BukkitCompleter.java @@ -0,0 +1,59 @@ +package me.devkevin.practice.util.command; + +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Command Framework - BukkitCompleter
+ * An implementation of the TabCompleter class allowing for multiple tab + * completers per command + * + * @author minnymin3 + * + */ +public class BukkitCompleter implements TabCompleter { + + private Map> completers = new HashMap>(); + + public void addCompleter(String label, Method m, Object obj) { + completers.put(label, new AbstractMap.SimpleEntry(m, obj)); + } + + @SuppressWarnings("unchecked") + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + for (int i = args.length; i >= 0; i--) { + StringBuffer buffer = new StringBuffer(); + buffer.append(label.toLowerCase()); + for (int x = 0; x < i; x++) { + if (!args[x].equals("") && !args[x].equals(" ")) { + buffer.append("." + args[x].toLowerCase()); + } + } + String cmdLabel = buffer.toString(); + if (completers.containsKey(cmdLabel)) { + Entry entry = completers.get(cmdLabel); + try { + return (List) entry.getKey().invoke(entry.getValue(), + new CommandArgs(sender, command, label, args, cmdLabel.split("\\.").length - 1)); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } + } + return null; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/command/Command.java b/Practice/src/main/java/me/devkevin/practice/util/command/Command.java new file mode 100644 index 0000000..1ea6a8d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/command/Command.java @@ -0,0 +1,33 @@ +package me.devkevin.practice.util.command; + +import me.devkevin.landcore.player.rank.Rank; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command Framework - Command
+ * The command annotation used to designate methods as commands. All methods + * should have a single CommandArgs argument + * + * @author minnymin3 + * + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Command { + + public String name(); + + public Rank permission() default Rank.MEMBER; + + public String[] aliases() default {}; + + public String description() default ""; + + public String usage() default ""; + + public boolean inGameOnly() default true; +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/command/CommandArgs.java b/Practice/src/main/java/me/devkevin/practice/util/command/CommandArgs.java new file mode 100644 index 0000000..720bd51 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/command/CommandArgs.java @@ -0,0 +1,72 @@ +package me.devkevin.practice.util.command; + +import lombok.Getter; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +/** + * Command Framework - CommandArgs
+ * This class is passed to the command methods and contains various utilities as + * well as the command info. + * + * @author minnymin3 + * + */ +@Getter +public class CommandArgs { + + private CommandSender sender; + private org.bukkit.command.Command command; + private String label; + private String[] args; + + protected CommandArgs(CommandSender sender, org.bukkit.command.Command command, String label, String[] args, + int subCommand) { + String[] modArgs = new String[args.length - subCommand]; + for (int i = 0; i < args.length - subCommand; i++) { + modArgs[i] = args[i + subCommand]; + } + + StringBuffer buffer = new StringBuffer(); + buffer.append(label); + for (int x = 0; x < subCommand; x++) { + buffer.append("." + args[x]); + } + String cmdLabel = buffer.toString(); + this.sender = sender; + this.command = command; + this.label = cmdLabel; + this.args = modArgs; + } + + public CommandSender getSender() { + return sender; + } + public org.bukkit.command.Command getCommand() { + return command; + } + public String getLabel() { + return label; + } + public String[] getArgs() { + return args; + } + public String getArgs(int index) { + return args[index]; + } + public int length() { + return args.length; + } + + public boolean isPlayer() { + return sender instanceof Player; + } + + public Player getPlayer() { + if (sender instanceof Player) { + return (Player) sender; + } else { + return null; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/command/CommandFramework.java b/Practice/src/main/java/me/devkevin/practice/util/command/CommandFramework.java new file mode 100644 index 0000000..bb91b2f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/command/CommandFramework.java @@ -0,0 +1,192 @@ +package me.devkevin.practice.util.command; + +import club.inverted.chatcolor.CC; +import me.devkevin.landcore.LandCore; +import me.devkevin.landcore.player.CoreProfile; +import me.devkevin.practice.Practice; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandMap; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; +import org.bukkit.entity.Player; +import org.bukkit.plugin.SimplePluginManager; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.AbstractMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Command Framework - BukkitCommand + * An implementation of Bukkit's Command class allowing for registering of commands without plugin.yml + * + * @author minnymin3 + */ +public class CommandFramework implements CommandExecutor { + + private final Practice plugin; + private Map> commandMap = new HashMap<>(); + private CommandMap map; + + public CommandFramework(Practice plugin) { + this.plugin = plugin; + + if (plugin.getServer().getPluginManager() instanceof SimplePluginManager) { + SimplePluginManager manager = (SimplePluginManager) plugin.getServer().getPluginManager(); + try { + Field field = SimplePluginManager.class.getDeclaredField("commandMap"); + field.setAccessible(true); + map = (CommandMap) field.get(manager); + } catch (IllegalArgumentException | SecurityException | NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + @Override + public boolean onCommand(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args) { + return handleCommand(sender, cmd, label, args); + } + + public boolean handleCommand(CommandSender sender, org.bukkit.command.Command cmd, String label, String[] args) { + for (int i = args.length; i >= 0; i--) { + StringBuffer buffer = new StringBuffer(); + buffer.append(label.toLowerCase()); + for (int x = 0; x < i; x++) { + buffer.append("." + args[x].toLowerCase()); + } + + String cmdLabel = buffer.toString(); + if (commandMap.containsKey(cmdLabel)) { + Method method = commandMap.get(cmdLabel).getKey(); + Object methodObject = commandMap.get(cmdLabel).getValue(); + Command command = method.getAnnotation(Command.class); + + + if (sender instanceof Player) { + Player player = (Player) sender; + CoreProfile coreProfile = LandCore.getInstance().getProfileManager().getProfile(player.getUniqueId()); + + if (coreProfile == null) { + return true; + } + + if (!coreProfile.hasRank(command.permission())) { + sender.sendMessage(CC.translate("&cYou don't have permissions to perform this.")); + return true; + } + } + + if (command.inGameOnly() && !(sender instanceof Player)) { + sender.sendMessage(CC.translate("&cThis command can only be executed in game.")); + return true; + } + + try { + method.invoke(methodObject, new CommandArgs(sender, cmd, label, args, cmdLabel.split("\\.").length - 1)); + } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { + e.printStackTrace(); + } + return true; + } + } + + defaultCommand(new CommandArgs(sender, cmd, label, args, 0)); + return true; + } + + public void registerCommands(Object obj, List aliases) { + for (Method method : obj.getClass().getMethods()) { + if (method.getAnnotation(Command.class) != null) { + Command command = method.getAnnotation(Command.class); + if (method.getParameterTypes().length > 1 || method.getParameterTypes()[0] != CommandArgs.class) { + System.out.println("Unable to register command " + method.getName() + ". Unexpected method arguments"); + continue; + } + + registerCommand(command, command.name(), method, obj); + for (String alias : command.aliases()) { + registerCommand(command, alias, method, obj); + } + if (aliases != null) { + for (String alias : aliases) { + registerCommand(command, alias, method, obj); + } + } + } else if (method.getAnnotation(Completer.class) != null) { + Completer comp = method.getAnnotation(Completer.class); + if (method.getParameterTypes().length > 1 || method.getParameterTypes().length == 0 || method.getParameterTypes()[0] != CommandArgs.class) { + System.out.println("Unable to register tab completer " + method.getName() + ". Unexpected method arguments"); + continue; + } + if (method.getReturnType() != List.class) { + System.out.println("Unable to register tab completer " + method.getName() + ". Unexpected return type"); + continue; + } + + registerCompleter(comp.name(), method, obj); + for (String alias : comp.aliases()) { + registerCompleter(alias, method, obj); + } + } + } + } + + public void registerCommand(Command command, String label, Method m, Object obj) { + commandMap.put(label.toLowerCase(), new AbstractMap.SimpleEntry<>(m, obj)); + commandMap.put(this.plugin.getName() + ':' + label.toLowerCase(), new AbstractMap.SimpleEntry<>(m, obj)); + + String cmdLabel = label.replace(".", ",").split(",")[0].toLowerCase(); + if (map.getCommand(cmdLabel) == null) { + org.bukkit.command.Command cmd = new BukkitCommand(cmdLabel, this, plugin); + map.register(plugin.getName(), cmd); + } + if (!command.description().equalsIgnoreCase("") && cmdLabel.equals(label)) { + map.getCommand(cmdLabel).setDescription(command.description()); + } + if (!command.usage().equalsIgnoreCase("") && cmdLabel.equals(label)) { + map.getCommand(cmdLabel).setUsage(command.usage()); + } + } + + public void registerCompleter(String label, Method m, Object obj) { + String cmdLabel = label.replace(".", ",").split(",")[0].toLowerCase(); + if (map.getCommand(cmdLabel) == null) { + org.bukkit.command.Command command = new BukkitCommand(cmdLabel, this, plugin); + map.register(plugin.getName(), command); + } + if (map.getCommand(cmdLabel) instanceof BukkitCommand) { + BukkitCommand command = (BukkitCommand) map.getCommand(cmdLabel); + if (command.completer == null) { + command.completer = new BukkitCompleter(); + } + command.completer.addCompleter(label, m, obj); + } else if (map.getCommand(cmdLabel) instanceof PluginCommand) { + try { + Object command = map.getCommand(cmdLabel); + Field field = command.getClass().getDeclaredField("completer"); + field.setAccessible(true); + if (field.get(command) == null) { + BukkitCompleter completer = new BukkitCompleter(); + completer.addCompleter(label, m, obj); + field.set(command, completer); + } else if (field.get(command) instanceof BukkitCompleter) { + BukkitCompleter completer = (BukkitCompleter) field.get(command); + completer.addCompleter(label, m, obj); + } else { + System.out.println("Unable to register tab completer " + m.getName() + ". A tab completer is already registered for that command!"); + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + + private void defaultCommand(CommandArgs args) { + args.getSender().sendMessage(args.getLabel() + " is not handled! Oh noes!"); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/command/Completer.java b/Practice/src/main/java/me/devkevin/practice/util/command/Completer.java new file mode 100644 index 0000000..af69af2 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/command/Completer.java @@ -0,0 +1,24 @@ +package me.devkevin.practice.util.command; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Command Framework - Completer
+ * The completer annotation used to designate methods as command completers. All + * methods should have a single CommandArgs argument and return a String List + * object + * + * @author minnymin3 + * + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface Completer { + + String name(); + String[] aliases() default {}; + +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/inventory/InventoryUI.java b/Practice/src/main/java/me/devkevin/practice/util/inventory/InventoryUI.java new file mode 100644 index 0000000..22c36c9 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/inventory/InventoryUI.java @@ -0,0 +1,296 @@ +package me.devkevin.practice.util.inventory; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.util.ItemUtil; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; +import org.bukkit.inventory.ItemStack; + +import java.util.LinkedList; +import java.util.List; + +@Getter +public class InventoryUI { + + @Getter private final List inventories = new LinkedList<>(); + + private final String title; + + private final int rowOffset; + private final int rows; + + @Setter private int offset; + private int page; + + public InventoryUI(String title, int rows) { + this(title, rows, 0); + } + + public InventoryUI(String title, boolean bool, int rows) { + this(title, rows, 0); + } + + public InventoryUI(String title, int rows, int rowOffset) { + this.title = title; + this.rows = rows; + this.rowOffset = rowOffset; + } + + public Inventory2D getCurrentUI() { + return this.inventories.get(page); + } + + public Inventory getCurrentPage() { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + return this.inventories.get(page).toInventory(); + } + + public ClickableItem getItem(int slot) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + return lastInventory.getItem(slot); + } + + public int getSize() { + return this.rows * 9; + } + + private void createNewInventory() { + Inventory2D inventory = new Inventory2D(this.title, this.rows, this.rowOffset); + if (this.inventories.size() > 0) { + inventory.setItem(0, this.rows - 1, new AbstractClickableItem(ItemUtil.createItem(Material.ARROW, ChatColor.AQUA + "Page #" + (this.inventories.size()))) { + @Override + public void onClick(InventoryClickEvent event) { + InventoryUI.this.page--; + try { + Inventory2D inventory2D = InventoryUI.this.inventories.get(InventoryUI.this.page); + if (inventory2D == null) { + InventoryUI.this.page++; + } else { + event.getWhoClicked().openInventory(InventoryUI.this.getCurrentPage()); + } + } catch (IndexOutOfBoundsException e) { + InventoryUI.this.page++; + } + } + }); + + if (inventory.currentY == this.rows - 1 && inventory.currentX == -1) { + inventory.currentX++; + } + } + + this.inventories.add(inventory); + } + + public void setItem(int x, int y, ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + lastInventory.setItem(x - 1, y - 1, item); + } + + public void setItem(int slot, ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + lastInventory.setItem(slot, item); + } + + public void addItem(ClickableItem item) { + if (this.inventories.size() == 0) { + this.createNewInventory(); + } + + Inventory2D lastInventory = this.inventories.get(this.inventories.size() - 1); + + if (lastInventory.currentY == this.rows - 1 && lastInventory.currentX >= 7 - this.offset) { + lastInventory.setItem(8, this.rows - 1, new AbstractClickableItem( + ItemUtil.createItem(Material.ARROW, ChatColor.RED + "Page #" + (this.inventories.size() + 1))) { + @Override + public void onClick(InventoryClickEvent event) { + InventoryUI.this.page++; + try { + Inventory2D inventory2D = InventoryUI.this.inventories.get(InventoryUI.this.page); + if (inventory2D == null) { + InventoryUI.this.page--; + } else { + event.getWhoClicked().openInventory(InventoryUI.this.getCurrentPage()); + } + } catch (IndexOutOfBoundsException e) { + InventoryUI.this.page--; + } + } + }); + this.createNewInventory(); + this.addItem(item); + } else { + lastInventory.setItem(++lastInventory.currentX + this.offset, lastInventory.currentY, item); + } + + if (lastInventory.currentX >= 8 - this.offset) { + lastInventory.currentX = this.offset - 1; + lastInventory.currentY++; + } + } + + public void removeItem(int slot) { + Inventory2D inventory2D = this.inventories.get(this.page); + this.setItem(slot, null); + for (int i = slot + 1; i < this.getSize(); i++) { + ClickableItem item = this.getItem(i); + this.setItem(i - 1, item); + this.setItem(i, null); + } + if (inventory2D.currentX >= 0) { + inventory2D.currentX--; + } else { + if (inventory2D.currentY > 0) { + inventory2D.currentY--; + inventory2D.currentX = 7; + } + } + } + + public interface ClickableItem { + + void onClick(InventoryClickEvent event); + + ItemStack getItemStack(); + + void setItemStack(ItemStack itemStack); + + ItemStack getDefaultItemStack(); + } + + @Getter @Setter + public static class EmptyClickableItem implements ClickableItem { + private final ItemStack defaultItemStack; + private ItemStack itemStack; + + public EmptyClickableItem(ItemStack itemStack) { + this.itemStack = itemStack; + this.defaultItemStack = itemStack; + } + + @Override + public void onClick(InventoryClickEvent event) { + + } + } + + @Getter @Setter + public static abstract class AbstractClickableItem implements ClickableItem { + private final ItemStack defaultItemStack; + private ItemStack itemStack; + + public AbstractClickableItem(ItemStack itemStack) { + this.itemStack = itemStack; + this.defaultItemStack = itemStack; + } + } + + @Getter + public static class InventoryUIHolder implements InventoryHolder { + private InventoryUI inventoryUI; + private String title; + private int slots; + + private InventoryUIHolder(InventoryUI inventoryUI, String title, int slots) { + this.inventoryUI = inventoryUI; + this.title = title; + this.slots = slots; + } + + @Override + public Inventory getInventory() { + return this.inventoryUI.getCurrentPage(); + } + } + + @Getter + public class Inventory2D { + private final ClickableItem[][] items; + private final String title; + private final int rows; + + private Inventory cachedInventory; + private int currentX = -1; + private int currentY; + + public Inventory2D(String title, int rows, int rowOffset) { + this.currentY = rowOffset; + this.title = title; + this.rows = rows; + this.items = new ClickableItem[9][this.rows]; + } + + public void setItem(int x, int y, ClickableItem clickableItem) { + this.items[x][y] = clickableItem; + + if (this.cachedInventory != null) { + int slot = (y * 9) + x; + + this.cachedInventory.setItem(slot, clickableItem != null ? clickableItem.getItemStack() : null); + } + } + + public void setItem(int slot, ClickableItem clickableItem) { + int y = Math.abs(slot / 9); + int x = -(y * 9 - slot); + + this.setItem(x, y, clickableItem); + } + + public ClickableItem getItem(int slot) { + int y = Math.abs(slot / 9); + int x = -(y * 9 - slot); + if (this.items.length <= x) { + return null; + } + + ClickableItem[] items = this.items[x]; + if (items.length <= y) { + return null; + } + + return items[y]; + } + + public Inventory toInventory() { + if (this.cachedInventory != null) { + return this.cachedInventory; + } + + Inventory inventory = Bukkit.getServer().createInventory(new InventoryUIHolder(InventoryUI.this, this.title, this.rows * 9), this.rows * 9, this.title); + for (int y = 0; y < this.rows; y++) { + for (int x = 0; x < 9; x++) { + int slot = y * 9 + x; + ClickableItem item = this.items[x][y]; + if (item != null) { + inventory.setItem(slot, item.getItemStack()); + } + } + } + + this.cachedInventory = inventory; + + return inventory; + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/inventory/UIListener.java b/Practice/src/main/java/me/devkevin/practice/util/inventory/UIListener.java new file mode 100644 index 0000000..60a6780 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/inventory/UIListener.java @@ -0,0 +1,36 @@ +package me.devkevin.practice.util.inventory; + +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; + +public class UIListener implements Listener { + + @EventHandler + public void onClick(InventoryClickEvent event) { + if (event.getInventory() == null) { + return; + } + if (!(event.getInventory().getHolder() instanceof InventoryUI.InventoryUIHolder)) { + return; + } + if (event.getCurrentItem() == null) { + return; + } + + InventoryUI.InventoryUIHolder inventoryUIHolder = (InventoryUI.InventoryUIHolder) event.getInventory().getHolder(); + + event.setCancelled(true); + + if (event.getClickedInventory() == null || !event.getInventory().equals(event.getClickedInventory())) { + return; + } + InventoryUI ui = inventoryUIHolder.getInventoryUI(); + InventoryUI.ClickableItem item = ui.getCurrentUI().getItem(event.getSlot()); + + if (item == null) { + return; + } + item.onClick(event); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/json/JsonChain.java b/Practice/src/main/java/me/devkevin/practice/util/json/JsonChain.java new file mode 100644 index 0000000..5132fb3 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/json/JsonChain.java @@ -0,0 +1,40 @@ +package me.devkevin.practice.util.json; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +public class JsonChain { + + private JsonObject json = new JsonObject(); + + public JsonChain addProperty(String property, String value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Number value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Boolean value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain addProperty(String property, Character value) { + this.json.addProperty(property, value); + return this; + } + + public JsonChain add(String property, JsonElement element) { + this.json.add(property, element); + return this; + } + + public JsonObject get() { + return this.json; + } + +} + diff --git a/Practice/src/main/java/me/devkevin/practice/util/json/JsonDeserializer.java b/Practice/src/main/java/me/devkevin/practice/util/json/JsonDeserializer.java new file mode 100644 index 0000000..4e1701d --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/json/JsonDeserializer.java @@ -0,0 +1,9 @@ +package me.devkevin.practice.util.json; + +import com.google.gson.JsonObject; + +public interface JsonDeserializer { + + T deserialize(JsonObject object); + +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/json/JsonSerializer.java b/Practice/src/main/java/me/devkevin/practice/util/json/JsonSerializer.java new file mode 100644 index 0000000..95deea6 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/json/JsonSerializer.java @@ -0,0 +1,9 @@ +package me.devkevin.practice.util.json; + +import com.google.gson.JsonObject; + +public interface JsonSerializer { + + JsonObject serialize(T t); + +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu.rar b/Practice/src/main/java/me/devkevin/practice/util/menu.rar new file mode 100644 index 0000000..3ecf265 Binary files /dev/null and b/Practice/src/main/java/me/devkevin/practice/util/menu.rar differ diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/Button.java b/Practice/src/main/java/me/devkevin/practice/util/menu/Button.java new file mode 100644 index 0000000..d19d7ec --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/Button.java @@ -0,0 +1,55 @@ +package me.devkevin.practice.util.menu; + +import me.devkevin.practice.Practice; +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 { + + protected final Practice plugin = Practice.getInstance(); + + 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, int slot, ClickType clickType, int hotbarButton) { + } + + public boolean shouldCancel(Player player, int slot, ClickType clickType) { + return (true); + } + + public boolean shouldUpdate(Player player, int slot, ClickType clickType) { + return (false); + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/ButtonListener.java b/Practice/src/main/java/me/devkevin/practice/util/menu/ButtonListener.java new file mode 100644 index 0000000..e12c141 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/ButtonListener.java @@ -0,0 +1,105 @@ +package me.devkevin.practice.util.menu; + +import me.devkevin.practice.Practice; +import me.devkevin.practice.util.menu.pagination.PaginatedMenu; +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.InventoryAction; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.metadata.FixedMetadataValue; + +public class ButtonListener implements Listener { + + @EventHandler(priority = EventPriority.HIGHEST) + 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.getSlot(), 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.getSlot(), event.getClick(), event.getHotbarButton()); + if (Menu.currentlyOpenedMenus.containsKey(player.getName())) { + Menu newMenu = Menu.currentlyOpenedMenus.get(player.getName()); + if (newMenu == openMenu) { + if (openMenu.isUpdateAfterClick()) { + openMenu.setClosedByMenu(true); + newMenu.openMenu(player); + } + } + } else if (button.shouldUpdate(player, event.getSlot(), event.getClick())) { + openMenu.setClosedByMenu(true); + openMenu.openMenu(player); + } + + if (event.isCancelled()) { + Bukkit.getScheduler().runTaskLater(Practice.getInstance(), player::updateInventory, 1L); + } + } else { + if ((event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT || event.getAction().equals(InventoryAction.MOVE_TO_OTHER_INVENTORY) || event.getAction().equals(InventoryAction.HOTBAR_MOVE_AND_READD) || event.getAction().equals(InventoryAction.HOTBAR_SWAP))) { + 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()); + if (openMenu instanceof PaginatedMenu) { + return; + } + } + + player.setMetadata("scanglitch", new FixedMetadataValue(Practice.getInstance(), true)); + } + + @EventHandler + public void onPlayerMove(PlayerMoveEvent event) { + Player player = event.getPlayer(); + if (player.hasMetadata("scanglitch")) { + player.removeMetadata("scanglitch", Practice.getInstance()); + for (ItemStack it : player.getInventory().getContents()) { + if (it != null) { + ItemMeta meta = it.getItemMeta(); + if (meta != null && meta.hasDisplayName()) { + if (meta.getDisplayName().contains("§b§c§d§e")) { + player.getInventory().remove(it); + } + } + } + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/Menu.java b/Practice/src/main/java/me/devkevin/practice/util/menu/Menu.java new file mode 100644 index 0000000..701ba7e --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/Menu.java @@ -0,0 +1,205 @@ +package me.devkevin.practice.util.menu; + +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.Practice; +import org.bukkit.Bukkit; +import org.bukkit.Material; +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 { + + protected final Practice plugin = Practice.getInstance(); + + public static Map currentlyOpenedMenus = new HashMap<>(); + @Getter private Map buttons = new HashMap<>(); + private boolean autoUpdate = false; + private boolean updateAfterClick = true; + private boolean closedByMenu = false; + private boolean placeholder = false; + private Button placeholderButton = 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) { + ItemMeta meta = item.getItemMeta(); + + if (meta != null && meta.hasDisplayName()) { + meta.setDisplayName(meta.getDisplayName()); + } + + 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 = 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); + player.closeInventory(); + } + } + } + + 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 void openMenu(Player player) { + this.buttons = this.getButtons(player); + Menu previousMenu = Menu.currentlyOpenedMenus.get(player.getName()); + + Inventory inventory = null; + int size = 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) { + int previousSize = player.getOpenInventory().getTopInventory().getSize(); + if (previousSize == size && player.getOpenInventory().getTopInventory().getTitle().equals(title)) { + inventory = player.getOpenInventory().getTopInventory(); + update = true; + } else { + previousMenu.onClose(player); + } + } + } + + if (inventory == null) { + inventory = Bukkit.createInventory(player, size, title); + } + + inventory.setContents(new ItemStack[inventory.getSize()]); + for (Map.Entry buttonEntry : this.buttons.entrySet()) { + inventory.setItem(buttonEntry.getKey(), this.createItemStack(player, buttonEntry.getValue())); + } + + if (update) { + player.updateInventory(); + } else { + player.openInventory(inventory); + } + + this.onOpen(player); + }*/ + + 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 void updateInventory(Player player) { + Inventory inventory = player.getOpenInventory().getTopInventory(); + inventory.setContents(new ItemStack[inventory.getSize()]); + + currentlyOpenedMenus.put(player.getName(), this); + + for (Map.Entry buttonEntry : getButtons(player).entrySet()) { + inventory.setItem(buttonEntry.getKey(), createItemStack(player, buttonEntry.getValue())); + } + player.updateInventory(); + } + + public int getSlot(int x, int y) { + return ((9 * y) + x); + } + + public int getSize() { + return -1; + } + + public abstract String getTitle(Player player); + + public abstract Map getButtons(Player player); + + public void onOpen(Player player) { + currentlyOpenedMenus.put(player.getName(), this); + } + + public void onClose(Player player) { + } + + public void fillEmptySlots(Map buttons, ItemStack itemStack) { + int bound = getSize(); + + for (int slot = 0; slot < bound; slot++) { + if (buttons.get(slot) == null) { + buttons.put(slot, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return itemStack; + } + }); + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/MenuListener.java b/Practice/src/main/java/me/devkevin/practice/util/menu/MenuListener.java new file mode 100644 index 0000000..d4b2870 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/MenuListener.java @@ -0,0 +1,74 @@ +package me.devkevin.practice.util.menu; + +import me.devkevin.practice.Practice; +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; + +/** + * Created by Elb1to + * Project: Frost + * Date: 6/9/2021 @ 10:12 PM + */ +public class MenuListener implements Listener { + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + public void onButtonPress(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + Menu openInventory = Menu.currentlyOpenedMenus.get(player.getName()); + + if (openInventory != null) { + if (event.getSlot() != event.getRawSlot()) { + if (event.getClick() == ClickType.SHIFT_LEFT || event.getClick() == ClickType.SHIFT_RIGHT) { + event.setCancelled(true); + } + + return; + } + + if (openInventory.getButtons().containsKey(event.getSlot())) { + Button button = openInventory.getButtons().get(event.getSlot()); + boolean cancel = button.shouldCancel(player, event.getSlot(), 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.getSlot(), event.getClick(), event.getHotbarButton()); + if (Menu.currentlyOpenedMenus.containsKey(player.getName())) { + Menu newInventory = Menu.currentlyOpenedMenus.get(player.getName()); + if (newInventory == openInventory) { + boolean buttonUpdate = button.shouldUpdate(player, event.getSlot(), event.getClick()); + if (buttonUpdate) { + openInventory.setClosedByMenu(true); + newInventory.openMenu(player); + } + } + } else if (button.shouldUpdate(player, event.getSlot(), event.getClick())) { + openInventory.setClosedByMenu(true); + openInventory.openMenu(player); + } + + if (event.isCancelled()) { + Bukkit.getScheduler().runTaskLater(Practice.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); + } + } + } + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/MenuUpdateTask.java b/Practice/src/main/java/me/devkevin/practice/util/menu/MenuUpdateTask.java new file mode 100644 index 0000000..c659637 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/MenuUpdateTask.java @@ -0,0 +1,19 @@ +package me.devkevin.practice.util.menu; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class MenuUpdateTask implements Runnable { + + @Override + public void run() { + Menu.currentlyOpenedMenus.forEach((key, value) -> { + final Player player = Bukkit.getPlayer(key); + if (player != null) { + if (value.isAutoUpdate()) { + value.openMenu(player); + } + } + }); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/buttons/BackButton.java b/Practice/src/main/java/me/devkevin/practice/util/menu/buttons/BackButton.java new file mode 100644 index 0000000..dc61a60 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/buttons/BackButton.java @@ -0,0 +1,35 @@ +package me.devkevin.practice.util.menu.buttons; + +import lombok.AllArgsConstructor; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +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; + +@AllArgsConstructor +public class BackButton extends Button { + + private Menu back; + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack itemStack = new ItemStack(Material.BED); + ItemMeta itemMeta = itemStack.getItemMeta(); + + itemMeta.setDisplayName(ChatColor.RED + "Go back"); + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + Button.playNeutral(player); + + this.back.openMenu(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/buttons/DisplayButton.java b/Practice/src/main/java/me/devkevin/practice/util/menu/buttons/DisplayButton.java new file mode 100644 index 0000000..d63b4b7 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/buttons/DisplayButton.java @@ -0,0 +1,31 @@ +package me.devkevin.practice.util.menu.buttons; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.Setter; +import me.devkevin.practice.util.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, int slot, ClickType clickType) { + return this.cancel; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/JumpToPageButton.java b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/JumpToPageButton.java new file mode 100644 index 0000000..707c0e5 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/JumpToPageButton.java @@ -0,0 +1,45 @@ +package me.devkevin.practice.util.menu.pagination; + +import lombok.AllArgsConstructor; +import me.devkevin.practice.util.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.GREEN + "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, int i, ClickType clickType, int hb) { + this.menu.modPage(player, this.page - this.menu.getPage()); + Button.playNeutral(player); + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/PageButton.java b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/PageButton.java new file mode 100644 index 0000000..0842429 --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/PageButton.java @@ -0,0 +1,61 @@ +package me.devkevin.practice.util.menu.pagination; + +import lombok.AllArgsConstructor; +import me.devkevin.practice.util.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 PageButton extends Button { + + private int mod; + private PaginatedMenu menu; + + @Override + public ItemStack getButtonItem(Player player) { + ItemStack itemStack = new ItemStack(Material.CARPET); + ItemMeta itemMeta = itemStack.getItemMeta(); + + if (this.hasNext(player)) { + itemMeta.setDisplayName(this.mod > 0 ? ChatColor.GREEN + "Next page" : ChatColor.RED + "Previous page"); + } else { + itemMeta.setDisplayName(ChatColor.GRAY + (this.mod > 0 ? "Last page" : "First page")); + } + + itemMeta.setLore(Arrays.asList( + "", + ChatColor.GREEN + "Right click to", + ChatColor.GREEN + "jump to a page" + )); + + itemStack.setItemMeta(itemMeta); + + return itemStack; + } + + @Override + public void clicked(Player player, int i, ClickType clickType, int hb) { + if (clickType == ClickType.RIGHT) { + new ViewAllPagesMenu(this.menu).openMenu(player); + playNeutral(player); + } else { + if (hasNext(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 pg > 0 && this.menu.getPages(player) >= pg; + } +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/PaginatedMenu.java b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/PaginatedMenu.java new file mode 100644 index 0000000..a6ec88f --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/PaginatedMenu.java @@ -0,0 +1,118 @@ +package me.devkevin.practice.util.menu.pagination; + +import lombok.Getter; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; +import java.util.stream.IntStream; + +public abstract class PaginatedMenu extends Menu { + + @Getter private int page = 1; + + { + setUpdateAfterClick(false); + } + + @Override + public String getTitle(Player player) { + return getPrePaginatedTitle(player) + " - " + page + "/" + getPages(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)); + + HashMap buttons = new HashMap<>(); + + buttons.put(0, new PageButton(-1, this)); + buttons.put(8, new PageButton(1, this)); + + 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()); + } + } + + 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 buttons that returns items which will be present on all pages + */ + public Map getGlobalButtons(Player player) { + return null; + } + + protected void bottomTopButtons(boolean full, Map buttons, ItemStack itemStack) { + IntStream.range(0, getSize()).filter(slot -> buttons.get(slot) == null).forEach(slot -> { + if (slot < 9 || slot > getSize() - 10 || full && (slot % 9 == 0 || (slot + 1) % 9 == 0)) { + buttons.put(slot, new Button() { + @Override + public ItemStack getButtonItem(Player player) { + return itemStack; + } + }); + } + }); + } + + /** + * @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 buttons that will be paginated and spread across pages + */ + public abstract Map getAllPagesButtons(Player player); +} diff --git a/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/ViewAllPagesMenu.java b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/ViewAllPagesMenu.java new file mode 100644 index 0000000..671f11a --- /dev/null +++ b/Practice/src/main/java/me/devkevin/practice/util/menu/pagination/ViewAllPagesMenu.java @@ -0,0 +1,46 @@ +package me.devkevin.practice.util.menu.pagination; + +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import me.devkevin.practice.util.menu.Button; +import me.devkevin.practice.util.menu.Menu; +import me.devkevin.practice.util.menu.buttons.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/Practice/src/main/resources/arenas.yml b/Practice/src/main/resources/arenas.yml new file mode 100644 index 0000000..dc815d4 --- /dev/null +++ b/Practice/src/main/resources/arenas.yml @@ -0,0 +1,283 @@ +arenas: + Fruit: + icon: STAINED_CLAY + icon-data: 4 + a: 13993.56925287581, 77.0, 1002.8598639286706, 0.8022766, -0.27107227 + b: 13993.543665620347, 77.0, 1012.2661663567684, 180.09406, -0.13225307 + min: 13971.485578375894, 69.0, 1039.6635567841945, 343.85983, 60.273026 + max: 14015.566043032288, 100.0, 984.4902973420366, 44.718704, 1.3887854 + build-max: 0 + dead-zone: 67 + portalProt: 0 + enabled: true + Snow: + icon: SNOW_BLOCK + icon-data: 0 + a: 16000.467308364958, 100.0, 1006.2122934040414, 181.65474, 1.5271193 + b: 16000.48169153912, 100.0, 996.7169603753629, 0.5572176, -3.1947443 + min: 16042.506842136312, 90.0, 957.3141324974871, 37.22205, 45.13484 + max: 16051.413190542547, 161.0, 1057.4124575332019, 137.3517, 48.606697 + build-max: 0 + dead-zone: 92 + portalProt: 0 + enabled: true + Flags: + icon: WOOL + icon-data: 14 + a: 19066.562116470737, 168.0, 1082.4276088394163, -87.688965, 7.645244 + b: 19102.60006308129, 168.0, 1082.5215928104817, -269.50293, 6.2564664 + min: 19006.5, 91.00099999523162, 1115.5, 236.61551, -40.12881 + max: 19147.5, 213.00099999523164, 1057.5, 62.73755, 32.64334 + build-max: 180 + dead-zone: 160 + portalProt: 0 + enabled: false + standaloneArenas: + '0': + a: 29066.562116470737, 168.0, 11082.427608839416, -87.688965, 7.645244 + b: 29102.60006308129, 168.0, 11082.52159281048, -269.50293, 6.2564664 + min: 29006.5, 91.00099999523162, 11115.5, 236.61551, -40.12881 + max: 29147.5, 213.00099999523164, 11057.5, 62.73755, 32.64334 + '1': + a: 48214.56211647074, 168.0, 12140.427608839416, -87.688965, 7.645244 + b: 48250.60006308129, 168.0, 12140.52159281048, -269.50293, 6.2564664 + min: 48154.5, 91.00099999523162, 12173.5, 236.61551, -40.12881 + max: 48295.5, 213.00099999523164, 12115.5, 62.73755, 32.64334 + '2': + a: 67362.56211647074, 168.0, 13198.427608839416, -87.688965, 7.645244 + b: 67398.60006308129, 168.0, 13198.52159281048, -269.50293, 6.2564664 + min: 67302.5, 91.00099999523162, 13231.5, 236.61551, -40.12881 + max: 67443.5, 213.00099999523164, 13173.5, 62.73755, 32.64334 + '3': + a: 86510.56211647074, 168.0, 14256.427608839416, -87.688965, 7.645244 + b: 86546.60006308129, 168.0, 14256.52159281048, -269.50293, 6.2564664 + min: 86450.5, 91.00099999523162, 14289.5, 236.61551, -40.12881 + max: 86591.5, 213.00099999523164, 14231.5, 62.73755, 32.64334 + '4': + a: 105658.56211647074, 168.0, 15314.427608839416, -87.688965, 7.645244 + b: 105694.60006308129, 168.0, 15314.52159281048, -269.50293, 6.2564664 + min: 105598.5, 91.00099999523162, 15347.5, 236.61551, -40.12881 + max: 105739.5, 213.00099999523164, 15289.5, 62.73755, 32.64334 + '5': + a: 124806.56211647074, 168.0, 16372.427608839416, -87.688965, 7.645244 + b: 124842.60006308129, 168.0, 16372.52159281048, -269.50293, 6.2564664 + min: 124746.5, 91.00099999523162, 16405.5, 236.61551, -40.12881 + max: 124887.5, 213.00099999523164, 16347.5, 62.73755, 32.64334 + '6': + a: 143954.56211647074, 168.0, 17430.427608839418, -87.688965, 7.645244 + b: 143990.60006308128, 168.0, 17430.52159281048, -269.50293, 6.2564664 + min: 143894.5, 91.00099999523162, 17463.5, 236.61551, -40.12881 + max: 144035.5, 213.00099999523164, 17405.5, 62.73755, 32.64334 + '7': + a: 163102.56211647074, 168.0, 18488.427608839418, -87.688965, 7.645244 + b: 163138.60006308128, 168.0, 18488.52159281048, -269.50293, 6.2564664 + min: 163042.5, 91.00099999523162, 18521.5, 236.61551, -40.12881 + max: 163183.5, 213.00099999523164, 18463.5, 62.73755, 32.64334 + '8': + a: 182250.56211647074, 168.0, 19546.427608839418, -87.688965, 7.645244 + b: 182286.60006308128, 168.0, 19546.52159281048, -269.50293, 6.2564664 + min: 182190.5, 91.00099999523162, 19579.5, 236.61551, -40.12881 + max: 182331.5, 213.00099999523164, 19521.5, 62.73755, 32.64334 + '9': + a: 201398.56211647074, 168.0, 20604.427608839418, -87.688965, 7.645244 + b: 201434.60006308128, 168.0, 20604.52159281048, -269.50293, 6.2564664 + min: 201338.5, 91.00099999523162, 20637.5, 236.61551, -40.12881 + max: 201479.5, 213.00099999523164, 20579.5, 62.73755, 32.64334 + '10': + a: 220546.56211647074, 168.0, 21662.427608839418, -87.688965, 7.645244 + b: 220582.60006308128, 168.0, 21662.52159281048, -269.50293, 6.2564664 + min: 220486.5, 91.00099999523162, 21695.5, 236.61551, -40.12881 + max: 220627.5, 213.00099999523164, 21637.5, 62.73755, 32.64334 + '11': + a: 239694.56211647074, 168.0, 22720.427608839418, -87.688965, 7.645244 + b: 239730.60006308128, 168.0, 22720.52159281048, -269.50293, 6.2564664 + min: 239634.5, 91.00099999523162, 22753.5, 236.61551, -40.12881 + max: 239775.5, 213.00099999523164, 22695.5, 62.73755, 32.64334 + '12': + a: 258842.56211647074, 168.0, 23778.427608839418, -87.688965, 7.645244 + b: 258878.60006308128, 168.0, 23778.52159281048, -269.50293, 6.2564664 + min: 258782.5, 91.00099999523162, 23811.5, 236.61551, -40.12881 + max: 258923.5, 213.00099999523164, 23753.5, 62.73755, 32.64334 + '13': + a: 277990.5621164707, 168.0, 24836.427608839418, -87.688965, 7.645244 + b: 278026.6000630813, 168.0, 24836.52159281048, -269.50293, 6.2564664 + min: 277930.5, 91.00099999523162, 24869.5, 236.61551, -40.12881 + max: 278071.5, 213.00099999523164, 24811.5, 62.73755, 32.64334 + '14': + a: 297138.5621164707, 168.0, 25894.427608839418, -87.688965, 7.645244 + b: 297174.6000630813, 168.0, 25894.52159281048, -269.50293, 6.2564664 + min: 297078.5, 91.00099999523162, 25927.5, 236.61551, -40.12881 + max: 297219.5, 213.00099999523164, 25869.5, 62.73755, 32.64334 + Spotify: + icon: WOOL + icon-data: 5 + a: 22115.40718319644, 109.0, 923.7759888757345, 0.2563175, -6.798522 + b: 22115.57390542501, 109.0, 1041.12445380757, 179.82605, -9.576192 + min: 22052.332368818734, 104.0, 1053.7236759181312, 219.43248, 58.61325 + max: 22172.611982717757, 210.0, 919.210185494591, 42.614227, 73.75092 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Mario: + icon: STAINED_CLAY + icon-data: 13 + a: 15001.500115323659, 100.0, 995.5884605774947, 359.00156, -1.8054876 + b: 15001.422276037185, 100.0, 1005.5591621393046, 180.65588, 1.8124976 + min: 15031.534489222116, 82.0, 952.299272766365, 29.976685, 2.090129 + max: 14953.5, 163.00099999523164, 1058.5, 224.01006, 35.00436 + build-max: 0 + dead-zone: 83 + portalProt: 0 + enabled: true + MarioBros: + icon: WOOL + icon-data: 14 + a: 11986.481841337672, 112.0, 1079.3199795430326, 180.68317, -5.47922 + b: 11986.435509078288, 112.0, 961.6470391553454, 0.3919983, -7.145761 + min: 11924.65708955614, 107.0, 952.0277239432368, 317.06705, 6.79806 + max: 12043.376087422193, 213.0, 1085.3312769191114, 315.11972, 68.59887 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Pepe: + icon: WOOL + icon-data: 13 + a: 21059.452026503157, 131.0, 925.7261962956578, 359.8327, -7.6314063 + b: 21059.530188031636, 131.0, 1043.2533796201337, 180.37396, -7.075925 + min: 21122.203025450246, 126.0, 915.7248735532214, 41.083313, -4.0204725 + max: 21002.342611982054, 205.0, 1049.5030949886657, 222.48347, 89.30572 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Apple: + icon: WOOL + icon-data: 15 + a: 8971.440471675896, 117.0, 764.7994071569353, 0.20355225, -8.186898 + b: 8971.5318738981, 117.0, 882.3815833383086, 179.93918, -8.74249 + min: 9033.85493064858, 112.0, 893.752067739367, 132.58282, -0.54887325 + max: 8913.436589248062, 190.0, 759.4504124444001, 328.81506, 28.337883 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Winter: + icon: SNOW_BLOCK + icon-data: 0 + a: 10002.546502519843, 100.0, 920.3900654852531, 180.67973, -2.423632 + b: 10002.455384307032, 100.0, 859.651612277709, -0.14024962, -2.8403184 + min: 10036.57039557963, 100.0, 830.5172879832027, 5.6621704, -4.8678646 + max: 9967.267865129243, 175.0, 924.9183556440516, 223.59195, 65.54349 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Hills: + icon: STAINED_CLAY + icon-data: 5 + a: 6093.449730232747, 129.0, 1082.4237578106013, 180.69, -3.7430534 + b: 6093.5323069242495, 129.0, 999.4827651130001, 0.2869873, -3.7431006 + min: 6036.5, 124.00099999523162, 1101.5, 198.0614, -23.616278 + max: 6138.54229628501, 178.0, 997.3646122136986, 19.039825, 63.877037 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Overwatch: + icon: WOOL + icon-data: 11 + a: 10882.510129812677, 113.0, 995.2866489715417, 180.30206, -5.409549 + b: 10882.465580053398, 113.0, 905.8281544896956, 0.5924072, -6.798321 + min: 10834.399823399635, 113.0, 1000.3000000119209, 177.53033, 50.82234 + max: 10929.548583697624, 178.0, 901.4518126394219, 29.479706, 67.21005 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Build_1: + icon: CACTUS + icon-data: 0 + a: 17000.453664898403, 101.0, 947.5490779901662, 0.13868101, -1.527684 + b: 16996.10492935065, 102.0, 1049.0188404890514, 183.59636, -1.1109011 + min: 17039.579550377606, 95.0, 939.6999999880791, 14.005066, 49.294865 + max: 16961.351556788093, 147.0, 1056.5503808176527, 197.7627, 58.73857 + build-max: 122 + dead-zone: 0 + portalProt: 0 + enabled: true + standaloneArenas: + '0': + a: 27000.453664898403, 101.0, 10947.549077990167, 0.13868101, -1.527684 + b: 26996.10492935065, 102.0, 11049.01884048905, 183.59636, -1.1109011 + min: 27039.579550377606, 95.0, 10939.699999988079, 14.005066, 49.294865 + max: 26961.351556788093, 147.0, 11056.550380817653, 197.7627, 58.73857 + '1': + a: 43961.45366489841, 101.0, 12004.549077990167, 0.13868101, -1.527684 + b: 43957.10492935065, 102.0, 12106.01884048905, 183.59636, -1.1109011 + min: 44000.5795503776, 95.0, 11996.699999988079, 14.005066, 49.294865 + max: 43922.3515567881, 147.0, 12113.550380817653, 197.7627, 58.73857 + '2': + a: 60922.45366489841, 101.0, 13061.549077990167, 0.13868101, -1.527684 + b: 60918.10492935065, 102.0, 13163.01884048905, 183.59636, -1.1109011 + min: 60961.5795503776, 95.0, 13053.699999988079, 14.005066, 49.294865 + max: 60883.3515567881, 147.0, 13170.550380817653, 197.7627, 58.73857 + '3': + a: 77883.4536648984, 101.0, 14118.549077990167, 0.13868101, -1.527684 + b: 77879.10492935065, 102.0, 14220.01884048905, 183.59636, -1.1109011 + min: 77922.5795503776, 95.0, 14110.699999988079, 14.005066, 49.294865 + max: 77844.3515567881, 147.0, 14227.550380817653, 197.7627, 58.73857 + '4': + a: 94844.4536648984, 101.0, 15175.549077990167, 0.13868101, -1.527684 + b: 94840.10492935065, 102.0, 15277.01884048905, 183.59636, -1.1109011 + min: 94883.5795503776, 95.0, 15167.699999988079, 14.005066, 49.294865 + max: 94805.3515567881, 147.0, 15284.550380817653, 197.7627, 58.73857 + Build_2: + icon: GRASS + icon-data: 0 + a: 17994.365682695505, 102.0, 1045.1897517012808, 181.65347, 0.6943345 + b: 18001.905486768388, 101.0, 946.2265643191207, 1.9195557, -3.3332129 + min: 17960.412750812186, 95.0, 1055.300000011921, 186.76599, 44.156284 + max: 18038.68728533059, 147.0, 938.6464255381953, 36.361725, 52.76673 + build-max: 115 + dead-zone: 0 + portalProt: 0 + enabled: true + standaloneArenas: + '0': + a: 27994.365682695505, 102.0, 11045.18975170128, 181.65347, 0.6943345 + b: 28001.905486768388, 101.0, 10946.22656431912, 1.9195557, -3.3332129 + min: 27960.412750812186, 95.0, 11055.300000011921, 186.76599, 44.156284 + max: 28038.68728533059, 147.0, 10938.646425538196, 36.361725, 52.76673 + '1': + a: 46033.365682695505, 102.0, 11984.18975170128, 181.65347, 0.6943345 + b: 46040.90548676839, 101.0, 11885.22656431912, 1.9195557, -3.3332129 + min: 45999.41275081219, 95.0, 11994.300000011921, 186.76599, 44.156284 + max: 46077.68728533059, 147.0, 11877.646425538196, 36.361725, 52.76673 + '2': + a: 64072.365682695505, 102.0, 12923.18975170128, 181.65347, 0.6943345 + b: 64079.90548676839, 101.0, 12824.22656431912, 1.9195557, -3.3332129 + min: 64038.41275081219, 95.0, 12933.300000011921, 186.76599, 44.156284 + max: 64116.68728533059, 147.0, 12816.646425538196, 36.361725, 52.76673 + '3': + a: 82111.3656826955, 102.0, 13862.18975170128, 181.65347, 0.6943345 + b: 82118.90548676839, 101.0, 13763.22656431912, 1.9195557, -3.3332129 + min: 82077.41275081219, 95.0, 13872.300000011921, 186.76599, 44.156284 + max: 82155.68728533058, 147.0, 13755.646425538196, 36.361725, 52.76673 + '4': + a: 100150.3656826955, 102.0, 14801.18975170128, 181.65347, 0.6943345 + b: 100157.90548676839, 101.0, 14702.22656431912, 1.9195557, -3.3332129 + min: 100116.41275081219, 95.0, 14811.300000011921, 186.76599, 44.156284 + max: 100194.68728533058, 147.0, 14694.646425538196, 36.361725, 52.76673 + Valorant: + icon: WOOL + icon-data: 14 + a: 4635.523942635199, 128.0, 1061.6183836999944, 0.651886, -5.687129 + b: 4635.554576107276, 128.0, 1141.4896910692794, 180.38774, -4.0206213 + min: 4678.446700265333, 127.0, 1056.6161121884388, 4.958557, 40.128674 + max: 4592.553027944798, 186.0, 1144.6864615319726, 220.38509, 78.45915 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true diff --git a/Practice/src/main/resources/config.yml b/Practice/src/main/resources/config.yml new file mode 100644 index 0000000..f527319 --- /dev/null +++ b/Practice/src/main/resources/config.yml @@ -0,0 +1,48 @@ +DATABASE: + MONGO: + DATABASE: "Practice" + HOST: "127.0.0.1" + PORT: 27017 + AUTHENTICATION: + ENABLED: FALSE + DATABASE: "admin" + USER: "user" + PASSWORD: "password" + +region: "REGION" + +LEADERBOARDS: + UPDATE-TIME: 15 # The time is calculated in minutes + UPDATE-MESSAGE: "&8[&b&lPractice&8] &7&oUpdating leaderboards! This could cause minor lag..." + +PLACEHOLDER-API: + PLAYER-KIT-ELO-FORMAT: "&b &f&8. &7(&f&7)" + +HOLOGRAM: + UPDATE-TIME: 20 # Seconds + FORMAT: + FORMAT: "&b. &f: &b" + LINES: + - "&b&lPractice Leaderboards" + - "&7" + - "&b " + - "&7" + - "" + WINSTREAK: + FORMAT: "&b. &f: &b" + LINES: + - "&b&lPractice Winstreak Leaderboards" + - "&7" + - "&b " + - "&7" + - "" + +NPC: + UPDATE-TIME: 20 # Seconds + FORMAT: + FORMAT: '&6# &f &7» &f &7» ' + LINES: + - "&a◉ ◉" + - "" + - "&7" + - "&fNext update in &6" \ No newline at end of file diff --git a/Practice/src/main/resources/ladders.yml b/Practice/src/main/resources/ladders.yml new file mode 100644 index 0000000..6ebf12f --- /dev/null +++ b/Practice/src/main/resources/ladders.yml @@ -0,0 +1,3307 @@ +ladders: + Gapple: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + damage: 1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + damage: 1 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Gapple + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oGawdApple§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oAgentAsh_§7 - §61000 + - '' + - §eClick here to play §6Gapple§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + NoDebuff: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: COOKED_FISH + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GRILLED_PORK + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + meta: + ==: ItemMeta + meta-type: POTION + display-name: §6NoDebuff + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oLeaan§7 - §61000 + - §72. §e§oAgentAsh_§7 - §61000 + - §73. §e§oAlleComboZ§7 - §61000 + - '' + - §eClick here to play §6NoDebuff§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Bat + - Christmas + - RedSand + - SnowTree + - HolyGarden + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Sumo: + contents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: STICK + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Sumo + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oBruhMonkeyJayy§7 - §61000 + - §72. §e§oAlleComboZ§7 - §61000 + - §73. §e§oAlexCanaryYT§7 - §61000 + - '' + - §eClick here to play §6Sumo§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Mario + - Fruit + - Snow + enabled: true + ranked: true + sumo: true + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Archer: + contents: + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 1 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: WOOD_PICKAXE + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 12 + - null + - null + - null + - null + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16454 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_BOOTS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_LEGGINGS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_CHESTPLATE + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_HELMET + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Archer + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oDe_el_pler§7 - §61000 + - §72. §e§oAgentAsh_§7 - §61000 + - §73. §e§oAlleComboZ§7 - §61000 + - '' + - §eClick here to play §6Archer§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Boxing: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + repair-cost: 8 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Boxing + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oAlleComboZ§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oiShamm§7 - §61000 + - '' + - §eClick here to play §6Boxing§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Bat + - HolyGarden + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: true + ArcherHCF: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 4 + DURABILITY: 3 + ARROW_FIRE: 1 + ARROW_INFINITE: 1 + repair-cost: 15 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: SUGAR + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_CARROT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: FEATHER + amount: 64 + armor: + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_BOOTS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + PROTECTION_FALL: 4 + repair-cost: 7 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_LEGGINGS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_CHESTPLATE + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_HELMET + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 4 + DURABILITY: 3 + ARROW_FIRE: 1 + ARROW_INFINITE: 1 + repair-cost: 15 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: SUGAR + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_CARROT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: FEATHER + amount: 64 + icon: + ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §aArcherHCF + enchants: + ARROW_DAMAGE: 4 + DURABILITY: 3 + ARROW_FIRE: 1 + ARROW_INFINITE: 1 + repair-cost: 15 + arenaWhitelist: [] + enabled: false + ranked: false + sumo: false + build: false + hcf: true + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Vanilla: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 5 + ARROW_FIRE: 1 + DURABILITY: 3 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 5 + ARROW_FIRE: 1 + DURABILITY: 3 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8229 + meta: + ==: ItemMeta + meta-type: POTION + display-name: §6Vanilla + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oGawdApple§7 - §61000 + - §72. §e§oAlexCanaryYT§7 - §61000 + - §73. §e§oAgentAsh_§7 - §61000 + - '' + - §eClick here to play §6Vanilla§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Combo: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + damage: 1 + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: RAW_FISH + damage: 3 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Combo + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oiShamm§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oDe_el_pler§7 - §61000 + - '' + - §eClick here to play §6Combo§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: true + boxing: false + HCF: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + FIRE_ASPECT: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + FIRE_ASPECT: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §aHCF + enchants: + DAMAGE_ALL: 3 + FIRE_ASPECT: 2 + DURABILITY: 3 + arenaWhitelist: [] + enabled: true + ranked: false + sumo: false + build: false + hcf: true + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Classic: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: BOW + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 3 + - null + - null + - null + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 10 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 16 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Classic + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oLeaan§7 - §61000 + - §72. §e§oiShamm§7 - §61000 + - §73. §e§oBruhMonkeyJayy§7 - §61000 + - '' + - §eClick here to play §6Classic§e. + arenaWhitelist: + - Pepe + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Bard: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: SUGAR + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: IRON_INGOT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: BLAZE_POWDER + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_CARROT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: FEATHER + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: GHAST_TEAR + amount: 64 + armor: + - ==: org.bukkit.inventory.ItemStack + type: GOLD_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + PROTECTION_FALL: 4 + DURABILITY: 3 + repair-cost: 7 + - ==: org.bukkit.inventory.ItemStack + type: GOLD_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: GOLD_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: GOLD_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: GOLD_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §aBard + arenaWhitelist: [] + enabled: false + ranked: false + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Axe: + contents: + - ==: org.bukkit.inventory.ItemStack + type: IRON_AXE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: IRON_BOOTS + - ==: org.bukkit.inventory.ItemStack + type: IRON_LEGGINGS + - ==: org.bukkit.inventory.ItemStack + type: IRON_CHESTPLATE + - ==: org.bukkit.inventory.ItemStack + type: IRON_HELMET + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: IRON_AXE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: IRON_AXE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Axe + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oiShamm§7 - §61000 + - §72. §e§oAgentAsh_§7 - §61000 + - §73. §e§oReleases§7 - §61000 + - '' + - §eClick here to play §6Axe§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Soup: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + armor: + - ==: org.bukkit.inventory.ItemStack + type: IRON_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: IRON_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: IRON_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: IRON_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + icon: + ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Soup + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oReleases§7 - §61000 + - §72. §e§oDe_el_pler§7 - §61000 + - §73. §e§oAlexCanaryYT§7 - §61000 + - '' + - §eClick here to play §6Soup§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Toxic + - Pond + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Debuff: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16394 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16394 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + meta: + ==: ItemMeta + meta-type: POTION + display-name: §6Debuff + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oiShamm§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oBruhMonkeyJayy§7 - §61000 + - '' + - §eClick here to play §6Debuff§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - HolyGarden + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + BuildUHC: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 3 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: WOOD + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 3 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: Golden Head + repair-cost: 2 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 6 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_AXE + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_PICKAXE + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: ANVIL + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - ==: org.bukkit.inventory.ItemStack + type: COBBLESTONE + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: LAVA_BUCKET + - ==: org.bukkit.inventory.ItemStack + type: LAVA_BUCKET + - ==: org.bukkit.inventory.ItemStack + type: WATER_BUCKET + - ==: org.bukkit.inventory.ItemStack + type: WATER_BUCKET + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_PROJECTILE: 2 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_PROJECTILE: 2 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: LAVA_BUCKET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6BuildUHC + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oAlexCanaryYT§7 - §61000 + - §72. §e§oLeaan§7 - §61000 + - §73. §e§oDe_el_pler§7 - §61000 + - '' + - §eClick here to play §6BuildUHC§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Build_1 + - Build_2 + enabled: true + ranked: true + sumo: false + build: true + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false diff --git a/Practice/src/main/resources/plugin.yml b/Practice/src/main/resources/plugin.yml new file mode 100644 index 0000000..ca2e413 --- /dev/null +++ b/Practice/src/main/resources/plugin.yml @@ -0,0 +1,8 @@ +main: me.devkevin.practice.Practice +name: Practice +author: DevKevin +version: 10.3 +description: Prac LOL Practice Plugin +depend: + - LandCore + - HolographicDisplays \ No newline at end of file diff --git a/Practice/target/Practice-dev-SNAPSHOT.jar b/Practice/target/Practice-dev-SNAPSHOT.jar new file mode 100644 index 0000000..ad98b1b Binary files /dev/null and b/Practice/target/Practice-dev-SNAPSHOT.jar differ diff --git a/Practice/target/classes/arenas.yml b/Practice/target/classes/arenas.yml new file mode 100644 index 0000000..dc815d4 --- /dev/null +++ b/Practice/target/classes/arenas.yml @@ -0,0 +1,283 @@ +arenas: + Fruit: + icon: STAINED_CLAY + icon-data: 4 + a: 13993.56925287581, 77.0, 1002.8598639286706, 0.8022766, -0.27107227 + b: 13993.543665620347, 77.0, 1012.2661663567684, 180.09406, -0.13225307 + min: 13971.485578375894, 69.0, 1039.6635567841945, 343.85983, 60.273026 + max: 14015.566043032288, 100.0, 984.4902973420366, 44.718704, 1.3887854 + build-max: 0 + dead-zone: 67 + portalProt: 0 + enabled: true + Snow: + icon: SNOW_BLOCK + icon-data: 0 + a: 16000.467308364958, 100.0, 1006.2122934040414, 181.65474, 1.5271193 + b: 16000.48169153912, 100.0, 996.7169603753629, 0.5572176, -3.1947443 + min: 16042.506842136312, 90.0, 957.3141324974871, 37.22205, 45.13484 + max: 16051.413190542547, 161.0, 1057.4124575332019, 137.3517, 48.606697 + build-max: 0 + dead-zone: 92 + portalProt: 0 + enabled: true + Flags: + icon: WOOL + icon-data: 14 + a: 19066.562116470737, 168.0, 1082.4276088394163, -87.688965, 7.645244 + b: 19102.60006308129, 168.0, 1082.5215928104817, -269.50293, 6.2564664 + min: 19006.5, 91.00099999523162, 1115.5, 236.61551, -40.12881 + max: 19147.5, 213.00099999523164, 1057.5, 62.73755, 32.64334 + build-max: 180 + dead-zone: 160 + portalProt: 0 + enabled: false + standaloneArenas: + '0': + a: 29066.562116470737, 168.0, 11082.427608839416, -87.688965, 7.645244 + b: 29102.60006308129, 168.0, 11082.52159281048, -269.50293, 6.2564664 + min: 29006.5, 91.00099999523162, 11115.5, 236.61551, -40.12881 + max: 29147.5, 213.00099999523164, 11057.5, 62.73755, 32.64334 + '1': + a: 48214.56211647074, 168.0, 12140.427608839416, -87.688965, 7.645244 + b: 48250.60006308129, 168.0, 12140.52159281048, -269.50293, 6.2564664 + min: 48154.5, 91.00099999523162, 12173.5, 236.61551, -40.12881 + max: 48295.5, 213.00099999523164, 12115.5, 62.73755, 32.64334 + '2': + a: 67362.56211647074, 168.0, 13198.427608839416, -87.688965, 7.645244 + b: 67398.60006308129, 168.0, 13198.52159281048, -269.50293, 6.2564664 + min: 67302.5, 91.00099999523162, 13231.5, 236.61551, -40.12881 + max: 67443.5, 213.00099999523164, 13173.5, 62.73755, 32.64334 + '3': + a: 86510.56211647074, 168.0, 14256.427608839416, -87.688965, 7.645244 + b: 86546.60006308129, 168.0, 14256.52159281048, -269.50293, 6.2564664 + min: 86450.5, 91.00099999523162, 14289.5, 236.61551, -40.12881 + max: 86591.5, 213.00099999523164, 14231.5, 62.73755, 32.64334 + '4': + a: 105658.56211647074, 168.0, 15314.427608839416, -87.688965, 7.645244 + b: 105694.60006308129, 168.0, 15314.52159281048, -269.50293, 6.2564664 + min: 105598.5, 91.00099999523162, 15347.5, 236.61551, -40.12881 + max: 105739.5, 213.00099999523164, 15289.5, 62.73755, 32.64334 + '5': + a: 124806.56211647074, 168.0, 16372.427608839416, -87.688965, 7.645244 + b: 124842.60006308129, 168.0, 16372.52159281048, -269.50293, 6.2564664 + min: 124746.5, 91.00099999523162, 16405.5, 236.61551, -40.12881 + max: 124887.5, 213.00099999523164, 16347.5, 62.73755, 32.64334 + '6': + a: 143954.56211647074, 168.0, 17430.427608839418, -87.688965, 7.645244 + b: 143990.60006308128, 168.0, 17430.52159281048, -269.50293, 6.2564664 + min: 143894.5, 91.00099999523162, 17463.5, 236.61551, -40.12881 + max: 144035.5, 213.00099999523164, 17405.5, 62.73755, 32.64334 + '7': + a: 163102.56211647074, 168.0, 18488.427608839418, -87.688965, 7.645244 + b: 163138.60006308128, 168.0, 18488.52159281048, -269.50293, 6.2564664 + min: 163042.5, 91.00099999523162, 18521.5, 236.61551, -40.12881 + max: 163183.5, 213.00099999523164, 18463.5, 62.73755, 32.64334 + '8': + a: 182250.56211647074, 168.0, 19546.427608839418, -87.688965, 7.645244 + b: 182286.60006308128, 168.0, 19546.52159281048, -269.50293, 6.2564664 + min: 182190.5, 91.00099999523162, 19579.5, 236.61551, -40.12881 + max: 182331.5, 213.00099999523164, 19521.5, 62.73755, 32.64334 + '9': + a: 201398.56211647074, 168.0, 20604.427608839418, -87.688965, 7.645244 + b: 201434.60006308128, 168.0, 20604.52159281048, -269.50293, 6.2564664 + min: 201338.5, 91.00099999523162, 20637.5, 236.61551, -40.12881 + max: 201479.5, 213.00099999523164, 20579.5, 62.73755, 32.64334 + '10': + a: 220546.56211647074, 168.0, 21662.427608839418, -87.688965, 7.645244 + b: 220582.60006308128, 168.0, 21662.52159281048, -269.50293, 6.2564664 + min: 220486.5, 91.00099999523162, 21695.5, 236.61551, -40.12881 + max: 220627.5, 213.00099999523164, 21637.5, 62.73755, 32.64334 + '11': + a: 239694.56211647074, 168.0, 22720.427608839418, -87.688965, 7.645244 + b: 239730.60006308128, 168.0, 22720.52159281048, -269.50293, 6.2564664 + min: 239634.5, 91.00099999523162, 22753.5, 236.61551, -40.12881 + max: 239775.5, 213.00099999523164, 22695.5, 62.73755, 32.64334 + '12': + a: 258842.56211647074, 168.0, 23778.427608839418, -87.688965, 7.645244 + b: 258878.60006308128, 168.0, 23778.52159281048, -269.50293, 6.2564664 + min: 258782.5, 91.00099999523162, 23811.5, 236.61551, -40.12881 + max: 258923.5, 213.00099999523164, 23753.5, 62.73755, 32.64334 + '13': + a: 277990.5621164707, 168.0, 24836.427608839418, -87.688965, 7.645244 + b: 278026.6000630813, 168.0, 24836.52159281048, -269.50293, 6.2564664 + min: 277930.5, 91.00099999523162, 24869.5, 236.61551, -40.12881 + max: 278071.5, 213.00099999523164, 24811.5, 62.73755, 32.64334 + '14': + a: 297138.5621164707, 168.0, 25894.427608839418, -87.688965, 7.645244 + b: 297174.6000630813, 168.0, 25894.52159281048, -269.50293, 6.2564664 + min: 297078.5, 91.00099999523162, 25927.5, 236.61551, -40.12881 + max: 297219.5, 213.00099999523164, 25869.5, 62.73755, 32.64334 + Spotify: + icon: WOOL + icon-data: 5 + a: 22115.40718319644, 109.0, 923.7759888757345, 0.2563175, -6.798522 + b: 22115.57390542501, 109.0, 1041.12445380757, 179.82605, -9.576192 + min: 22052.332368818734, 104.0, 1053.7236759181312, 219.43248, 58.61325 + max: 22172.611982717757, 210.0, 919.210185494591, 42.614227, 73.75092 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Mario: + icon: STAINED_CLAY + icon-data: 13 + a: 15001.500115323659, 100.0, 995.5884605774947, 359.00156, -1.8054876 + b: 15001.422276037185, 100.0, 1005.5591621393046, 180.65588, 1.8124976 + min: 15031.534489222116, 82.0, 952.299272766365, 29.976685, 2.090129 + max: 14953.5, 163.00099999523164, 1058.5, 224.01006, 35.00436 + build-max: 0 + dead-zone: 83 + portalProt: 0 + enabled: true + MarioBros: + icon: WOOL + icon-data: 14 + a: 11986.481841337672, 112.0, 1079.3199795430326, 180.68317, -5.47922 + b: 11986.435509078288, 112.0, 961.6470391553454, 0.3919983, -7.145761 + min: 11924.65708955614, 107.0, 952.0277239432368, 317.06705, 6.79806 + max: 12043.376087422193, 213.0, 1085.3312769191114, 315.11972, 68.59887 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Pepe: + icon: WOOL + icon-data: 13 + a: 21059.452026503157, 131.0, 925.7261962956578, 359.8327, -7.6314063 + b: 21059.530188031636, 131.0, 1043.2533796201337, 180.37396, -7.075925 + min: 21122.203025450246, 126.0, 915.7248735532214, 41.083313, -4.0204725 + max: 21002.342611982054, 205.0, 1049.5030949886657, 222.48347, 89.30572 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Apple: + icon: WOOL + icon-data: 15 + a: 8971.440471675896, 117.0, 764.7994071569353, 0.20355225, -8.186898 + b: 8971.5318738981, 117.0, 882.3815833383086, 179.93918, -8.74249 + min: 9033.85493064858, 112.0, 893.752067739367, 132.58282, -0.54887325 + max: 8913.436589248062, 190.0, 759.4504124444001, 328.81506, 28.337883 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Winter: + icon: SNOW_BLOCK + icon-data: 0 + a: 10002.546502519843, 100.0, 920.3900654852531, 180.67973, -2.423632 + b: 10002.455384307032, 100.0, 859.651612277709, -0.14024962, -2.8403184 + min: 10036.57039557963, 100.0, 830.5172879832027, 5.6621704, -4.8678646 + max: 9967.267865129243, 175.0, 924.9183556440516, 223.59195, 65.54349 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Hills: + icon: STAINED_CLAY + icon-data: 5 + a: 6093.449730232747, 129.0, 1082.4237578106013, 180.69, -3.7430534 + b: 6093.5323069242495, 129.0, 999.4827651130001, 0.2869873, -3.7431006 + min: 6036.5, 124.00099999523162, 1101.5, 198.0614, -23.616278 + max: 6138.54229628501, 178.0, 997.3646122136986, 19.039825, 63.877037 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Overwatch: + icon: WOOL + icon-data: 11 + a: 10882.510129812677, 113.0, 995.2866489715417, 180.30206, -5.409549 + b: 10882.465580053398, 113.0, 905.8281544896956, 0.5924072, -6.798321 + min: 10834.399823399635, 113.0, 1000.3000000119209, 177.53033, 50.82234 + max: 10929.548583697624, 178.0, 901.4518126394219, 29.479706, 67.21005 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true + Build_1: + icon: CACTUS + icon-data: 0 + a: 17000.453664898403, 101.0, 947.5490779901662, 0.13868101, -1.527684 + b: 16996.10492935065, 102.0, 1049.0188404890514, 183.59636, -1.1109011 + min: 17039.579550377606, 95.0, 939.6999999880791, 14.005066, 49.294865 + max: 16961.351556788093, 147.0, 1056.5503808176527, 197.7627, 58.73857 + build-max: 122 + dead-zone: 0 + portalProt: 0 + enabled: true + standaloneArenas: + '0': + a: 27000.453664898403, 101.0, 10947.549077990167, 0.13868101, -1.527684 + b: 26996.10492935065, 102.0, 11049.01884048905, 183.59636, -1.1109011 + min: 27039.579550377606, 95.0, 10939.699999988079, 14.005066, 49.294865 + max: 26961.351556788093, 147.0, 11056.550380817653, 197.7627, 58.73857 + '1': + a: 43961.45366489841, 101.0, 12004.549077990167, 0.13868101, -1.527684 + b: 43957.10492935065, 102.0, 12106.01884048905, 183.59636, -1.1109011 + min: 44000.5795503776, 95.0, 11996.699999988079, 14.005066, 49.294865 + max: 43922.3515567881, 147.0, 12113.550380817653, 197.7627, 58.73857 + '2': + a: 60922.45366489841, 101.0, 13061.549077990167, 0.13868101, -1.527684 + b: 60918.10492935065, 102.0, 13163.01884048905, 183.59636, -1.1109011 + min: 60961.5795503776, 95.0, 13053.699999988079, 14.005066, 49.294865 + max: 60883.3515567881, 147.0, 13170.550380817653, 197.7627, 58.73857 + '3': + a: 77883.4536648984, 101.0, 14118.549077990167, 0.13868101, -1.527684 + b: 77879.10492935065, 102.0, 14220.01884048905, 183.59636, -1.1109011 + min: 77922.5795503776, 95.0, 14110.699999988079, 14.005066, 49.294865 + max: 77844.3515567881, 147.0, 14227.550380817653, 197.7627, 58.73857 + '4': + a: 94844.4536648984, 101.0, 15175.549077990167, 0.13868101, -1.527684 + b: 94840.10492935065, 102.0, 15277.01884048905, 183.59636, -1.1109011 + min: 94883.5795503776, 95.0, 15167.699999988079, 14.005066, 49.294865 + max: 94805.3515567881, 147.0, 15284.550380817653, 197.7627, 58.73857 + Build_2: + icon: GRASS + icon-data: 0 + a: 17994.365682695505, 102.0, 1045.1897517012808, 181.65347, 0.6943345 + b: 18001.905486768388, 101.0, 946.2265643191207, 1.9195557, -3.3332129 + min: 17960.412750812186, 95.0, 1055.300000011921, 186.76599, 44.156284 + max: 18038.68728533059, 147.0, 938.6464255381953, 36.361725, 52.76673 + build-max: 115 + dead-zone: 0 + portalProt: 0 + enabled: true + standaloneArenas: + '0': + a: 27994.365682695505, 102.0, 11045.18975170128, 181.65347, 0.6943345 + b: 28001.905486768388, 101.0, 10946.22656431912, 1.9195557, -3.3332129 + min: 27960.412750812186, 95.0, 11055.300000011921, 186.76599, 44.156284 + max: 28038.68728533059, 147.0, 10938.646425538196, 36.361725, 52.76673 + '1': + a: 46033.365682695505, 102.0, 11984.18975170128, 181.65347, 0.6943345 + b: 46040.90548676839, 101.0, 11885.22656431912, 1.9195557, -3.3332129 + min: 45999.41275081219, 95.0, 11994.300000011921, 186.76599, 44.156284 + max: 46077.68728533059, 147.0, 11877.646425538196, 36.361725, 52.76673 + '2': + a: 64072.365682695505, 102.0, 12923.18975170128, 181.65347, 0.6943345 + b: 64079.90548676839, 101.0, 12824.22656431912, 1.9195557, -3.3332129 + min: 64038.41275081219, 95.0, 12933.300000011921, 186.76599, 44.156284 + max: 64116.68728533059, 147.0, 12816.646425538196, 36.361725, 52.76673 + '3': + a: 82111.3656826955, 102.0, 13862.18975170128, 181.65347, 0.6943345 + b: 82118.90548676839, 101.0, 13763.22656431912, 1.9195557, -3.3332129 + min: 82077.41275081219, 95.0, 13872.300000011921, 186.76599, 44.156284 + max: 82155.68728533058, 147.0, 13755.646425538196, 36.361725, 52.76673 + '4': + a: 100150.3656826955, 102.0, 14801.18975170128, 181.65347, 0.6943345 + b: 100157.90548676839, 101.0, 14702.22656431912, 1.9195557, -3.3332129 + min: 100116.41275081219, 95.0, 14811.300000011921, 186.76599, 44.156284 + max: 100194.68728533058, 147.0, 14694.646425538196, 36.361725, 52.76673 + Valorant: + icon: WOOL + icon-data: 14 + a: 4635.523942635199, 128.0, 1061.6183836999944, 0.651886, -5.687129 + b: 4635.554576107276, 128.0, 1141.4896910692794, 180.38774, -4.0206213 + min: 4678.446700265333, 127.0, 1056.6161121884388, 4.958557, 40.128674 + max: 4592.553027944798, 186.0, 1144.6864615319726, 220.38509, 78.45915 + build-max: 0 + dead-zone: 0 + portalProt: 0 + enabled: true diff --git a/Practice/target/classes/club/inverted/chatcolor/CC$1.class b/Practice/target/classes/club/inverted/chatcolor/CC$1.class new file mode 100644 index 0000000..0ad6560 Binary files /dev/null and b/Practice/target/classes/club/inverted/chatcolor/CC$1.class differ diff --git a/Practice/target/classes/club/inverted/chatcolor/CC.class b/Practice/target/classes/club/inverted/chatcolor/CC.class new file mode 100644 index 0000000..126ff67 Binary files /dev/null and b/Practice/target/classes/club/inverted/chatcolor/CC.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/Aether$1.class b/Practice/target/classes/com/bizarrealex/aether/Aether$1.class new file mode 100644 index 0000000..6094c1d Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/Aether$1.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/Aether.class b/Practice/target/classes/com/bizarrealex/aether/Aether.class new file mode 100644 index 0000000..2761303 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/Aether.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/AetherOptions.class b/Practice/target/classes/com/bizarrealex/aether/AetherOptions.class new file mode 100644 index 0000000..2e54754 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/AetherOptions.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/event/BoardCreateEvent.class b/Practice/target/classes/com/bizarrealex/aether/event/BoardCreateEvent.class new file mode 100644 index 0000000..a626b15 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/event/BoardCreateEvent.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/scoreboard/Board.class b/Practice/target/classes/com/bizarrealex/aether/scoreboard/Board.class new file mode 100644 index 0000000..b184c38 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/scoreboard/Board.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/scoreboard/BoardAdapter.class b/Practice/target/classes/com/bizarrealex/aether/scoreboard/BoardAdapter.class new file mode 100644 index 0000000..5238b83 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/scoreboard/BoardAdapter.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/scoreboard/BoardEntry.class b/Practice/target/classes/com/bizarrealex/aether/scoreboard/BoardEntry.class new file mode 100644 index 0000000..4b48f74 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/scoreboard/BoardEntry.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.class b/Practice/target/classes/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.class new file mode 100644 index 0000000..4041dc1 Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.class differ diff --git a/Practice/target/classes/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.class b/Practice/target/classes/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.class new file mode 100644 index 0000000..efa391e Binary files /dev/null and b/Practice/target/classes/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.class differ diff --git a/Practice/target/classes/config.yml b/Practice/target/classes/config.yml new file mode 100644 index 0000000..f527319 --- /dev/null +++ b/Practice/target/classes/config.yml @@ -0,0 +1,48 @@ +DATABASE: + MONGO: + DATABASE: "Practice" + HOST: "127.0.0.1" + PORT: 27017 + AUTHENTICATION: + ENABLED: FALSE + DATABASE: "admin" + USER: "user" + PASSWORD: "password" + +region: "REGION" + +LEADERBOARDS: + UPDATE-TIME: 15 # The time is calculated in minutes + UPDATE-MESSAGE: "&8[&b&lPractice&8] &7&oUpdating leaderboards! This could cause minor lag..." + +PLACEHOLDER-API: + PLAYER-KIT-ELO-FORMAT: "&b &f&8. &7(&f&7)" + +HOLOGRAM: + UPDATE-TIME: 20 # Seconds + FORMAT: + FORMAT: "&b. &f: &b" + LINES: + - "&b&lPractice Leaderboards" + - "&7" + - "&b " + - "&7" + - "" + WINSTREAK: + FORMAT: "&b. &f: &b" + LINES: + - "&b&lPractice Winstreak Leaderboards" + - "&7" + - "&b " + - "&7" + - "" + +NPC: + UPDATE-TIME: 20 # Seconds + FORMAT: + FORMAT: '&6# &f &7» &f &7» ' + LINES: + - "&a◉ ◉" + - "" + - "&7" + - "&fNext update in &6" \ No newline at end of file diff --git a/Practice/target/classes/ladders.yml b/Practice/target/classes/ladders.yml new file mode 100644 index 0000000..6ebf12f --- /dev/null +++ b/Practice/target/classes/ladders.yml @@ -0,0 +1,3307 @@ +ladders: + Gapple: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + damage: 1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + amount: 0 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + damage: 1 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Gapple + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oGawdApple§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oAgentAsh_§7 - §61000 + - '' + - §eClick here to play §6Gapple§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + NoDebuff: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: COOKED_FISH + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GRILLED_PORK + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + meta: + ==: ItemMeta + meta-type: POTION + display-name: §6NoDebuff + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oLeaan§7 - §61000 + - §72. §e§oAgentAsh_§7 - §61000 + - §73. §e§oAlleComboZ§7 - §61000 + - '' + - §eClick here to play §6NoDebuff§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Bat + - Christmas + - RedSand + - SnowTree + - HolyGarden + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Sumo: + contents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: STICK + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Sumo + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oBruhMonkeyJayy§7 - §61000 + - §72. §e§oAlleComboZ§7 - §61000 + - §73. §e§oAlexCanaryYT§7 - §61000 + - '' + - §eClick here to play §6Sumo§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Mario + - Fruit + - Snow + enabled: true + ranked: true + sumo: true + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Archer: + contents: + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 1 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: WOOD_PICKAXE + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 12 + - null + - null + - null + - null + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16454 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_BOOTS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_LEGGINGS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_CHESTPLATE + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_HELMET + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Archer + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oDe_el_pler§7 - §61000 + - §72. §e§oAgentAsh_§7 - §61000 + - §73. §e§oAlleComboZ§7 - §61000 + - '' + - §eClick here to play §6Archer§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Boxing: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + repair-cost: 8 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + - ==: org.bukkit.inventory.ItemStack + type: AIR + damage: -1 + amount: 0 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Boxing + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oAlleComboZ§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oiShamm§7 - §61000 + - '' + - §eClick here to play §6Boxing§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Bat + - HolyGarden + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: true + ArcherHCF: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 4 + DURABILITY: 3 + ARROW_FIRE: 1 + ARROW_INFINITE: 1 + repair-cost: 15 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: SUGAR + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_CARROT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: FEATHER + amount: 64 + armor: + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_BOOTS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + PROTECTION_FALL: 4 + repair-cost: 7 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_LEGGINGS + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_CHESTPLATE + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: LEATHER_HELMET + meta: + ==: ItemMeta + meta-type: LEATHER_ARMOR + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 4 + DURABILITY: 3 + ARROW_FIRE: 1 + ARROW_INFINITE: 1 + repair-cost: 15 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: SUGAR + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_CARROT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: FEATHER + amount: 64 + icon: + ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §aArcherHCF + enchants: + ARROW_DAMAGE: 4 + DURABILITY: 3 + ARROW_FIRE: 1 + ARROW_INFINITE: 1 + repair-cost: 15 + arenaWhitelist: [] + enabled: false + ranked: false + sumo: false + build: false + hcf: true + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Vanilla: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 5 + ARROW_FIRE: 1 + DURABILITY: 3 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 5 + ARROW_FIRE: 1 + DURABILITY: 3 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8257 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8233 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8229 + meta: + ==: ItemMeta + meta-type: POTION + display-name: §6Vanilla + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oGawdApple§7 - §61000 + - §72. §e§oAlexCanaryYT§7 - §61000 + - §73. §e§oAgentAsh_§7 - §61000 + - '' + - §eClick here to play §6Vanilla§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Combo: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 5 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + damage: 1 + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 4 + DURABILITY: 3 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: RAW_FISH + damage: 3 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Combo + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oiShamm§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oDe_el_pler§7 - §61000 + - '' + - §eClick here to play §6Combo§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: true + boxing: false + HCF: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + FIRE_ASPECT: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + FIRE_ASPECT: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §aHCF + enchants: + DAMAGE_ALL: 3 + FIRE_ASPECT: 2 + DURABILITY: 3 + arenaWhitelist: [] + enabled: true + ranked: false + sumo: false + build: false + hcf: true + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Classic: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: BOW + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 3 + - null + - null + - null + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 10 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 16 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Classic + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oLeaan§7 - §61000 + - §72. §e§oiShamm§7 - §61000 + - §73. §e§oBruhMonkeyJayy§7 - §61000 + - '' + - §eClick here to play §6Classic§e. + arenaWhitelist: + - Pepe + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Bard: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: SUGAR + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: IRON_INGOT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: BLAZE_POWDER + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_CARROT + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: FEATHER + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: GHAST_TEAR + amount: 64 + armor: + - ==: org.bukkit.inventory.ItemStack + type: GOLD_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + PROTECTION_FALL: 4 + DURABILITY: 3 + repair-cost: 7 + - ==: org.bukkit.inventory.ItemStack + type: GOLD_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: GOLD_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + - ==: org.bukkit.inventory.ItemStack + type: GOLD_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + DURABILITY: 3 + repair-cost: 3 + kitEditContents: + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: GOLD_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §aBard + arenaWhitelist: [] + enabled: false + ranked: false + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Axe: + contents: + - ==: org.bukkit.inventory.ItemStack + type: IRON_AXE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: IRON_BOOTS + - ==: org.bukkit.inventory.ItemStack + type: IRON_LEGGINGS + - ==: org.bukkit.inventory.ItemStack + type: IRON_CHESTPLATE + - ==: org.bukkit.inventory.ItemStack + type: IRON_HELMET + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: IRON_AXE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: IRON_AXE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Axe + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oiShamm§7 - §61000 + - §72. §e§oAgentAsh_§7 - §61000 + - §73. §e§oReleases§7 - §61000 + - '' + - §eClick here to play §6Axe§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Soup: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + armor: + - ==: org.bukkit.inventory.ItemStack + type: IRON_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: IRON_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: IRON_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + - ==: org.bukkit.inventory.ItemStack + type: IRON_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 1 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 1 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + - ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + icon: + ==: org.bukkit.inventory.ItemStack + type: MUSHROOM_SOUP + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6Soup + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oReleases§7 - §61000 + - §72. §e§oDe_el_pler§7 - §61000 + - §73. §e§oAlexCanaryYT§7 - §61000 + - '' + - §eClick here to play §6Soup§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Toxic + - Pond + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - Valorant + - Overwatch + - Hills + - Winter + - Apple + - Pepe + - Spotify + - MarioBros + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + Debuff: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16394 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + PROTECTION_FALL: 4 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + DURABILITY: 3 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + DURABILITY: 3 + FIRE_ASPECT: 2 + - ==: org.bukkit.inventory.ItemStack + type: ENDER_PEARL + amount: 16 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8259 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16394 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16426 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16421 + - ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 8226 + icon: + ==: org.bukkit.inventory.ItemStack + type: POTION + damage: 16388 + meta: + ==: ItemMeta + meta-type: POTION + display-name: §6Debuff + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oiShamm§7 - §61000 + - §72. §e§oReleases§7 - §61000 + - §73. §e§oBruhMonkeyJayy§7 - §61000 + - '' + - §eClick here to play §6Debuff§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Pond + - Toxic + - Fountain + - Candy + - Cavern + - YingYang + - Desert + - Train + - Panda + - HolyGarden + - MarioBros + - Spotify + - Pepe + - Apple + - Winter + - Hills + - Overwatch + - Valorant + enabled: true + ranked: true + sumo: false + build: false + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false + BuildUHC: + contents: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_SWORD + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + DAMAGE_ALL: 3 + - ==: org.bukkit.inventory.ItemStack + type: FISHING_ROD + - ==: org.bukkit.inventory.ItemStack + type: BOW + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + ARROW_DAMAGE: 3 + ARROW_INFINITE: 1 + - ==: org.bukkit.inventory.ItemStack + type: WOOD + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 3 + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: Golden Head + repair-cost: 2 + - ==: org.bukkit.inventory.ItemStack + type: GOLDEN_APPLE + amount: 6 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_AXE + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_PICKAXE + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: ARROW + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: ANVIL + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - ==: org.bukkit.inventory.ItemStack + type: COBBLESTONE + amount: 64 + - ==: org.bukkit.inventory.ItemStack + type: LAVA_BUCKET + - ==: org.bukkit.inventory.ItemStack + type: LAVA_BUCKET + - ==: org.bukkit.inventory.ItemStack + type: WATER_BUCKET + - ==: org.bukkit.inventory.ItemStack + type: WATER_BUCKET + - null + armor: + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_BOOTS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_PROJECTILE: 2 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_LEGGINGS + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_CHESTPLATE + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_ENVIRONMENTAL: 2 + - ==: org.bukkit.inventory.ItemStack + type: DIAMOND_HELMET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + enchants: + PROTECTION_PROJECTILE: 2 + kitEditContents: + - ==: org.bukkit.inventory.ItemStack + type: COOKED_BEEF + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + - null + icon: + ==: org.bukkit.inventory.ItemStack + type: LAVA_BUCKET + meta: + ==: ItemMeta + meta-type: UNSPECIFIC + display-name: §6BuildUHC + lore: + - '§7● §eIn queue: §60' + - '§7● §eIn match: §60' + - '' + - §71. §e§oAlexCanaryYT§7 - §61000 + - §72. §e§oLeaan§7 - §61000 + - §73. §e§oDe_el_pler§7 - §61000 + - '' + - §eClick here to play §6BuildUHC§e. + ItemFlags: !!set + HIDE_UNBREAKABLE: null + HIDE_POTION_EFFECTS: null + HIDE_ATTRIBUTES: null + arenaWhitelist: + - Build_1 + - Build_2 + enabled: true + ranked: true + sumo: false + build: true + hcf: false + parkour: false + spleef: false + bedWars: false + combo: false + boxing: false diff --git a/Practice/target/classes/me/devkevin/practice/Practice.class b/Practice/target/classes/me/devkevin/practice/Practice.class new file mode 100644 index 0000000..48d031c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/Practice.class differ diff --git a/Practice/target/classes/me/devkevin/practice/PracticeCache.class b/Practice/target/classes/me/devkevin/practice/PracticeCache.class new file mode 100644 index 0000000..45e9ebc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/PracticeCache.class differ diff --git a/Practice/target/classes/me/devkevin/practice/PracticeLang.class b/Practice/target/classes/me/devkevin/practice/PracticeLang.class new file mode 100644 index 0000000..3b1d9d8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/PracticeLang.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/Arena.class b/Practice/target/classes/me/devkevin/practice/arena/Arena.class new file mode 100644 index 0000000..5928bbf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/Arena.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/data/NekoChunk.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/data/NekoChunk.class new file mode 100644 index 0000000..208c7f8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/data/NekoChunk.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/data/NekoChunkData.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/data/NekoChunkData.class new file mode 100644 index 0000000..06b6f6e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/data/NekoChunkData.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/listener/ArenaPlayerChunkLimiter.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/listener/ArenaPlayerChunkLimiter.class new file mode 100644 index 0000000..36881f4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/listener/ArenaPlayerChunkLimiter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkManager$1.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkManager$1.class new file mode 100644 index 0000000..dd89e5c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkManager$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkManager.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkManager.class new file mode 100644 index 0000000..178bbd3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkRestorationManager.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkRestorationManager.class new file mode 100644 index 0000000..0e83cb3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/manager/ChunkRestorationManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/reset/INekoChunkReset.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/reset/INekoChunkReset.class new file mode 100644 index 0000000..7fcf037 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/reset/INekoChunkReset.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/reset/impl/VanillaNekoChunkReset.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/reset/impl/VanillaNekoChunkReset.class new file mode 100644 index 0000000..990c62c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/reset/impl/VanillaNekoChunkReset.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/restoration/IChunkRestoration.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/restoration/IChunkRestoration.class new file mode 100644 index 0000000..541ab22 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/restoration/IChunkRestoration.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/chunk/restoration/impl/PracticeChunkRestoration.class b/Practice/target/classes/me/devkevin/practice/arena/chunk/restoration/impl/PracticeChunkRestoration.class new file mode 100644 index 0000000..8e01abc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/chunk/restoration/impl/PracticeChunkRestoration.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/command/ArenaChunkCommands.class b/Practice/target/classes/me/devkevin/practice/arena/command/ArenaChunkCommands.class new file mode 100644 index 0000000..f0d0e2d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/command/ArenaChunkCommands.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/command/ArenaCommand.class b/Practice/target/classes/me/devkevin/practice/arena/command/ArenaCommand.class new file mode 100644 index 0000000..e803bd7 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/command/ArenaCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/cuboid/Cuboid$1.class b/Practice/target/classes/me/devkevin/practice/arena/cuboid/Cuboid$1.class new file mode 100644 index 0000000..e125fab Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/cuboid/Cuboid$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/cuboid/Cuboid.class b/Practice/target/classes/me/devkevin/practice/arena/cuboid/Cuboid.class new file mode 100644 index 0000000..f13b7da Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/cuboid/Cuboid.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidBlockIterator.class b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidBlockIterator.class new file mode 100644 index 0000000..25cc46d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidBlockIterator.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidDirection$1.class b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidDirection$1.class new file mode 100644 index 0000000..1c8d4cc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidDirection$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidDirection.class b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidDirection.class new file mode 100644 index 0000000..edabd66 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidDirection.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidLocationIterator.class b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidLocationIterator.class new file mode 100644 index 0000000..2afbfcf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/cuboid/CuboidLocationIterator.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCommandRunnable$1.class b/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCommandRunnable$1.class new file mode 100644 index 0000000..1422ac2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCommandRunnable$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCommandRunnable.class b/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCommandRunnable.class new file mode 100644 index 0000000..b66e0d7 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCommandRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCopyRemovalRunnable.class b/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCopyRemovalRunnable.class new file mode 100644 index 0000000..b7bf1af Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/generate/ArenaCopyRemovalRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/generate/BlockPlaceRunnable.class b/Practice/target/classes/me/devkevin/practice/arena/generate/BlockPlaceRunnable.class new file mode 100644 index 0000000..6baaa80 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/generate/BlockPlaceRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/generate/DuplicateArenaRunnable$1.class b/Practice/target/classes/me/devkevin/practice/arena/generate/DuplicateArenaRunnable$1.class new file mode 100644 index 0000000..8b31ae7 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/generate/DuplicateArenaRunnable$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/generate/DuplicateArenaRunnable.class b/Practice/target/classes/me/devkevin/practice/arena/generate/DuplicateArenaRunnable.class new file mode 100644 index 0000000..c2b9f56 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/generate/DuplicateArenaRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/manager/ArenaManager.class b/Practice/target/classes/me/devkevin/practice/arena/manager/ArenaManager.class new file mode 100644 index 0000000..047110d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/manager/ArenaManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaCopyMenu.class b/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaCopyMenu.class new file mode 100644 index 0000000..549967b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaCopyMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaGenerationMenu.class b/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaGenerationMenu.class new file mode 100644 index 0000000..e1d0279 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaGenerationMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaManagerMenu.class b/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaManagerMenu.class new file mode 100644 index 0000000..dc6e823 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/ArenaManagerMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaButton$1.class b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaButton$1.class new file mode 100644 index 0000000..51fc383 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaButton$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaButton.class b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaButton.class new file mode 100644 index 0000000..e796dfe Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton$1.class b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton$1.class new file mode 100644 index 0000000..98114c6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton.class b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton.class new file mode 100644 index 0000000..397c221 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaCopyButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaGenerateButton.class b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaGenerateButton.class new file mode 100644 index 0000000..3634862 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/menu/buttons/ArenaGenerateButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/arena/standalone/StandaloneArena.class b/Practice/target/classes/me/devkevin/practice/arena/standalone/StandaloneArena.class new file mode 100644 index 0000000..f3de901 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/arena/standalone/StandaloneArena.class differ diff --git a/Practice/target/classes/me/devkevin/practice/board/PracticeBoard.class b/Practice/target/classes/me/devkevin/practice/board/PracticeBoard.class new file mode 100644 index 0000000..6071181 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/board/PracticeBoard.class differ diff --git a/Practice/target/classes/me/devkevin/practice/chat/ChatType.class b/Practice/target/classes/me/devkevin/practice/chat/ChatType.class new file mode 100644 index 0000000..818341e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/chat/ChatType.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/PracticeCommand.class b/Practice/target/classes/me/devkevin/practice/command/PracticeCommand.class new file mode 100644 index 0000000..675eb70 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/PracticeCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/general/FlyCommand.class b/Practice/target/classes/me/devkevin/practice/command/general/FlyCommand.class new file mode 100644 index 0000000..d47c7ed Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/general/FlyCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/general/ResetLeaderboardsCommand.class b/Practice/target/classes/me/devkevin/practice/command/general/ResetLeaderboardsCommand.class new file mode 100644 index 0000000..761a727 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/general/ResetLeaderboardsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/general/SetEditorSpawnCommand.class b/Practice/target/classes/me/devkevin/practice/command/general/SetEditorSpawnCommand.class new file mode 100644 index 0000000..b1c153a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/general/SetEditorSpawnCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/general/SetEventSpawnCommand.class b/Practice/target/classes/me/devkevin/practice/command/general/SetEventSpawnCommand.class new file mode 100644 index 0000000..7bc7b92 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/general/SetEventSpawnCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/general/SetSpawnCommand.class b/Practice/target/classes/me/devkevin/practice/command/general/SetSpawnCommand.class new file mode 100644 index 0000000..6982cdf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/general/SetSpawnCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/general/StatsCommand.class b/Practice/target/classes/me/devkevin/practice/command/general/StatsCommand.class new file mode 100644 index 0000000..9364f73 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/general/StatsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/requeue/PlayAgainCommand.class b/Practice/target/classes/me/devkevin/practice/command/requeue/PlayAgainCommand.class new file mode 100644 index 0000000..664439e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/requeue/PlayAgainCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/staff/CancelMatchCommand.class b/Practice/target/classes/me/devkevin/practice/command/staff/CancelMatchCommand.class new file mode 100644 index 0000000..6bae1cc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/staff/CancelMatchCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/staff/FollowCommand.class b/Practice/target/classes/me/devkevin/practice/command/staff/FollowCommand.class new file mode 100644 index 0000000..1a24539 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/staff/FollowCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/staff/OngoingMatchesCommand.class b/Practice/target/classes/me/devkevin/practice/command/staff/OngoingMatchesCommand.class new file mode 100644 index 0000000..3ba4aa3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/staff/OngoingMatchesCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/staff/StaffModeCommand.class b/Practice/target/classes/me/devkevin/practice/command/staff/StaffModeCommand.class new file mode 100644 index 0000000..88bfafc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/staff/StaffModeCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/stats/ResetStatsCommand.class b/Practice/target/classes/me/devkevin/practice/command/stats/ResetStatsCommand.class new file mode 100644 index 0000000..1a989ed Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/stats/ResetStatsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/stats/SetStatsCommand.class b/Practice/target/classes/me/devkevin/practice/command/stats/SetStatsCommand.class new file mode 100644 index 0000000..41baf3a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/stats/SetStatsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/time/DayCommand.class b/Practice/target/classes/me/devkevin/practice/command/time/DayCommand.class new file mode 100644 index 0000000..b4c457a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/time/DayCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/time/NightCommand.class b/Practice/target/classes/me/devkevin/practice/command/time/NightCommand.class new file mode 100644 index 0000000..66e00ef Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/time/NightCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/command/time/SunsetCommand.class b/Practice/target/classes/me/devkevin/practice/command/time/SunsetCommand.class new file mode 100644 index 0000000..7d83cdb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/command/time/SunsetCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/data/PracticeDatabase.class b/Practice/target/classes/me/devkevin/practice/data/PracticeDatabase.class new file mode 100644 index 0000000..ed6a27c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/data/PracticeDatabase.class differ diff --git a/Practice/target/classes/me/devkevin/practice/elo/EloCalculator.class b/Practice/target/classes/me/devkevin/practice/elo/EloCalculator.class new file mode 100644 index 0000000..1b0ddcd Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/elo/EloCalculator.class differ diff --git a/Practice/target/classes/me/devkevin/practice/elo/EloUtil.class b/Practice/target/classes/me/devkevin/practice/elo/EloUtil.class new file mode 100644 index 0000000..e926766 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/elo/EloUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/elo/KFactor.class b/Practice/target/classes/me/devkevin/practice/elo/KFactor.class new file mode 100644 index 0000000..df503d2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/elo/KFactor.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/EventCountdownTask.class b/Practice/target/classes/me/devkevin/practice/events/EventCountdownTask.class new file mode 100644 index 0000000..47e8880 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/EventCountdownTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/EventPlayer.class b/Practice/target/classes/me/devkevin/practice/events/EventPlayer.class new file mode 100644 index 0000000..a915a3a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/EventPlayer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/EventState.class b/Practice/target/classes/me/devkevin/practice/events/EventState.class new file mode 100644 index 0000000..457516f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/EventState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/PracticeEvent.class b/Practice/target/classes/me/devkevin/practice/events/PracticeEvent.class new file mode 100644 index 0000000..cab362f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/PracticeEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/commands/EventManagerCommand.class b/Practice/target/classes/me/devkevin/practice/events/commands/EventManagerCommand.class new file mode 100644 index 0000000..d9bf46c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/commands/EventManagerCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/commands/HostCommand.class b/Practice/target/classes/me/devkevin/practice/events/commands/HostCommand.class new file mode 100644 index 0000000..e2c4c7a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/commands/HostCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/commands/HostEventCommand.class b/Practice/target/classes/me/devkevin/practice/events/commands/HostEventCommand.class new file mode 100644 index 0000000..2a11841 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/commands/HostEventCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/commands/JoinEventCommand.class b/Practice/target/classes/me/devkevin/practice/events/commands/JoinEventCommand.class new file mode 100644 index 0000000..9a5338b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/commands/JoinEventCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/commands/LeaveEventCommand.class b/Practice/target/classes/me/devkevin/practice/events/commands/LeaveEventCommand.class new file mode 100644 index 0000000..cc0e4b0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/commands/LeaveEventCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/event/BaseEvent.class b/Practice/target/classes/me/devkevin/practice/events/event/BaseEvent.class new file mode 100644 index 0000000..685a9fa Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/event/BaseEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/event/EventStartEvent.class b/Practice/target/classes/me/devkevin/practice/events/event/EventStartEvent.class new file mode 100644 index 0000000..88fda87 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/event/EventStartEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/lms/LMSCountdownTask.class b/Practice/target/classes/me/devkevin/practice/events/lms/LMSCountdownTask.class new file mode 100644 index 0000000..70a5703 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/lms/LMSCountdownTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/lms/LMSEvent$LMSGameTask.class b/Practice/target/classes/me/devkevin/practice/events/lms/LMSEvent$LMSGameTask.class new file mode 100644 index 0000000..a5bd080 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/lms/LMSEvent$LMSGameTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/lms/LMSEvent.class b/Practice/target/classes/me/devkevin/practice/events/lms/LMSEvent.class new file mode 100644 index 0000000..caf3cb8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/lms/LMSEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/lms/LMSPlayer$LMSState.class b/Practice/target/classes/me/devkevin/practice/events/lms/LMSPlayer$LMSState.class new file mode 100644 index 0000000..b29fce5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/lms/LMSPlayer$LMSState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/lms/LMSPlayer.class b/Practice/target/classes/me/devkevin/practice/events/lms/LMSPlayer.class new file mode 100644 index 0000000..9f2de8c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/lms/LMSPlayer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/manager/EventManager.class b/Practice/target/classes/me/devkevin/practice/events/manager/EventManager.class new file mode 100644 index 0000000..48b55e4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/manager/EventManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$1.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$1.class new file mode 100644 index 0000000..b777d1f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$2.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$2.class new file mode 100644 index 0000000..db5079d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$3.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$3.class new file mode 100644 index 0000000..b6c9893 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$4.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$4.class new file mode 100644 index 0000000..f33b501 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$5.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$5.class new file mode 100644 index 0000000..e81c9df Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$5.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$6.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$6.class new file mode 100644 index 0000000..d34b9ec Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$6.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$7.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$7.class new file mode 100644 index 0000000..b8dedf3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu$7.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu.class b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu.class new file mode 100644 index 0000000..699f89c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/menu/HostMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCCountdownTask.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCCountdownTask.class new file mode 100644 index 0000000..5549055 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCCountdownTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$1.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$1.class new file mode 100644 index 0000000..11ed198 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$OITCGameTask.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$OITCGameTask.class new file mode 100644 index 0000000..0d7920b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$OITCGameTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$RespawnTask.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$RespawnTask.class new file mode 100644 index 0000000..3647341 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$RespawnTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$SortComparator.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$SortComparator.class new file mode 100644 index 0000000..753e028 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent$SortComparator.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent.class new file mode 100644 index 0000000..413bd4d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCPlayer$OITCState.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCPlayer$OITCState.class new file mode 100644 index 0000000..074535f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCPlayer$OITCState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/oitc/OITCPlayer.class b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCPlayer.class new file mode 100644 index 0000000..63163a6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/oitc/OITCPlayer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/sumo/SumoCountdownTask.class b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoCountdownTask.class new file mode 100644 index 0000000..6c572eb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoCountdownTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent$SumoFightTask.class b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent$SumoFightTask.class new file mode 100644 index 0000000..1b717a1 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent$SumoFightTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent$WaterCheckTask.class b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent$WaterCheckTask.class new file mode 100644 index 0000000..3b48419 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent$WaterCheckTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent.class b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent.class new file mode 100644 index 0000000..26191ed Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/sumo/SumoPlayer$SumoState.class b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoPlayer$SumoState.class new file mode 100644 index 0000000..fa04eff Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoPlayer$SumoState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/sumo/SumoPlayer.class b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoPlayer.class new file mode 100644 index 0000000..9f526b0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/sumo/SumoPlayer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunCountdownTask.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunCountdownTask.class new file mode 100644 index 0000000..cb7e0d6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunCountdownTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$1.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$1.class new file mode 100644 index 0000000..3987066 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$PlayerPosition.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$PlayerPosition.class new file mode 100644 index 0000000..fa96607 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$PlayerPosition.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$RemoveBlocksTask.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$RemoveBlocksTask.class new file mode 100644 index 0000000..81d1b31 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$RemoveBlocksTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$TNTRunGameTask.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$TNTRunGameTask.class new file mode 100644 index 0000000..ed11c03 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$TNTRunGameTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$VoidCheckTask.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$VoidCheckTask.class new file mode 100644 index 0000000..32ec70c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent$VoidCheckTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent.class new file mode 100644 index 0000000..710da55 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunPlayer$TntRunState.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunPlayer$TntRunState.class new file mode 100644 index 0000000..00d2b5c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunPlayer$TntRunState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunPlayer.class b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunPlayer.class new file mode 100644 index 0000000..788e326 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tntrun/TntRunPlayer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagCountdownTask.class b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagCountdownTask.class new file mode 100644 index 0000000..d9cdc1f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagCountdownTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent$TNTTagGameTask.class b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent$TNTTagGameTask.class new file mode 100644 index 0000000..9a231cb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent$TNTTagGameTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent$TNTTagTask.class b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent$TNTTagTask.class new file mode 100644 index 0000000..ed7442a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent$TNTTagTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent.class b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent.class new file mode 100644 index 0000000..d53c6b9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagPlayer$TNTTagState.class b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagPlayer$TNTTagState.class new file mode 100644 index 0000000..b8a852a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagPlayer$TNTTagState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagPlayer.class b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagPlayer.class new file mode 100644 index 0000000..dca1239 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/events/tnttag/TNTTagPlayer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/file/Config.class b/Practice/target/classes/me/devkevin/practice/file/Config.class new file mode 100644 index 0000000..6ba2c3c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/file/Config.class differ diff --git a/Practice/target/classes/me/devkevin/practice/file/ConfigFile.class b/Practice/target/classes/me/devkevin/practice/file/ConfigFile.class new file mode 100644 index 0000000..a51c63b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/file/ConfigFile.class differ diff --git a/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$1.class b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$1.class new file mode 100644 index 0000000..9437f44 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$2.class b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$2.class new file mode 100644 index 0000000..515cfb5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$3.class b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$3.class new file mode 100644 index 0000000..1b94ff3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu.class b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu.class new file mode 100644 index 0000000..3e3be1e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/general/GeneralSettingMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/handler/MovementHandler.class b/Practice/target/classes/me/devkevin/practice/handler/MovementHandler.class new file mode 100644 index 0000000..4f67eb0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/handler/MovementHandler.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/HCFClass.class b/Practice/target/classes/me/devkevin/practice/hcf/HCFClass.class new file mode 100644 index 0000000..5151b14 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/HCFClass.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/classes/Archer$TaggedTask.class b/Practice/target/classes/me/devkevin/practice/hcf/classes/Archer$TaggedTask.class new file mode 100644 index 0000000..cbbdc25 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/classes/Archer$TaggedTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/classes/Archer.class b/Practice/target/classes/me/devkevin/practice/hcf/classes/Archer.class new file mode 100644 index 0000000..c8cdf2d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/classes/Archer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/classes/Bard$1.class b/Practice/target/classes/me/devkevin/practice/hcf/classes/Bard$1.class new file mode 100644 index 0000000..25c6b38 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/classes/Bard$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/classes/Bard.class b/Practice/target/classes/me/devkevin/practice/hcf/classes/Bard.class new file mode 100644 index 0000000..131805a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/classes/Bard.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/effects/BardData.class b/Practice/target/classes/me/devkevin/practice/hcf/effects/BardData.class new file mode 100644 index 0000000..6a5ae2f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/effects/BardData.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/effects/EffectData.class b/Practice/target/classes/me/devkevin/practice/hcf/effects/EffectData.class new file mode 100644 index 0000000..1996f75 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/effects/EffectData.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/effects/EffectRestorer.class b/Practice/target/classes/me/devkevin/practice/hcf/effects/EffectRestorer.class new file mode 100644 index 0000000..baa789a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/effects/EffectRestorer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/event/ArmorClassEquipEvent.class b/Practice/target/classes/me/devkevin/practice/hcf/event/ArmorClassEquipEvent.class new file mode 100644 index 0000000..c8037cf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/event/ArmorClassEquipEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/event/ArmorClassUnequipEvent.class b/Practice/target/classes/me/devkevin/practice/hcf/event/ArmorClassUnequipEvent.class new file mode 100644 index 0000000..34701c0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/event/ArmorClassUnequipEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/kit/HCFKit.class b/Practice/target/classes/me/devkevin/practice/hcf/kit/HCFKit.class new file mode 100644 index 0000000..75a4be4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/kit/HCFKit.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener$1.class b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener$1.class new file mode 100644 index 0000000..b5ea6e7 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener$2.class b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener$2.class new file mode 100644 index 0000000..0395799 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener.class b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener.class new file mode 100644 index 0000000..111409f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFClassListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFMatchListener$1.class b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFMatchListener$1.class new file mode 100644 index 0000000..089b125 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFMatchListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFMatchListener.class b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFMatchListener.class new file mode 100644 index 0000000..d7a6195 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/listener/HCFMatchListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/manager/HCFManager.class b/Practice/target/classes/me/devkevin/practice/hcf/manager/HCFManager.class new file mode 100644 index 0000000..28b83af Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/manager/HCFManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/menu/ClassSelectionMenu.class b/Practice/target/classes/me/devkevin/practice/hcf/menu/ClassSelectionMenu.class new file mode 100644 index 0000000..41cf03f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/menu/ClassSelectionMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/hcf/menu/button/ClassSelectionButton.class b/Practice/target/classes/me/devkevin/practice/hcf/menu/button/ClassSelectionButton.class new file mode 100644 index 0000000..79d67eb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/hcf/menu/button/ClassSelectionButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/Kit.class b/Practice/target/classes/me/devkevin/practice/kit/Kit.class new file mode 100644 index 0000000..62c2f61 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/Kit.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/PlayerKit.class b/Practice/target/classes/me/devkevin/practice/kit/PlayerKit.class new file mode 100644 index 0000000..e63af89 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/PlayerKit.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/command/KitManageCommand.class b/Practice/target/classes/me/devkevin/practice/kit/command/KitManageCommand.class new file mode 100644 index 0000000..c989b97 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/command/KitManageCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/command/KitsCommand.class b/Practice/target/classes/me/devkevin/practice/kit/command/KitsCommand.class new file mode 100644 index 0000000..faf1e8d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/command/KitsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/listener/KitEditorError32Listener.class b/Practice/target/classes/me/devkevin/practice/kit/listener/KitEditorError32Listener.class new file mode 100644 index 0000000..a5391ba Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/listener/KitEditorError32Listener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/manager/EditorManager.class b/Practice/target/classes/me/devkevin/practice/kit/manager/EditorManager.class new file mode 100644 index 0000000..a147d46 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/manager/EditorManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/manager/KitManager.class b/Practice/target/classes/me/devkevin/practice/kit/manager/KitManager.class new file mode 100644 index 0000000..d6fe543 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/manager/KitManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$1.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$1.class new file mode 100644 index 0000000..3cd9bfb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$1.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$1.class new file mode 100644 index 0000000..af0f9ce Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$2.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$2.class new file mode 100644 index 0000000..30641ba Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$3.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$3.class new file mode 100644 index 0000000..6fd7c4e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2.class new file mode 100644 index 0000000..b782b97 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$3.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$3.class new file mode 100644 index 0000000..c310d71 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$4.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$4.class new file mode 100644 index 0000000..957c21a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$5.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$5.class new file mode 100644 index 0000000..5054083 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$5.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$1.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$1.class new file mode 100644 index 0000000..d310b2d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$2.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$2.class new file mode 100644 index 0000000..70d7d2a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$3.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$3.class new file mode 100644 index 0000000..10248c2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6.class new file mode 100644 index 0000000..5f24b28 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$6.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$7.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$7.class new file mode 100644 index 0000000..682d79f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$7.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$8.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$8.class new file mode 100644 index 0000000..98b2a94 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$8.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$9.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$9.class new file mode 100644 index 0000000..a285369 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu$9.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu.class b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu.class new file mode 100644 index 0000000..7d0de9c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/menu/KitEditorMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/kit/npc/EditorNPC.class b/Practice/target/classes/me/devkevin/practice/kit/npc/EditorNPC.class new file mode 100644 index 0000000..e2b21aa Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/kit/npc/EditorNPC.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/Leaderboard.class b/Practice/target/classes/me/devkevin/practice/leaderboard/Leaderboard.class new file mode 100644 index 0000000..612ffc9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/Leaderboard.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/LeaderboardManager.class b/Practice/target/classes/me/devkevin/practice/leaderboard/LeaderboardManager.class new file mode 100644 index 0000000..d0dc040 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/LeaderboardManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/hologram/HologramManager.class b/Practice/target/classes/me/devkevin/practice/leaderboard/hologram/HologramManager.class new file mode 100644 index 0000000..fb7e889 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/hologram/HologramManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/LeaderboardsMenu.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/LeaderboardsMenu.class new file mode 100644 index 0000000..3633087 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/LeaderboardsMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/WinstreaksMenu.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/WinstreaksMenu.class new file mode 100644 index 0000000..6f86240 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/WinstreaksMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/KitStatsButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/KitStatsButton.class new file mode 100644 index 0000000..33156c8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/KitStatsButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/LeaderboardButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/LeaderboardButton.class new file mode 100644 index 0000000..b6980fe Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/LeaderboardButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/LeaderboardGlobalButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/LeaderboardGlobalButton.class new file mode 100644 index 0000000..48f7fe1 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/LeaderboardGlobalButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/PlayerStatsButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/PlayerStatsButton.class new file mode 100644 index 0000000..c2d68f1 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/PlayerStatsButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakButton.class new file mode 100644 index 0000000..5761850 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakGlobalButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakGlobalButton.class new file mode 100644 index 0000000..6364abd Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakGlobalButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakKitButton.class b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakKitButton.class new file mode 100644 index 0000000..ed15605 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/menu/button/WinstreakKitButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/leaderboard/npc/NPCRunnable.class b/Practice/target/classes/me/devkevin/practice/leaderboard/npc/NPCRunnable.class new file mode 100644 index 0000000..26f3dc9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/leaderboard/npc/NPCRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/location/CustomLocation.class b/Practice/target/classes/me/devkevin/practice/location/CustomLocation.class new file mode 100644 index 0000000..f871b85 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/location/CustomLocation.class differ diff --git a/Practice/target/classes/me/devkevin/practice/location/manager/CustomLocationManager.class b/Practice/target/classes/me/devkevin/practice/location/manager/CustomLocationManager.class new file mode 100644 index 0000000..f4b3d43 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/location/manager/CustomLocationManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/Match.class b/Practice/target/classes/me/devkevin/practice/match/Match.class new file mode 100644 index 0000000..fa7eb88 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/Match.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/MatchRequest.class b/Practice/target/classes/me/devkevin/practice/match/MatchRequest.class new file mode 100644 index 0000000..3b1bdf7 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/MatchRequest.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/MatchState.class b/Practice/target/classes/me/devkevin/practice/match/MatchState.class new file mode 100644 index 0000000..babc00b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/MatchState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/MatchTeam.class b/Practice/target/classes/me/devkevin/practice/match/MatchTeam.class new file mode 100644 index 0000000..67cfa15 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/MatchTeam.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/command/AcceptCommand.class b/Practice/target/classes/me/devkevin/practice/match/duel/command/AcceptCommand.class new file mode 100644 index 0000000..dd1e27b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/command/AcceptCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/command/DuelCommand.class b/Practice/target/classes/me/devkevin/practice/match/duel/command/DuelCommand.class new file mode 100644 index 0000000..cfcf049 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/command/DuelCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$1.class b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$1.class new file mode 100644 index 0000000..0ff1500 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$2.class b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$2.class new file mode 100644 index 0000000..3ed7224 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$3.class b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$3.class new file mode 100644 index 0000000..e2f1803 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$4.class b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$4.class new file mode 100644 index 0000000..7a5b4f3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu.class b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu.class new file mode 100644 index 0000000..6598d5e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/duel/menu/DuelMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/event/MatchEvent.class b/Practice/target/classes/me/devkevin/practice/match/event/MatchEvent.class new file mode 100644 index 0000000..bd3de3b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/event/MatchEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/event/impl/MatchEndEvent.class b/Practice/target/classes/me/devkevin/practice/match/event/impl/MatchEndEvent.class new file mode 100644 index 0000000..306b379 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/event/impl/MatchEndEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/event/impl/MatchStartEvent.class b/Practice/target/classes/me/devkevin/practice/match/event/impl/MatchStartEvent.class new file mode 100644 index 0000000..7883ba8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/event/impl/MatchStartEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/freeze/FreezeListener.class b/Practice/target/classes/me/devkevin/practice/match/freeze/FreezeListener.class new file mode 100644 index 0000000..a0acdb9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/freeze/FreezeListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$1.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$1.class new file mode 100644 index 0000000..83ca2eb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$2.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$2.class new file mode 100644 index 0000000..ff214d4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$3.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$3.class new file mode 100644 index 0000000..c66d78f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$4.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$4.class new file mode 100644 index 0000000..c0aa6e4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$5.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$5.class new file mode 100644 index 0000000..a575b1d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$5.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$6.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$6.class new file mode 100644 index 0000000..5300329 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$6.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$7.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$7.class new file mode 100644 index 0000000..9eabc7b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$7.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$8.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$8.class new file mode 100644 index 0000000..87b866e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap$8.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap.class new file mode 100644 index 0000000..0f818fb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchHistoryInvSnap.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/MatchLocatedData.class b/Practice/target/classes/me/devkevin/practice/match/history/MatchLocatedData.class new file mode 100644 index 0000000..3c19254 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/MatchLocatedData.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/command/MatchHistoryCommand.class b/Practice/target/classes/me/devkevin/practice/match/history/command/MatchHistoryCommand.class new file mode 100644 index 0000000..fcc3f93 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/command/MatchHistoryCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/menu/MatchHistoryMenu.class b/Practice/target/classes/me/devkevin/practice/match/history/menu/MatchHistoryMenu.class new file mode 100644 index 0000000..660441f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/menu/MatchHistoryMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/history/menu/button/MatchHistoryButton.class b/Practice/target/classes/me/devkevin/practice/match/history/menu/button/MatchHistoryButton.class new file mode 100644 index 0000000..8b27698 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/history/menu/button/MatchHistoryButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/BowBoostingListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/BowBoostingListener.class new file mode 100644 index 0000000..5ffc8c9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/BowBoostingListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/EnderpearlListener$1.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EnderpearlListener$1.class new file mode 100644 index 0000000..6c84bc4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EnderpearlListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/EnderpearlListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EnderpearlListener.class new file mode 100644 index 0000000..72fad03 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EnderpearlListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/EntityListener$1.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EntityListener$1.class new file mode 100644 index 0000000..8d9951f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EntityListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/EntityListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EntityListener.class new file mode 100644 index 0000000..4af9fb1 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/EntityListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/MatchRodListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/MatchRodListener.class new file mode 100644 index 0000000..7a26ea3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/MatchRodListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/PotionMatchListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/PotionMatchListener.class new file mode 100644 index 0000000..714b655 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/PotionMatchListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/SwordBlockDetector$1.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/SwordBlockDetector$1.class new file mode 100644 index 0000000..a2915a0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/SwordBlockDetector$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/entity/SwordBlockDetector.class b/Practice/target/classes/me/devkevin/practice/match/listener/entity/SwordBlockDetector.class new file mode 100644 index 0000000..6689e76 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/entity/SwordBlockDetector.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/game/MatchEndListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/game/MatchEndListener.class new file mode 100644 index 0000000..f23e8cb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/game/MatchEndListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/game/MatchStartListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/game/MatchStartListener.class new file mode 100644 index 0000000..2c06aaf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/game/MatchStartListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/time/MatchDurationLimitListener$1.class b/Practice/target/classes/me/devkevin/practice/match/listener/time/MatchDurationLimitListener$1.class new file mode 100644 index 0000000..d5fbade Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/time/MatchDurationLimitListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/listener/time/MatchDurationLimitListener.class b/Practice/target/classes/me/devkevin/practice/match/listener/time/MatchDurationLimitListener.class new file mode 100644 index 0000000..ed1505e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/listener/time/MatchDurationLimitListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/manager/MatchManager.class b/Practice/target/classes/me/devkevin/practice/match/manager/MatchManager.class new file mode 100644 index 0000000..db80e10 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/manager/MatchManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/matches/OngoingMatchesMenu.class b/Practice/target/classes/me/devkevin/practice/match/matches/OngoingMatchesMenu.class new file mode 100644 index 0000000..9549196 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/matches/OngoingMatchesMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/matches/buttons/OngoingMatchButton.class b/Practice/target/classes/me/devkevin/practice/match/matches/buttons/OngoingMatchButton.class new file mode 100644 index 0000000..245d7cb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/matches/buttons/OngoingMatchButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/matches/buttons/RefreshButton.class b/Practice/target/classes/me/devkevin/practice/match/matches/buttons/RefreshButton.class new file mode 100644 index 0000000..e6589ff Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/matches/buttons/RefreshButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailSnapshot.class b/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailSnapshot.class new file mode 100644 index 0000000..d365c0c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailSnapshot.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailsMenu$1.class b/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailsMenu$1.class new file mode 100644 index 0000000..6e7b433 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailsMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailsMenu.class b/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailsMenu.class new file mode 100644 index 0000000..a8aca71 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/menu/MatchDetailsMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/menu/command/InvCommand.class b/Practice/target/classes/me/devkevin/practice/match/menu/command/InvCommand.class new file mode 100644 index 0000000..4e4e9c4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/menu/command/InvCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/spec/SpectateCommand.class b/Practice/target/classes/me/devkevin/practice/match/spec/SpectateCommand.class new file mode 100644 index 0000000..151c7ff Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/spec/SpectateCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/task/MatchLogicTask$1.class b/Practice/target/classes/me/devkevin/practice/match/task/MatchLogicTask$1.class new file mode 100644 index 0000000..6def745 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/task/MatchLogicTask$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/task/MatchLogicTask.class b/Practice/target/classes/me/devkevin/practice/match/task/MatchLogicTask.class new file mode 100644 index 0000000..6fe3260 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/task/MatchLogicTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/task/MatchResetRunnable.class b/Practice/target/classes/me/devkevin/practice/match/task/MatchResetRunnable.class new file mode 100644 index 0000000..cdbcc28 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/task/MatchResetRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/task/NewRoundRunnable.class b/Practice/target/classes/me/devkevin/practice/match/task/NewRoundRunnable.class new file mode 100644 index 0000000..3be3d03 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/task/NewRoundRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/task/RematchRunnable.class b/Practice/target/classes/me/devkevin/practice/match/task/RematchRunnable.class new file mode 100644 index 0000000..54f0029 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/task/RematchRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/team/KillableTeam.class b/Practice/target/classes/me/devkevin/practice/match/team/KillableTeam.class new file mode 100644 index 0000000..295f0f3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/team/KillableTeam.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/PlayerTimer.class b/Practice/target/classes/me/devkevin/practice/match/timer/PlayerTimer.class new file mode 100644 index 0000000..e3a9c91 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/PlayerTimer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/Timer.class b/Practice/target/classes/me/devkevin/practice/match/timer/Timer.class new file mode 100644 index 0000000..5b5393d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/Timer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/TimerCooldown$1.class b/Practice/target/classes/me/devkevin/practice/match/timer/TimerCooldown$1.class new file mode 100644 index 0000000..eb982ed Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/TimerCooldown$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/TimerCooldown.class b/Practice/target/classes/me/devkevin/practice/match/timer/TimerCooldown.class new file mode 100644 index 0000000..b7f5db3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/TimerCooldown.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/TimerManager.class b/Practice/target/classes/me/devkevin/practice/match/timer/TimerManager.class new file mode 100644 index 0000000..67ee33d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/TimerManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerClearEvent.class b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerClearEvent.class new file mode 100644 index 0000000..6634d2a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerClearEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerExpireEvent.class b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerExpireEvent.class new file mode 100644 index 0000000..725dbfc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerExpireEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerExtendEvent.class b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerExtendEvent.class new file mode 100644 index 0000000..a540e8e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerExtendEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerPauseEvent.class b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerPauseEvent.class new file mode 100644 index 0000000..3e00bec Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerPauseEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerStartEvent.class b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerStartEvent.class new file mode 100644 index 0000000..335212c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/event/TimerStartEvent.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/timer/impl/EnderpearlTimer.class b/Practice/target/classes/me/devkevin/practice/match/timer/impl/EnderpearlTimer.class new file mode 100644 index 0000000..6991aaf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/timer/impl/EnderpearlTimer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/vote/Vote.class b/Practice/target/classes/me/devkevin/practice/match/vote/Vote.class new file mode 100644 index 0000000..928b4f6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/vote/Vote.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/vote/VoteManager.class b/Practice/target/classes/me/devkevin/practice/match/vote/VoteManager.class new file mode 100644 index 0000000..ad17432 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/vote/VoteManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/vote/commands/ArenaStatsCommand.class b/Practice/target/classes/me/devkevin/practice/match/vote/commands/ArenaStatsCommand.class new file mode 100644 index 0000000..c080246 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/vote/commands/ArenaStatsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/match/vote/commands/RateCommand.class b/Practice/target/classes/me/devkevin/practice/match/vote/commands/RateCommand.class new file mode 100644 index 0000000..5bb23ee Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/match/vote/commands/RateCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/npc/NpcListener.class b/Practice/target/classes/me/devkevin/practice/npc/NpcListener.class new file mode 100644 index 0000000..e79afee Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/npc/NpcListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/options/ProfileOptions.class b/Practice/target/classes/me/devkevin/practice/options/ProfileOptions.class new file mode 100644 index 0000000..5ccdd1c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/options/ProfileOptions.class differ diff --git a/Practice/target/classes/me/devkevin/practice/options/command/OptionsCommand.class b/Practice/target/classes/me/devkevin/practice/options/command/OptionsCommand.class new file mode 100644 index 0000000..73e5e31 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/options/command/OptionsCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/options/item/ProfileOptionsItem.class b/Practice/target/classes/me/devkevin/practice/options/item/ProfileOptionsItem.class new file mode 100644 index 0000000..d150d68 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/options/item/ProfileOptionsItem.class differ diff --git a/Practice/target/classes/me/devkevin/practice/options/item/ProfileOptionsItemState.class b/Practice/target/classes/me/devkevin/practice/options/item/ProfileOptionsItemState.class new file mode 100644 index 0000000..7c0fd0b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/options/item/ProfileOptionsItemState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/options/listener/ProfileOptionsListeners.class b/Practice/target/classes/me/devkevin/practice/options/listener/ProfileOptionsListeners.class new file mode 100644 index 0000000..92b1df1 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/options/listener/ProfileOptionsListeners.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/PanelCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/PanelCommand.class new file mode 100644 index 0000000..dcf80f6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/PanelCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/DebugBlockedCommands.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/DebugBlockedCommands.class new file mode 100644 index 0000000..abb81db Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/DebugBlockedCommands.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceChunkSaveCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceChunkSaveCommand.class new file mode 100644 index 0000000..da75917 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceChunkSaveCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceGlobalEloUpdateCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceGlobalEloUpdateCommand.class new file mode 100644 index 0000000..c4b537d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceGlobalEloUpdateCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceQueueCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceQueueCommand.class new file mode 100644 index 0000000..8f3fc9d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/ForceQueueCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GlobalEloDebugCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GlobalEloDebugCommand.class new file mode 100644 index 0000000..06d50e4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GlobalEloDebugCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GlobalQueueDebugCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GlobalQueueDebugCommand.class new file mode 100644 index 0000000..cd683a0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GlobalQueueDebugCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GotoEventCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GotoEventCommand.class new file mode 100644 index 0000000..65fe4cc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/GotoEventCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/PartyDebugCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/PartyDebugCommand.class new file mode 100644 index 0000000..e152ca0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/PartyDebugCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/PlayerStateDebugCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/PlayerStateDebugCommand.class new file mode 100644 index 0000000..bc1f087 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/PlayerStateDebugCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand$1.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand$1.class new file mode 100644 index 0000000..3812987 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand$2.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand$2.class new file mode 100644 index 0000000..2561695 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand.class new file mode 100644 index 0000000..45c4987 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SafeStopCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SetMatchesPlayedCommand.class b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SetMatchesPlayedCommand.class new file mode 100644 index 0000000..8463ce8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/commands/impl/SetMatchesPlayedCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/panel/menu/PanelMenu.class b/Practice/target/classes/me/devkevin/practice/panel/menu/PanelMenu.class new file mode 100644 index 0000000..546943b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/panel/menu/PanelMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/Party$PartyTask.class b/Practice/target/classes/me/devkevin/practice/party/Party$PartyTask.class new file mode 100644 index 0000000..64295ee Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/Party$PartyTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/Party.class b/Practice/target/classes/me/devkevin/practice/party/Party.class new file mode 100644 index 0000000..2fbcd23 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/Party.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyAcceptCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyAcceptCommand.class new file mode 100644 index 0000000..f6e37af Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyAcceptCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyCreateCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyCreateCommand.class new file mode 100644 index 0000000..cf66740 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyCreateCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyHelpCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyHelpCommand.class new file mode 100644 index 0000000..e7eecce Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyHelpCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyInfoCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyInfoCommand.class new file mode 100644 index 0000000..d82e287 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyInfoCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyInviteCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyInviteCommand.class new file mode 100644 index 0000000..30ea176 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyInviteCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyJoinCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyJoinCommand.class new file mode 100644 index 0000000..5c3a569 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyJoinCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyKickCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyKickCommand.class new file mode 100644 index 0000000..d2940e9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyKickCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyLeaveCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyLeaveCommand.class new file mode 100644 index 0000000..13ba8a2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyLeaveCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyLimitCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyLimitCommand.class new file mode 100644 index 0000000..f116669 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyLimitCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyListCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyListCommand.class new file mode 100644 index 0000000..9417284 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyListCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyOpenCommand$1.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyOpenCommand$1.class new file mode 100644 index 0000000..d88ba7c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyOpenCommand$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/command/PartyOpenCommand.class b/Practice/target/classes/me/devkevin/practice/party/command/PartyOpenCommand.class new file mode 100644 index 0000000..5422698 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/command/PartyOpenCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager$1.class b/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager$1.class new file mode 100644 index 0000000..0bdf809 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager$2.class b/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager$2.class new file mode 100644 index 0000000..a8c390d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager.class b/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager.class new file mode 100644 index 0000000..8dd582c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/manager/PartyManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$1.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$1.class new file mode 100644 index 0000000..1940456 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$10.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$10.class new file mode 100644 index 0000000..1ec6038 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$10.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$11.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$11.class new file mode 100644 index 0000000..5004710 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$11.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$12.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$12.class new file mode 100644 index 0000000..e924d08 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$12.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$13.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$13.class new file mode 100644 index 0000000..0c0f82d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$13.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$14.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$14.class new file mode 100644 index 0000000..2edba2e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$14.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$2.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$2.class new file mode 100644 index 0000000..94ab4c1 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$3.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$3.class new file mode 100644 index 0000000..4a2ea6e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$4.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$4.class new file mode 100644 index 0000000..f4cbf7b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$5.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$5.class new file mode 100644 index 0000000..dbe3e93 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$5.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$6.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$6.class new file mode 100644 index 0000000..da5d8c3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$6.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$7.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$7.class new file mode 100644 index 0000000..0d62823 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$7.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$8.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$8.class new file mode 100644 index 0000000..c34443e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$8.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$9.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$9.class new file mode 100644 index 0000000..16a6067 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu$9.class differ diff --git a/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu.class b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu.class new file mode 100644 index 0000000..3e0372b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/party/menu/PartyMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/Profile.class b/Practice/target/classes/me/devkevin/practice/profile/Profile.class new file mode 100644 index 0000000..d10cf79 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/Profile.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/hotbar/HotbarItem.class b/Practice/target/classes/me/devkevin/practice/profile/hotbar/HotbarItem.class new file mode 100644 index 0000000..6a10c85 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/hotbar/HotbarItem.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/InventoryListener.class b/Practice/target/classes/me/devkevin/practice/profile/listener/InventoryListener.class new file mode 100644 index 0000000..71a7cd8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/InventoryListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/MovementListener.class b/Practice/target/classes/me/devkevin/practice/profile/listener/MovementListener.class new file mode 100644 index 0000000..20546a2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/MovementListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/PlayerTabCompleteFix.class b/Practice/target/classes/me/devkevin/practice/profile/listener/PlayerTabCompleteFix.class new file mode 100644 index 0000000..64b7499 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/PlayerTabCompleteFix.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/ProfileListener$1.class b/Practice/target/classes/me/devkevin/practice/profile/listener/ProfileListener$1.class new file mode 100644 index 0000000..41cd5c5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/ProfileListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/ProfileListener.class b/Practice/target/classes/me/devkevin/practice/profile/listener/ProfileListener.class new file mode 100644 index 0000000..006ba83 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/ProfileListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/TabCompleteListener.class b/Practice/target/classes/me/devkevin/practice/profile/listener/TabCompleteListener.class new file mode 100644 index 0000000..57b6d80 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/TabCompleteListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/WorldListener$1.class b/Practice/target/classes/me/devkevin/practice/profile/listener/WorldListener$1.class new file mode 100644 index 0000000..48fbf76 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/WorldListener$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/listener/WorldListener.class b/Practice/target/classes/me/devkevin/practice/profile/listener/WorldListener.class new file mode 100644 index 0000000..d31d54a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/listener/WorldListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/manager/ProfileManager.class b/Practice/target/classes/me/devkevin/practice/profile/manager/ProfileManager.class new file mode 100644 index 0000000..a47fba8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/manager/ProfileManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/menu/StatsMenu$1.class b/Practice/target/classes/me/devkevin/practice/profile/menu/StatsMenu$1.class new file mode 100644 index 0000000..b84ce33 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/menu/StatsMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/menu/StatsMenu.class b/Practice/target/classes/me/devkevin/practice/profile/menu/StatsMenu.class new file mode 100644 index 0000000..af733fe Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/menu/StatsMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/state/ProfileState.class b/Practice/target/classes/me/devkevin/practice/profile/state/ProfileState.class new file mode 100644 index 0000000..888fd2f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/state/ProfileState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/task/DataLoaderWorkerRunnable.class b/Practice/target/classes/me/devkevin/practice/profile/task/DataLoaderWorkerRunnable.class new file mode 100644 index 0000000..cee98ba Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/task/DataLoaderWorkerRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/task/ExpBarTask.class b/Practice/target/classes/me/devkevin/practice/profile/task/ExpBarTask.class new file mode 100644 index 0000000..aea42a2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/task/ExpBarTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/task/ProfileSaveDataTask.class b/Practice/target/classes/me/devkevin/practice/profile/task/ProfileSaveDataTask.class new file mode 100644 index 0000000..1d9ddfe Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/task/ProfileSaveDataTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/profile/task/SpawnPlayerVisibilityRunnable.class b/Practice/target/classes/me/devkevin/practice/profile/task/SpawnPlayerVisibilityRunnable.class new file mode 100644 index 0000000..54393db Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/profile/task/SpawnPlayerVisibilityRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/Queue.class b/Practice/target/classes/me/devkevin/practice/queue/Queue.class new file mode 100644 index 0000000..ca8e491 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/Queue.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/QueueEntry.class b/Practice/target/classes/me/devkevin/practice/queue/QueueEntry.class new file mode 100644 index 0000000..3965c71 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/QueueEntry.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/QueueType.class b/Practice/target/classes/me/devkevin/practice/queue/QueueType.class new file mode 100644 index 0000000..9ea4181 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/QueueType.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$1.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$1.class new file mode 100644 index 0000000..7df3403 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$2.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$2.class new file mode 100644 index 0000000..bc6c881 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$3.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$3.class new file mode 100644 index 0000000..5339dc5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$4.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$4.class new file mode 100644 index 0000000..8bc6241 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$5.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$5.class new file mode 100644 index 0000000..b8bebe9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu$5.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu.class new file mode 100644 index 0000000..14f4d89 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PartyQueueJoinMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$1.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$1.class new file mode 100644 index 0000000..fe49dc4 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$2.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$2.class new file mode 100644 index 0000000..36be259 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$3.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$3.class new file mode 100644 index 0000000..bc1511e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$4.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$4.class new file mode 100644 index 0000000..56296fa Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$4.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$5.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$5.class new file mode 100644 index 0000000..2ec4d84 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$5.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$6.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$6.class new file mode 100644 index 0000000..c1a91ce Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$6.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$7.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$7.class new file mode 100644 index 0000000..a90fde5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu$7.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu.class b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu.class new file mode 100644 index 0000000..a5acd46 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/party/PlayJoinMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$1.class b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$1.class new file mode 100644 index 0000000..5d07ecc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$2.class b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$2.class new file mode 100644 index 0000000..3b2c499 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$3.class b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$3.class new file mode 100644 index 0000000..10f7008 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu.class b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu.class new file mode 100644 index 0000000..8a61a69 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/queue/menu/play/QueueMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/staff/StaffMode.class b/Practice/target/classes/me/devkevin/practice/staff/StaffMode.class new file mode 100644 index 0000000..d71e94c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/staff/StaffMode.class differ diff --git a/Practice/target/classes/me/devkevin/practice/titles/Titles.class b/Practice/target/classes/me/devkevin/practice/titles/Titles.class new file mode 100644 index 0000000..45e1460 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/titles/Titles.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/Tournament.class b/Practice/target/classes/me/devkevin/practice/tournament/Tournament.class new file mode 100644 index 0000000..ae9bf03 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/Tournament.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/command/TournamentCommand.class b/Practice/target/classes/me/devkevin/practice/tournament/command/TournamentCommand.class new file mode 100644 index 0000000..5760799 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/command/TournamentCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$1.class b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$1.class new file mode 100644 index 0000000..b8e4183 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$2.class b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$2.class new file mode 100644 index 0000000..7e4015a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$3$1.class b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$3$1.class new file mode 100644 index 0000000..7899e88 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$3$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$3.class b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$3.class new file mode 100644 index 0000000..ce36b2b Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu$3.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu.class b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu.class new file mode 100644 index 0000000..a6c893a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/host/TournamentHostMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/manager/TournamentManager$1.class b/Practice/target/classes/me/devkevin/practice/tournament/manager/TournamentManager$1.class new file mode 100644 index 0000000..28ae8a8 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/manager/TournamentManager$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/manager/TournamentManager.class b/Practice/target/classes/me/devkevin/practice/tournament/manager/TournamentManager.class new file mode 100644 index 0000000..e63aebc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/manager/TournamentManager.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/runnable/TournamentRunnable.class b/Practice/target/classes/me/devkevin/practice/tournament/runnable/TournamentRunnable.class new file mode 100644 index 0000000..0b9c073 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/runnable/TournamentRunnable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/state/TournamentState.class b/Practice/target/classes/me/devkevin/practice/tournament/state/TournamentState.class new file mode 100644 index 0000000..33a8206 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/state/TournamentState.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/team/MatchRandomTeam.class b/Practice/target/classes/me/devkevin/practice/tournament/team/MatchRandomTeam.class new file mode 100644 index 0000000..9c48ba7 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/team/MatchRandomTeam.class differ diff --git a/Practice/target/classes/me/devkevin/practice/tournament/team/TournamentTeam.class b/Practice/target/classes/me/devkevin/practice/tournament/team/TournamentTeam.class new file mode 100644 index 0000000..8ede09e Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/tournament/team/TournamentTeam.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Animation.class b/Practice/target/classes/me/devkevin/practice/util/Animation.class new file mode 100644 index 0000000..b0c2316 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Animation.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/BlockUtil.class b/Practice/target/classes/me/devkevin/practice/util/BlockUtil.class new file mode 100644 index 0000000..08bbf58 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/BlockUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/BukkitReflection.class b/Practice/target/classes/me/devkevin/practice/util/BukkitReflection.class new file mode 100644 index 0000000..c6caf2a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/BukkitReflection.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ByteBufUtils.class b/Practice/target/classes/me/devkevin/practice/util/ByteBufUtils.class new file mode 100644 index 0000000..6cb53cf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ByteBufUtils.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ChatComponentBuilder.class b/Practice/target/classes/me/devkevin/practice/util/ChatComponentBuilder.class new file mode 100644 index 0000000..fec6503 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ChatComponentBuilder.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Circle.class b/Practice/target/classes/me/devkevin/practice/util/Circle.class new file mode 100644 index 0000000..9522add Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Circle.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Clickable.class b/Practice/target/classes/me/devkevin/practice/util/Clickable.class new file mode 100644 index 0000000..60b8825 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Clickable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Color.class b/Practice/target/classes/me/devkevin/practice/util/Color.class new file mode 100644 index 0000000..3d85f7c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Color.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter$1.class b/Practice/target/classes/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter$1.class new file mode 100644 index 0000000..ddade37 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter.class b/Practice/target/classes/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter.class new file mode 100644 index 0000000..d3291b9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ConfigurationSerializableTypeAdapter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Cooldown.class b/Practice/target/classes/me/devkevin/practice/util/Cooldown.class new file mode 100644 index 0000000..304be66 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Cooldown.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats$1.class b/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats$1.class new file mode 100644 index 0000000..d71535f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats$2.class b/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats$2.class new file mode 100644 index 0000000..6c890e5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats.class b/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats.class new file mode 100644 index 0000000..f6cb1b6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/DateTimeFormats.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/DateUtil.class b/Practice/target/classes/me/devkevin/practice/util/DateUtil.class new file mode 100644 index 0000000..8c15d01 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/DateUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/EffectUtils.class b/Practice/target/classes/me/devkevin/practice/util/EffectUtils.class new file mode 100644 index 0000000..7a0486d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/EffectUtils.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/EntityUtils.class b/Practice/target/classes/me/devkevin/practice/util/EntityUtils.class new file mode 100644 index 0000000..b188a26 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/EntityUtils.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$1.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$1.class new file mode 100644 index 0000000..c7a4375 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$DateGsonAdapter.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$DateGsonAdapter.class new file mode 100644 index 0000000..0ca1daf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$DateGsonAdapter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ExposeExclusion.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ExposeExclusion.class new file mode 100644 index 0000000..7412771 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ExposeExclusion.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$Ignore.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$Ignore.class new file mode 100644 index 0000000..0a333c3 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$Ignore.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ItemStackGsonAdapter$1.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ItemStackGsonAdapter$1.class new file mode 100644 index 0000000..4a950da Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ItemStackGsonAdapter$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ItemStackGsonAdapter.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ItemStackGsonAdapter.class new file mode 100644 index 0000000..dc2e20d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$ItemStackGsonAdapter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$LocationGsonAdapter$1.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$LocationGsonAdapter$1.class new file mode 100644 index 0000000..c815ecb Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$LocationGsonAdapter$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$LocationGsonAdapter.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$LocationGsonAdapter.class new file mode 100644 index 0000000..b71ad45 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$LocationGsonAdapter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$NewItemStackAdapter.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$NewItemStackAdapter.class new file mode 100644 index 0000000..c7734d0 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$NewItemStackAdapter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$PotionEffectGsonAdapter$1.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$PotionEffectGsonAdapter$1.class new file mode 100644 index 0000000..d7a4a2d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$PotionEffectGsonAdapter$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory$PotionEffectGsonAdapter.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$PotionEffectGsonAdapter.class new file mode 100644 index 0000000..9dfb8bd Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory$PotionEffectGsonAdapter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/GsonFactory.class b/Practice/target/classes/me/devkevin/practice/util/GsonFactory.class new file mode 100644 index 0000000..b564960 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/GsonFactory.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/InventoryUtil.class b/Practice/target/classes/me/devkevin/practice/util/InventoryUtil.class new file mode 100644 index 0000000..347063a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/InventoryUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ItemBuilder.class b/Practice/target/classes/me/devkevin/practice/util/ItemBuilder.class new file mode 100644 index 0000000..0141201 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ItemBuilder.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ItemMaker.class b/Practice/target/classes/me/devkevin/practice/util/ItemMaker.class new file mode 100644 index 0000000..6a8a979 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ItemMaker.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ItemStackUtil.class b/Practice/target/classes/me/devkevin/practice/util/ItemStackUtil.class new file mode 100644 index 0000000..1018e5f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ItemStackUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ItemUtil$1.class b/Practice/target/classes/me/devkevin/practice/util/ItemUtil$1.class new file mode 100644 index 0000000..61fa063 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ItemUtil$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ItemUtil$ReloreType.class b/Practice/target/classes/me/devkevin/practice/util/ItemUtil$ReloreType.class new file mode 100644 index 0000000..7994885 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ItemUtil$ReloreType.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ItemUtil.class b/Practice/target/classes/me/devkevin/practice/util/ItemUtil.class new file mode 100644 index 0000000..d412e34 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ItemUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/MathUtil.class b/Practice/target/classes/me/devkevin/practice/util/MathUtil.class new file mode 100644 index 0000000..cb345cd Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/MathUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/NPCUtil$1.class b/Practice/target/classes/me/devkevin/practice/util/NPCUtil$1.class new file mode 100644 index 0000000..260d112 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/NPCUtil$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/NPCUtil.class b/Practice/target/classes/me/devkevin/practice/util/NPCUtil.class new file mode 100644 index 0000000..7dda925 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/NPCUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/PacketUtils.class b/Practice/target/classes/me/devkevin/practice/util/PacketUtils.class new file mode 100644 index 0000000..ab9b6ee Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/PacketUtils.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Pair.class b/Practice/target/classes/me/devkevin/practice/util/Pair.class new file mode 100644 index 0000000..8415c23 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Pair.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/PlayerUtil$1.class b/Practice/target/classes/me/devkevin/practice/util/PlayerUtil$1.class new file mode 100644 index 0000000..1e16c28 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/PlayerUtil$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/PlayerUtil.class b/Practice/target/classes/me/devkevin/practice/util/PlayerUtil.class new file mode 100644 index 0000000..55c2ea5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/PlayerUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ProgressBar.class b/Practice/target/classes/me/devkevin/practice/util/ProgressBar.class new file mode 100644 index 0000000..c5ffd67 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ProgressBar.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/ReflectionUtils.class b/Practice/target/classes/me/devkevin/practice/util/ReflectionUtils.class new file mode 100644 index 0000000..a345a0a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/ReflectionUtils.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TaskUtil.class b/Practice/target/classes/me/devkevin/practice/util/TaskUtil.class new file mode 100644 index 0000000..569e796 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TaskUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Tasks$Callable.class b/Practice/target/classes/me/devkevin/practice/util/Tasks$Callable.class new file mode 100644 index 0000000..629623c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Tasks$Callable.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/Tasks.class b/Practice/target/classes/me/devkevin/practice/util/Tasks.class new file mode 100644 index 0000000..473a8fd Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/Tasks.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TeamUtil.class b/Practice/target/classes/me/devkevin/practice/util/TeamUtil.class new file mode 100644 index 0000000..074ef78 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TeamUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TimeUtil.class b/Practice/target/classes/me/devkevin/practice/util/TimeUtil.class new file mode 100644 index 0000000..94a3e7c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TimeUtil.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TimeUtils.class b/Practice/target/classes/me/devkevin/practice/util/TimeUtils.class new file mode 100644 index 0000000..15e2c17 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TimeUtils.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TimerHashMap.class b/Practice/target/classes/me/devkevin/practice/util/TimerHashMap.class new file mode 100644 index 0000000..4b527be Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TimerHashMap.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TimerHashMapHandler.class b/Practice/target/classes/me/devkevin/practice/util/TimerHashMapHandler.class new file mode 100644 index 0000000..76ee8fc Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TimerHashMapHandler.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TtlHandler.class b/Practice/target/classes/me/devkevin/practice/util/TtlHandler.class new file mode 100644 index 0000000..a4cee50 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TtlHandler.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/TtlHashMap.class b/Practice/target/classes/me/devkevin/practice/util/TtlHashMap.class new file mode 100644 index 0000000..35d90af Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/TtlHashMap.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/command/BukkitCommand.class b/Practice/target/classes/me/devkevin/practice/util/command/BukkitCommand.class new file mode 100644 index 0000000..4ee2be9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/command/BukkitCommand.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/command/BukkitCompleter.class b/Practice/target/classes/me/devkevin/practice/util/command/BukkitCompleter.class new file mode 100644 index 0000000..0edef16 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/command/BukkitCompleter.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/command/Command.class b/Practice/target/classes/me/devkevin/practice/util/command/Command.class new file mode 100644 index 0000000..96e0231 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/command/Command.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/command/CommandArgs.class b/Practice/target/classes/me/devkevin/practice/util/command/CommandArgs.class new file mode 100644 index 0000000..d9e5e00 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/command/CommandArgs.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/command/CommandFramework.class b/Practice/target/classes/me/devkevin/practice/util/command/CommandFramework.class new file mode 100644 index 0000000..3a1cba9 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/command/CommandFramework.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/command/Completer.class b/Practice/target/classes/me/devkevin/practice/util/command/Completer.class new file mode 100644 index 0000000..fffd27a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/command/Completer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$1.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$1.class new file mode 100644 index 0000000..783ab7c Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$2.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$2.class new file mode 100644 index 0000000..76e6129 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$2.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$AbstractClickableItem.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$AbstractClickableItem.class new file mode 100644 index 0000000..8174155 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$AbstractClickableItem.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$ClickableItem.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$ClickableItem.class new file mode 100644 index 0000000..c98a39a Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$ClickableItem.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$EmptyClickableItem.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$EmptyClickableItem.class new file mode 100644 index 0000000..3611832 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$EmptyClickableItem.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$Inventory2D.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$Inventory2D.class new file mode 100644 index 0000000..f968d19 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$Inventory2D.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$InventoryUIHolder.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$InventoryUIHolder.class new file mode 100644 index 0000000..eaa6806 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI$InventoryUIHolder.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI.class b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI.class new file mode 100644 index 0000000..c17960d Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/InventoryUI.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/inventory/UIListener.class b/Practice/target/classes/me/devkevin/practice/util/inventory/UIListener.class new file mode 100644 index 0000000..3dd7287 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/inventory/UIListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/json/JsonChain.class b/Practice/target/classes/me/devkevin/practice/util/json/JsonChain.class new file mode 100644 index 0000000..ac7bd20 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/json/JsonChain.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/json/JsonDeserializer.class b/Practice/target/classes/me/devkevin/practice/util/json/JsonDeserializer.class new file mode 100644 index 0000000..e3631ae Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/json/JsonDeserializer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/json/JsonSerializer.class b/Practice/target/classes/me/devkevin/practice/util/json/JsonSerializer.class new file mode 100644 index 0000000..8a2ab21 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/json/JsonSerializer.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/Button$1.class b/Practice/target/classes/me/devkevin/practice/util/menu/Button$1.class new file mode 100644 index 0000000..5dbfb7f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/Button$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/Button.class b/Practice/target/classes/me/devkevin/practice/util/menu/Button.class new file mode 100644 index 0000000..c4392f2 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/Button.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/ButtonListener.class b/Practice/target/classes/me/devkevin/practice/util/menu/ButtonListener.class new file mode 100644 index 0000000..9fa6598 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/ButtonListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/Menu$1.class b/Practice/target/classes/me/devkevin/practice/util/menu/Menu$1.class new file mode 100644 index 0000000..9e4dd00 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/Menu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/Menu.class b/Practice/target/classes/me/devkevin/practice/util/menu/Menu.class new file mode 100644 index 0000000..aff000f Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/Menu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/MenuListener.class b/Practice/target/classes/me/devkevin/practice/util/menu/MenuListener.class new file mode 100644 index 0000000..34985cf Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/MenuListener.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/MenuUpdateTask.class b/Practice/target/classes/me/devkevin/practice/util/menu/MenuUpdateTask.class new file mode 100644 index 0000000..9ac9555 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/MenuUpdateTask.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/buttons/BackButton.class b/Practice/target/classes/me/devkevin/practice/util/menu/buttons/BackButton.class new file mode 100644 index 0000000..ff42ec5 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/buttons/BackButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/buttons/DisplayButton.class b/Practice/target/classes/me/devkevin/practice/util/menu/buttons/DisplayButton.class new file mode 100644 index 0000000..56ccc95 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/buttons/DisplayButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/pagination/JumpToPageButton.class b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/JumpToPageButton.class new file mode 100644 index 0000000..f9b7545 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/JumpToPageButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PageButton.class b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PageButton.class new file mode 100644 index 0000000..9bd37a6 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PageButton.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PaginatedMenu$1.class b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PaginatedMenu$1.class new file mode 100644 index 0000000..fbd3b88 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PaginatedMenu$1.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PaginatedMenu.class b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PaginatedMenu.class new file mode 100644 index 0000000..6935f53 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/PaginatedMenu.class differ diff --git a/Practice/target/classes/me/devkevin/practice/util/menu/pagination/ViewAllPagesMenu.class b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/ViewAllPagesMenu.class new file mode 100644 index 0000000..55cd652 Binary files /dev/null and b/Practice/target/classes/me/devkevin/practice/util/menu/pagination/ViewAllPagesMenu.class differ diff --git a/Practice/target/classes/plugin.yml b/Practice/target/classes/plugin.yml new file mode 100644 index 0000000..019682a --- /dev/null +++ b/Practice/target/classes/plugin.yml @@ -0,0 +1,7 @@ +main: me.devkevin.practice.Practice +name: Practice +author: DevKevin +version: 10.3 +depend: + - LandCore + - HolographicDisplays \ No newline at end of file diff --git a/Practice/target/maven-archiver/pom.properties b/Practice/target/maven-archiver/pom.properties new file mode 100644 index 0000000..3e87a86 --- /dev/null +++ b/Practice/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Thu May 25 01:23:34 BST 2023 +version=dev-SNAPSHOT +groupId=me.devkevin.practice +artifactId=Practice diff --git a/Practice/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/Practice/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..e045aad --- /dev/null +++ b/Practice/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,456 @@ +me\devkevin\practice\match\team\KillableTeam.class +me\devkevin\practice\events\commands\HostEventCommand.class +me\devkevin\practice\match\listener\entity\EnderpearlListener.class +me\devkevin\practice\events\sumo\SumoEvent$WaterCheckTask.class +me\devkevin\practice\events\tntrun\TntRunCountdownTask.class +me\devkevin\practice\match\listener\entity\PotionMatchListener.class +me\devkevin\practice\panel\commands\impl\ForceGlobalEloUpdateCommand.class +me\devkevin\practice\events\sumo\SumoPlayer$SumoState.class +me\devkevin\practice\util\GsonFactory$LocationGsonAdapter.class +me\devkevin\practice\util\menu\Button$1.class +me\devkevin\practice\hcf\listener\HCFMatchListener$1.class +me\devkevin\practice\util\menu\MenuUpdateTask.class +me\devkevin\practice\panel\commands\impl\GlobalEloDebugCommand.class +me\devkevin\practice\tournament\Tournament.class +me\devkevin\practice\util\ItemUtil.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$4.class +me\devkevin\practice\elo\EloCalculator.class +me\devkevin\practice\party\command\PartyListCommand.class +me\devkevin\practice\party\command\PartyAcceptCommand.class +com\bizarrealex\aether\Aether$1.class +me\devkevin\practice\command\general\SetEditorSpawnCommand.class +me\devkevin\practice\events\sumo\SumoEvent$SumoFightTask.class +me\devkevin\practice\command\time\SunsetCommand.class +me\devkevin\practice\events\tntrun\TntRunPlayer$TntRunState.class +me\devkevin\practice\match\matches\OngoingMatchesMenu.class +me\devkevin\practice\profile\listener\ProfileListener$1.class +me\devkevin\practice\util\NPCUtil.class +me\devkevin\practice\kit\command\KitsCommand.class +me\devkevin\practice\tournament\runnable\TournamentRunnable.class +me\devkevin\practice\events\oitc\OITCPlayer.class +me\devkevin\practice\events\commands\JoinEventCommand.class +me\devkevin\practice\kit\menu\KitEditorMenu$6$3.class +me\devkevin\practice\arena\chunk\reset\impl\VanillaNekoChunkReset.class +me\devkevin\practice\leaderboard\menu\LeaderboardsMenu.class +me\devkevin\practice\kit\menu\KitEditorMenu$9.class +me\devkevin\practice\arena\chunk\manager\ChunkRestorationManager.class +me\devkevin\practice\Practice.class +me\devkevin\practice\kit\PlayerKit.class +me\devkevin\practice\profile\task\SpawnPlayerVisibilityRunnable.class +me\devkevin\practice\queue\QueueType.class +me\devkevin\practice\match\MatchRequest.class +me\devkevin\practice\kit\menu\KitEditorMenu$2.class +me\devkevin\practice\leaderboard\Leaderboard.class +me\devkevin\practice\events\menu\HostMenu$3.class +me\devkevin\practice\match\timer\TimerManager.class +me\devkevin\practice\arena\manager\ArenaManager.class +me\devkevin\practice\party\menu\PartyMenu$5.class +me\devkevin\practice\party\command\PartyHelpCommand.class +me\devkevin\practice\match\vote\commands\ArenaStatsCommand.class +me\devkevin\practice\party\command\PartyOpenCommand$1.class +me\devkevin\practice\match\duel\menu\DuelMenu$3.class +me\devkevin\practice\util\NPCUtil$1.class +me\devkevin\practice\util\InventoryUtil.class +me\devkevin\practice\titles\Titles.class +me\devkevin\practice\util\DateTimeFormats$1.class +me\devkevin\practice\util\GsonFactory$DateGsonAdapter.class +me\devkevin\practice\board\PracticeBoard.class +me\devkevin\practice\events\tnttag\TNTTagCountdownTask.class +me\devkevin\practice\PracticeLang.class +me\devkevin\practice\kit\menu\KitEditorMenu$4.class +me\devkevin\practice\util\BlockUtil.class +me\devkevin\practice\events\menu\HostMenu$6.class +me\devkevin\practice\party\manager\PartyManager$2.class +me\devkevin\practice\events\EventCountdownTask.class +me\devkevin\practice\util\inventory\InventoryUI$1.class +me\devkevin\practice\events\sumo\SumoEvent.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$2.class +me\devkevin\practice\kit\menu\KitEditorMenu$7.class +me\devkevin\practice\match\timer\PlayerTimer.class +me\devkevin\practice\party\menu\PartyMenu$14.class +me\devkevin\practice\hcf\classes\Archer.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$2.class +me\devkevin\practice\panel\commands\impl\SafeStopCommand$1.class +me\devkevin\practice\match\event\impl\MatchEndEvent.class +me\devkevin\practice\panel\commands\impl\ForceQueueCommand.class +me\devkevin\practice\profile\listener\InventoryListener.class +me\devkevin\practice\util\command\Command.class +me\devkevin\practice\match\menu\MatchDetailSnapshot.class +me\devkevin\practice\util\Color.class +me\devkevin\practice\match\duel\command\DuelCommand.class +me\devkevin\practice\util\inventory\InventoryUI$Inventory2D.class +me\devkevin\practice\file\ConfigFile.class +me\devkevin\practice\events\EventPlayer.class +me\devkevin\practice\command\stats\SetStatsCommand.class +me\devkevin\practice\events\event\EventStartEvent.class +me\devkevin\practice\kit\menu\KitEditorMenu$6$1.class +me\devkevin\practice\util\Pair.class +me\devkevin\practice\party\menu\PartyMenu$7.class +me\devkevin\practice\command\general\SetSpawnCommand.class +me\devkevin\practice\util\inventory\InventoryUI$AbstractClickableItem.class +me\devkevin\practice\kit\menu\KitEditorMenu.class +me\devkevin\practice\match\vote\VoteManager.class +me\devkevin\practice\events\oitc\OITCPlayer$OITCState.class +me\devkevin\practice\leaderboard\menu\button\WinstreakButton.class +me\devkevin\practice\match\listener\entity\SwordBlockDetector.class +me\devkevin\practice\events\tntrun\TntRunEvent$RemoveBlocksTask.class +me\devkevin\practice\match\listener\game\MatchEndListener.class +me\devkevin\practice\match\listener\entity\EnderpearlListener$1.class +me\devkevin\practice\util\TimeUtil.class +me\devkevin\practice\panel\commands\impl\ForceChunkSaveCommand.class +me\devkevin\practice\util\Animation.class +me\devkevin\practice\match\timer\TimerCooldown$1.class +me\devkevin\practice\queue\menu\play\QueueMenu$2.class +me\devkevin\practice\tournament\team\TournamentTeam.class +me\devkevin\practice\match\event\MatchEvent.class +me\devkevin\practice\match\MatchState.class +me\devkevin\practice\kit\command\KitManageCommand.class +me\devkevin\practice\util\command\CommandFramework.class +me\devkevin\practice\util\command\BukkitCompleter.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$4.class +me\devkevin\practice\arena\chunk\data\NekoChunk.class +me\devkevin\practice\profile\listener\TabCompleteListener.class +me\devkevin\practice\party\command\PartyJoinCommand.class +me\devkevin\practice\leaderboard\menu\button\WinstreakKitButton.class +me\devkevin\practice\general\GeneralSettingMenu$2.class +me\devkevin\practice\profile\menu\StatsMenu.class +me\devkevin\practice\util\TimeUtils.class +me\devkevin\practice\match\task\RematchRunnable.class +me\devkevin\practice\match\history\menu\MatchHistoryMenu.class +me\devkevin\practice\tournament\manager\TournamentManager$1.class +me\devkevin\practice\profile\task\DataLoaderWorkerRunnable.class +me\devkevin\practice\hcf\event\ArmorClassEquipEvent.class +me\devkevin\practice\panel\commands\impl\SetMatchesPlayedCommand.class +me\devkevin\practice\events\menu\HostMenu.class +me\devkevin\practice\events\sumo\SumoCountdownTask.class +me\devkevin\practice\kit\menu\KitEditorMenu$2$2.class +me\devkevin\practice\events\tntrun\TntRunEvent$PlayerPosition.class +me\devkevin\practice\events\lms\LMSPlayer.class +me\devkevin\practice\profile\task\ProfileSaveDataTask.class +me\devkevin\practice\events\tnttag\TNTTagEvent.class +me\devkevin\practice\events\menu\HostMenu$5.class +me\devkevin\practice\events\tntrun\TntRunEvent$1.class +me\devkevin\practice\match\listener\game\MatchStartListener.class +me\devkevin\practice\tournament\host\TournamentHostMenu$3$1.class +me\devkevin\practice\arena\generate\DuplicateArenaRunnable.class +me\devkevin\practice\events\commands\LeaveEventCommand.class +me\devkevin\practice\hcf\listener\HCFClassListener$2.class +me\devkevin\practice\match\Match.class +me\devkevin\practice\util\GsonFactory$Ignore.class +me\devkevin\practice\panel\commands\impl\PartyDebugCommand.class +me\devkevin\practice\util\TtlHashMap.class +me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu$5.class +me\devkevin\practice\kit\manager\EditorManager.class +me\devkevin\practice\match\task\MatchLogicTask$1.class +me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu$1.class +me\devkevin\practice\panel\commands\impl\GlobalQueueDebugCommand.class +me\devkevin\practice\match\menu\MatchDetailsMenu.class +me\devkevin\practice\leaderboard\menu\button\PlayerStatsButton.class +me\devkevin\practice\panel\menu\PanelMenu.class +me\devkevin\practice\party\Party.class +me\devkevin\practice\events\menu\HostMenu$4.class +me\devkevin\practice\match\MatchTeam.class +me\devkevin\practice\leaderboard\npc\NPCRunnable.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$6.class +me\devkevin\practice\util\menu\pagination\PaginatedMenu.class +me\devkevin\practice\util\GsonFactory$1.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$7.class +me\devkevin\practice\arena\menu\buttons\ArenaGenerateButton.class +me\devkevin\practice\hcf\listener\HCFClassListener$1.class +me\devkevin\practice\util\BukkitReflection.class +me\devkevin\practice\util\ItemStackUtil.class +me\devkevin\practice\util\inventory\InventoryUI.class +me\devkevin\practice\match\event\impl\MatchStartEvent.class +me\devkevin\practice\match\duel\command\AcceptCommand.class +me\devkevin\practice\general\GeneralSettingMenu.class +me\devkevin\practice\panel\commands\impl\SafeStopCommand.class +me\devkevin\practice\panel\commands\impl\SafeStopCommand$2.class +me\devkevin\practice\util\menu\Button.class +me\devkevin\practice\arena\menu\buttons\ArenaCopyButton$1.class +me\devkevin\practice\arena\chunk\data\NekoChunkData.class +me\devkevin\practice\kit\menu\KitEditorMenu$2$3.class +me\devkevin\practice\elo\EloUtil.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$8.class +me\devkevin\practice\match\duel\menu\DuelMenu$1.class +me\devkevin\practice\party\command\PartyKickCommand.class +me\devkevin\practice\util\DateUtil.class +me\devkevin\practice\util\PlayerUtil$1.class +me\devkevin\practice\events\EventState.class +me\devkevin\practice\command\PracticeCommand.class +com\bizarrealex\aether\scoreboard\BoardEntry.class +com\bizarrealex\aether\scoreboard\cooldown\BoardFormat.class +me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu$4.class +me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu$2.class +com\bizarrealex\aether\AetherOptions.class +me\devkevin\practice\kit\menu\KitEditorMenu$2$1.class +me\devkevin\practice\events\lms\LMSEvent.class +me\devkevin\practice\match\listener\entity\SwordBlockDetector$1.class +me\devkevin\practice\file\Config.class +me\devkevin\practice\match\timer\event\TimerStartEvent.class +me\devkevin\practice\kit\manager\KitManager.class +me\devkevin\practice\util\ItemBuilder.class +me\devkevin\practice\command\staff\CancelMatchCommand.class +me\devkevin\practice\elo\KFactor.class +me\devkevin\practice\arena\cuboid\CuboidDirection.class +me\devkevin\practice\events\menu\HostMenu$1.class +me\devkevin\practice\match\history\MatchHistoryInvSnap.class +me\devkevin\practice\party\Party$PartyTask.class +club\inverted\chatcolor\CC.class +me\devkevin\practice\match\listener\entity\BowBoostingListener.class +me\devkevin\practice\hcf\event\ArmorClassUnequipEvent.class +com\bizarrealex\aether\event\BoardCreateEvent.class +me\devkevin\practice\arena\menu\ArenaGenerationMenu.class +me\devkevin\practice\events\manager\EventManager.class +me\devkevin\practice\leaderboard\menu\button\WinstreakGlobalButton.class +me\devkevin\practice\match\menu\MatchDetailsMenu$1.class +me\devkevin\practice\util\GsonFactory$PotionEffectGsonAdapter.class +me\devkevin\practice\hcf\HCFClass.class +me\devkevin\practice\events\sumo\SumoPlayer.class +me\devkevin\practice\arena\chunk\manager\ChunkManager$1.class +me\devkevin\practice\options\item\ProfileOptionsItemState.class +me\devkevin\practice\tournament\state\TournamentState.class +me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu$3.class +me\devkevin\practice\command\general\ResetLeaderboardsCommand.class +me\devkevin\practice\arena\generate\ArenaCommandRunnable$1.class +me\devkevin\practice\events\tnttag\TNTTagPlayer.class +me\devkevin\practice\arena\cuboid\Cuboid.class +me\devkevin\practice\party\command\PartyOpenCommand.class +me\devkevin\practice\events\lms\LMSEvent$LMSGameTask.class +me\devkevin\practice\party\menu\PartyMenu$6.class +me\devkevin\practice\profile\Profile.class +me\devkevin\practice\match\listener\entity\EntityListener.class +me\devkevin\practice\util\TimerHashMap.class +me\devkevin\practice\party\command\PartyLimitCommand.class +me\devkevin\practice\tournament\team\MatchRandomTeam.class +me\devkevin\practice\arena\cuboid\CuboidBlockIterator.class +me\devkevin\practice\match\vote\Vote.class +me\devkevin\practice\events\tnttag\TNTTagEvent$TNTTagGameTask.class +me\devkevin\practice\util\menu\MenuListener.class +me\devkevin\practice\panel\commands\impl\GotoEventCommand.class +me\devkevin\practice\leaderboard\menu\button\LeaderboardButton.class +me\devkevin\practice\match\timer\event\TimerExtendEvent.class +me\devkevin\practice\util\GsonFactory.class +me\devkevin\practice\arena\chunk\manager\ChunkManager.class +me\devkevin\practice\util\inventory\InventoryUI$InventoryUIHolder.class +me\devkevin\practice\events\PracticeEvent.class +me\devkevin\practice\leaderboard\menu\WinstreaksMenu.class +me\devkevin\practice\match\duel\menu\DuelMenu$2.class +me\devkevin\practice\events\menu\HostMenu$2.class +me\devkevin\practice\party\menu\PartyMenu$10.class +me\devkevin\practice\events\oitc\OITCEvent.class +me\devkevin\practice\kit\menu\KitEditorMenu$8.class +me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu.class +me\devkevin\practice\command\general\FlyCommand.class +me\devkevin\practice\party\command\PartyInviteCommand.class +com\bizarrealex\aether\Aether.class +me\devkevin\practice\hcf\effects\EffectData.class +me\devkevin\practice\command\time\NightCommand.class +me\devkevin\practice\util\menu\pagination\ViewAllPagesMenu.class +me\devkevin\practice\util\TtlHandler.class +me\devkevin\practice\command\general\StatsCommand.class +me\devkevin\practice\PracticeCache.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$3.class +me\devkevin\practice\util\ByteBufUtils.class +me\devkevin\practice\match\listener\entity\MatchRodListener.class +me\devkevin\practice\match\history\command\MatchHistoryCommand.class +me\devkevin\practice\events\tnttag\TNTTagEvent$TNTTagTask.class +me\devkevin\practice\util\EntityUtils.class +me\devkevin\practice\hcf\effects\EffectRestorer.class +me\devkevin\practice\util\ProgressBar.class +me\devkevin\practice\util\GsonFactory$NewItemStackAdapter.class +me\devkevin\practice\kit\menu\KitEditorMenu$6$2.class +me\devkevin\practice\queue\Queue.class +me\devkevin\practice\party\command\PartyLeaveCommand.class +me\devkevin\practice\kit\menu\KitEditorMenu$3.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu.class +me\devkevin\practice\panel\commands\PanelCommand.class +me\devkevin\practice\util\PacketUtils.class +me\devkevin\practice\hcf\classes\Bard.class +me\devkevin\practice\arena\generate\ArenaCopyRemovalRunnable.class +me\devkevin\practice\events\lms\LMSCountdownTask.class +me\devkevin\practice\profile\hotbar\HotbarItem.class +me\devkevin\practice\util\command\Completer.class +me\devkevin\practice\arena\menu\ArenaManagerMenu.class +me\devkevin\practice\queue\menu\play\QueueMenu.class +me\devkevin\practice\util\json\JsonChain.class +me\devkevin\practice\util\TimerHashMapHandler.class +me\devkevin\practice\kit\Kit.class +me\devkevin\practice\options\listener\ProfileOptionsListeners.class +me\devkevin\practice\match\duel\menu\DuelMenu$4.class +me\devkevin\practice\util\GsonFactory$ExposeExclusion.class +me\devkevin\practice\util\inventory\InventoryUI$ClickableItem.class +me\devkevin\practice\util\GsonFactory$PotionEffectGsonAdapter$1.class +me\devkevin\practice\util\TeamUtil.class +me\devkevin\practice\util\DateTimeFormats.class +me\devkevin\practice\match\freeze\FreezeListener.class +me\devkevin\practice\tournament\host\TournamentHostMenu$3.class +me\devkevin\practice\events\oitc\OITCEvent$1.class +me\devkevin\practice\match\timer\event\TimerClearEvent.class +me\devkevin\practice\match\history\MatchLocatedData.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$5.class +me\devkevin\practice\util\json\JsonSerializer.class +me\devkevin\practice\arena\cuboid\CuboidDirection$1.class +me\devkevin\practice\profile\listener\WorldListener$1.class +me\devkevin\practice\tournament\command\TournamentCommand.class +me\devkevin\practice\party\menu\PartyMenu$8.class +me\devkevin\practice\kit\menu\KitEditorMenu$6.class +me\devkevin\practice\queue\menu\play\QueueMenu$1.class +me\devkevin\practice\options\item\ProfileOptionsItem.class +me\devkevin\practice\party\command\PartyCreateCommand.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$3.class +me\devkevin\practice\match\listener\time\MatchDurationLimitListener.class +me\devkevin\practice\staff\StaffMode.class +com\bizarrealex\aether\scoreboard\cooldown\BoardCooldown.class +me\devkevin\practice\match\duel\menu\DuelMenu.class +me\devkevin\practice\party\menu\PartyMenu.class +me\devkevin\practice\util\Cooldown.class +me\devkevin\practice\events\oitc\OITCEvent$SortComparator.class +me\devkevin\practice\util\menu\ButtonListener.class +me\devkevin\practice\general\GeneralSettingMenu$3.class +me\devkevin\practice\util\Tasks.class +me\devkevin\practice\events\tntrun\TntRunPlayer.class +me\devkevin\practice\util\TaskUtil.class +me\devkevin\practice\party\manager\PartyManager$1.class +me\devkevin\practice\util\menu\pagination\JumpToPageButton.class +me\devkevin\practice\party\menu\PartyMenu$9.class +me\devkevin\practice\events\menu\HostMenu$7.class +me\devkevin\practice\events\tntrun\TntRunEvent.class +me\devkevin\practice\util\menu\pagination\PageButton.class +me\devkevin\practice\util\command\BukkitCommand.class +me\devkevin\practice\command\requeue\PlayAgainCommand.class +me\devkevin\practice\util\ItemUtil$1.class +me\devkevin\practice\hcf\classes\Archer$TaggedTask.class +me\devkevin\practice\util\PlayerUtil.class +me\devkevin\practice\match\timer\event\TimerExpireEvent.class +me\devkevin\practice\util\GsonFactory$ItemStackGsonAdapter.class +me\devkevin\practice\util\Tasks$Callable.class +me\devkevin\practice\tournament\host\TournamentHostMenu.class +me\devkevin\practice\util\GsonFactory$LocationGsonAdapter$1.class +me\devkevin\practice\match\history\MatchHistoryInvSnap$1.class +me\devkevin\practice\panel\commands\impl\DebugBlockedCommands.class +me\devkevin\practice\arena\generate\DuplicateArenaRunnable$1.class +me\devkevin\practice\events\commands\HostCommand.class +me\devkevin\practice\events\oitc\OITCEvent$OITCGameTask.class +me\devkevin\practice\hcf\manager\HCFManager.class +me\devkevin\practice\match\timer\event\TimerPauseEvent.class +me\devkevin\practice\match\timer\Timer.class +me\devkevin\practice\util\menu\Menu.class +me\devkevin\practice\events\oitc\OITCCountdownTask.class +me\devkevin\practice\tournament\host\TournamentHostMenu$2.class +me\devkevin\practice\match\task\NewRoundRunnable.class +me\devkevin\practice\hcf\menu\ClassSelectionMenu.class +me\devkevin\practice\options\ProfileOptions.class +me\devkevin\practice\events\lms\LMSPlayer$LMSState.class +me\devkevin\practice\general\GeneralSettingMenu$1.class +me\devkevin\practice\events\commands\EventManagerCommand.class +me\devkevin\practice\arena\chunk\listener\ArenaPlayerChunkLimiter.class +me\devkevin\practice\party\menu\PartyMenu$3.class +me\devkevin\practice\arena\generate\ArenaCommandRunnable.class +me\devkevin\practice\kit\menu\KitEditorMenu$5.class +me\devkevin\practice\util\inventory\InventoryUI$EmptyClickableItem.class +me\devkevin\practice\util\DateTimeFormats$2.class +me\devkevin\practice\arena\menu\buttons\ArenaButton$1.class +me\devkevin\practice\util\Clickable.class +me\devkevin\practice\match\listener\entity\EntityListener$1.class +me\devkevin\practice\queue\menu\play\QueueMenu$3.class +me\devkevin\practice\util\inventory\InventoryUI$2.class +me\devkevin\practice\util\EffectUtils.class +me\devkevin\practice\arena\chunk\restoration\impl\PracticeChunkRestoration.class +me\devkevin\practice\util\MathUtil.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$1.class +me\devkevin\practice\hcf\listener\HCFClassListener.class +me\devkevin\practice\panel\commands\impl\PlayerStateDebugCommand.class +me\devkevin\practice\util\menu\pagination\PaginatedMenu$1.class +me\devkevin\practice\party\menu\PartyMenu$13.class +me\devkevin\practice\data\PracticeDatabase.class +me\devkevin\practice\leaderboard\hologram\HologramManager.class +me\devkevin\practice\command\staff\StaffModeCommand.class +me\devkevin\practice\util\ConfigurationSerializableTypeAdapter$1.class +me\devkevin\practice\arena\cuboid\CuboidLocationIterator.class +me\devkevin\practice\events\tntrun\TntRunEvent$TNTRunGameTask.class +me\devkevin\practice\match\task\MatchResetRunnable.class +me\devkevin\practice\arena\chunk\restoration\IChunkRestoration.class +me\devkevin\practice\hcf\listener\HCFMatchListener.class +me\devkevin\practice\command\time\DayCommand.class +me\devkevin\practice\match\timer\impl\EnderpearlTimer.class +me\devkevin\practice\hcf\kit\HCFKit.class +me\devkevin\practice\match\menu\command\InvCommand.class +me\devkevin\practice\arena\cuboid\Cuboid$1.class +me\devkevin\practice\events\event\BaseEvent.class +me\devkevin\practice\hcf\effects\BardData.class +me\devkevin\practice\party\menu\PartyMenu$12.class +me\devkevin\practice\util\ItemMaker.class +me\devkevin\practice\arena\generate\BlockPlaceRunnable.class +me\devkevin\practice\leaderboard\LeaderboardManager.class +me\devkevin\practice\location\CustomLocation.class +me\devkevin\practice\leaderboard\menu\button\KitStatsButton.class +me\devkevin\practice\profile\menu\StatsMenu$1.class +me\devkevin\practice\util\ChatComponentBuilder.class +me\devkevin\practice\command\stats\ResetStatsCommand.class +me\devkevin\practice\tournament\host\TournamentHostMenu$1.class +me\devkevin\practice\command\general\SetEventSpawnCommand.class +me\devkevin\practice\hcf\classes\Bard$1.class +me\devkevin\practice\kit\npc\EditorNPC.class +me\devkevin\practice\util\inventory\UIListener.class +me\devkevin\practice\events\oitc\OITCEvent$RespawnTask.class +com\bizarrealex\aether\scoreboard\BoardAdapter.class +me\devkevin\practice\profile\state\ProfileState.class +me\devkevin\practice\kit\listener\KitEditorError32Listener.class +me\devkevin\practice\party\menu\PartyMenu$11.class +me\devkevin\practice\arena\Arena.class +me\devkevin\practice\arena\menu\buttons\ArenaCopyButton.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$5.class +me\devkevin\practice\match\matches\buttons\RefreshButton.class +me\devkevin\practice\match\spec\SpectateCommand.class +me\devkevin\practice\util\menu\buttons\DisplayButton.class +me\devkevin\practice\profile\task\ExpBarTask.class +me\devkevin\practice\arena\chunk\reset\INekoChunkReset.class +me\devkevin\practice\match\matches\buttons\OngoingMatchButton.class +me\devkevin\practice\match\vote\commands\RateCommand.class +me\devkevin\practice\util\command\CommandArgs.class +me\devkevin\practice\profile\listener\WorldListener.class +me\devkevin\practice\arena\menu\ArenaCopyMenu.class +me\devkevin\practice\tournament\manager\TournamentManager.class +me\devkevin\practice\util\GsonFactory$ItemStackGsonAdapter$1.class +me\devkevin\practice\match\listener\time\MatchDurationLimitListener$1.class +me\devkevin\practice\profile\listener\PlayerTabCompleteFix.class +me\devkevin\practice\command\staff\OngoingMatchesCommand.class +me\devkevin\practice\events\tnttag\TNTTagPlayer$TNTTagState.class +me\devkevin\practice\kit\menu\KitEditorMenu$1.class +me\devkevin\practice\party\menu\PartyMenu$4.class +me\devkevin\practice\profile\manager\ProfileManager.class +me\devkevin\practice\hcf\menu\button\ClassSelectionButton.class +me\devkevin\practice\arena\menu\buttons\ArenaButton.class +com\bizarrealex\aether\scoreboard\Board.class +me\devkevin\practice\match\task\MatchLogicTask.class +me\devkevin\practice\arena\command\ArenaChunkCommands.class +me\devkevin\practice\party\menu\PartyMenu$1.class +me\devkevin\practice\util\ReflectionUtils.class +me\devkevin\practice\util\ConfigurationSerializableTypeAdapter.class +me\devkevin\practice\party\manager\PartyManager.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$7.class +me\devkevin\practice\arena\standalone\StandaloneArena.class +me\devkevin\practice\arena\command\ArenaCommand.class +me\devkevin\practice\handler\MovementHandler.class +me\devkevin\practice\match\timer\TimerCooldown.class +me\devkevin\practice\match\manager\MatchManager.class +me\devkevin\practice\util\ItemUtil$ReloreType.class +me\devkevin\practice\npc\NpcListener.class +me\devkevin\practice\util\json\JsonDeserializer.class +me\devkevin\practice\events\tntrun\TntRunEvent$VoidCheckTask.class +me\devkevin\practice\party\menu\PartyMenu$2.class +me\devkevin\practice\util\menu\buttons\BackButton.class +me\devkevin\practice\queue\QueueEntry.class +me\devkevin\practice\location\manager\CustomLocationManager.class +me\devkevin\practice\profile\listener\MovementListener.class +me\devkevin\practice\profile\listener\ProfileListener.class +me\devkevin\practice\command\staff\FollowCommand.class +me\devkevin\practice\util\Circle.class +me\devkevin\practice\util\menu\Menu$1.class +club\inverted\chatcolor\CC$1.class +me\devkevin\practice\match\history\menu\button\MatchHistoryButton.class +me\devkevin\practice\options\command\OptionsCommand.class +me\devkevin\practice\chat\ChatType.class +me\devkevin\practice\party\command\PartyInfoCommand.class +me\devkevin\practice\queue\menu\party\PlayJoinMenu$6.class +me\devkevin\practice\leaderboard\menu\button\LeaderboardGlobalButton.class diff --git a/Practice/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/Practice/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..77db284 --- /dev/null +++ b/Practice/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,308 @@ +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\EventState.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\PracticeEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\task\MatchLogicTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\GotoEventCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\PlayerUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\menu\MatchDetailsMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\cuboid\CuboidDirection.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Tasks.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\inventory\UIListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\manager\ChunkRestorationManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TaskUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\event\MatchEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\command\KitManageCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\Practice.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\generate\ArenaCommandRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\menu\ArenaManagerMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\chat\ChatType.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\PartyDebugCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\pagination\PageButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\scoreboard\BoardAdapter.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TeamUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\task\ExpBarTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\npc\EditorNPC.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\PlayerTimer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\Button.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Circle.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\tnttag\TNTTagPlayer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TimerHashMap.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\PracticeCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\menu\ArenaCopyMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\EffectUtils.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\state\ProfileState.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\AetherOptions.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\oitc\OITCEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\options\ProfileOptions.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\task\SpawnPlayerVisibilityRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\task\RematchRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\event\ArmorClassUnequipEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\listener\TabCompleteListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\PracticeLang.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\location\CustomLocation.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\WinstreakGlobalButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\game\MatchStartListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\menu\KitEditorMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\commands\EventManagerCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\WinstreaksMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\entity\PotionMatchListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyInviteCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\event\impl\MatchStartEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\manager\ChunkManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\matches\buttons\OngoingMatchButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\task\NewRoundRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\event\EventStartEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\data\PracticeDatabase.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\EventPlayer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\history\menu\button\MatchHistoryButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\Leaderboard.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\LeaderboardManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\manager\ArenaManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyInfoCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\impl\EnderpearlTimer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\task\DataLoaderWorkerRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\file\Config.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\host\TournamentHostMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\classes\Archer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\effects\BardData.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\ForceChunkSaveCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\listener\HCFMatchListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\scoreboard\BoardEntry.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyLimitCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ItemUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\listener\KitEditorError32Listener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\event\TimerClearEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\npc\NpcListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\menu\buttons\ArenaGenerateButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\general\SetEditorSpawnCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ItemMaker.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\generate\BlockPlaceRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\matches\buttons\RefreshButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\entity\EntityListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\ButtonListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\Match.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\Kit.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\options\item\ProfileOptionsItem.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\listener\PlayerTabCompleteFix.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ChatComponentBuilder.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\menu\ArenaGenerationMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\MathUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TimerHashMapHandler.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\restoration\IChunkRestoration.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\event\TimerExtendEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\Arena.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\file\ConfigFile.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\SafeStopCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\sumo\SumoEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TimeUtils.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\time\SunsetCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\queue\menu\party\PartyQueueJoinMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\classes\Bard.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\game\MatchEndListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\queue\menu\play\QueueMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\buttons\BackButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\history\command\MatchHistoryCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\entity\BowBoostingListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\Profile.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\event\BoardCreateEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\oitc\OITCCountdownTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\options\command\OptionsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TtlHashMap.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\WinstreakKitButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\elo\EloUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\general\SetEventSpawnCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\board\TablistProvider.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\vote\VoteManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\hologram\HologramManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyOpenCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ItemStackUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TimeUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\Tournament.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\Menu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\GlobalEloDebugCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\commands\HostEventCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\general\FlyCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\LeaderboardButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\hotbar\HotbarItem.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\team\TournamentTeam.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\command\ArenaChunkCommands.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\MatchRequest.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\commands\LeaveEventCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\generate\DuplicateArenaRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\entity\SwordBlockDetector.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\BlockUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\lms\LMSEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\commands\JoinEventCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\handler\MovementHandler.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\json\JsonChain.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\GlobalQueueDebugCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\elo\KFactor.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\npc\NPCRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\manager\MatchManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\Party.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\manager\EditorManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyHelpCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\history\MatchLocatedData.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\command\CommandArgs.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\entity\MatchRodListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\menu\button\ClassSelectionButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\manager\PartyManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\generate\ArenaCopyRemovalRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ProgressBar.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\PracticeCache.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\InventoryUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\staff\CancelMatchCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\listener\HCFClassListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\BukkitReflection.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\requeue\PlayAgainCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\pagination\PaginatedMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\staff\OngoingMatchesCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\DateUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ItemBuilder.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\options\item\ProfileOptionsItemState.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\board\PracticeBoard.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\duel\command\AcceptCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\tnttag\TNTTagEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\manager\KitManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\stats\SetStatsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\matches\OngoingMatchesMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\MatchTeam.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\listener\InventoryListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\menu\HostMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\staff\StaffModeCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\staff\StaffMode.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\command\ArenaCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\lms\LMSPlayer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\PlayerKit.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\event\TimerExpireEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\ForceGlobalEloUpdateCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\kit\command\KitsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\manager\ProfileManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\listener\ArenaPlayerChunkLimiter.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Animation.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\reset\INekoChunkReset.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\duel\menu\DuelMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\sumo\SumoPlayer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\HCFClass.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\queue\QueueType.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\listener\WorldListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\freeze\FreezeListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\general\GeneralSettingMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\club\inverted\chatcolor\CC.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\tntrun\TntRunEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\queue\Queue.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\WinstreakButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\state\TournamentState.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\tnttag\TNTTagCountdownTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\MenuListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\scoreboard\cooldown\BoardCooldown.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\location\manager\CustomLocationManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ConfigurationSerializableTypeAdapter.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\event\TimerStartEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\GsonFactory.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ByteBufUtils.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\kit\HCFKit.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\command\BukkitCompleter.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\EventCountdownTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Clickable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\duel\command\DuelCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\event\TimerPauseEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\effects\EffectRestorer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\vote\commands\RateCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\event\ArmorClassEquipEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\pagination\ViewAllPagesMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\listener\ProfileListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\entity\EnderpearlListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\PlayerStateDebugCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\TtlHandler.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\effects\EffectData.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\general\StatsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\command\TournamentCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\command\Completer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\manager\HCFManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\hcf\menu\ClassSelectionMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\menu\PanelMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyCreateCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyJoinCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\menu\buttons\ArenaButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\standalone\StandaloneArena.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\LeaderboardGlobalButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\json\JsonDeserializer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\reset\impl\VanillaNekoChunkReset.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\general\SetSpawnCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\time\NightCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyLeaveCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\PacketUtils.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\restoration\impl\PracticeChunkRestoration.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\manager\TournamentManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Pair.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\commands\HostCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\team\MatchRandomTeam.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\task\MatchResetRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\queue\menu\party\PlayJoinMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\MenuUpdateTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\KitStatsButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\command\Command.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\cuboid\CuboidBlockIterator.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\NPCUtil.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\lms\LMSCountdownTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\tntrun\TntRunPlayer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\task\ProfileSaveDataTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\ReflectionUtils.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\TimerManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\EntityUtils.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\command\CommandFramework.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\DebugBlockedCommands.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyListCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\elo\EloCalculator.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\Aether.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\listener\time\MatchDurationLimitListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\inventory\InventoryUI.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\scoreboard\Board.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\com\bizarrealex\aether\scoreboard\cooldown\BoardFormat.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\options\listener\ProfileOptionsListeners.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\menu\buttons\ArenaCopyButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\history\menu\MatchHistoryMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\data\NekoChunk.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyKickCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\spec\SpectateCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\pagination\JumpToPageButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\chunk\data\NekoChunkData.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\event\impl\MatchEndEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\staff\FollowCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\general\ResetLeaderboardsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\TimerCooldown.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Color.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\ForceQueueCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\timer\Timer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\Cooldown.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\vote\commands\ArenaStatsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\menu\StatsMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\profile\listener\MovementListener.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\DateTimeFormats.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\menu\command\InvCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\time\DayCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\menu\MatchDetailSnapshot.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\PanelCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\cuboid\Cuboid.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\tntrun\TntRunCountdownTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\menu\PartyMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\queue\QueueEntry.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\LeaderboardsMenu.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\command\stats\ResetStatsCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\tournament\runnable\TournamentRunnable.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\manager\EventManager.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\oitc\OITCPlayer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\sumo\SumoCountdownTask.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\party\command\PartyAcceptCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\command\BukkitCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\menu\buttons\DisplayButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\util\json\JsonSerializer.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\arena\cuboid\CuboidLocationIterator.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\vote\Vote.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\history\MatchHistoryInvSnap.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\panel\commands\impl\SetMatchesPlayedCommand.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\leaderboard\menu\button\PlayerStatsButton.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\MatchState.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\match\team\KillableTeam.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\events\event\BaseEvent.java +C:\Users\kevin\Desktop\Java Projects\Practice\src\main\java\me\devkevin\practice\titles\Titles.java diff --git a/Practice/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/Practice/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/Practice/target/original-Practice-dev-SNAPSHOT.jar b/Practice/target/original-Practice-dev-SNAPSHOT.jar new file mode 100644 index 0000000..f89694c Binary files /dev/null and b/Practice/target/original-Practice-dev-SNAPSHOT.jar differ diff --git a/WebAPI/.idea/.gitignore b/WebAPI/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/WebAPI/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/WebAPI/.idea/compiler.xml b/WebAPI/.idea/compiler.xml new file mode 100644 index 0000000..119f15d --- /dev/null +++ b/WebAPI/.idea/compiler.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebAPI/.idea/discord.xml b/WebAPI/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/WebAPI/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/WebAPI/.idea/encodings.xml b/WebAPI/.idea/encodings.xml new file mode 100644 index 0000000..63e9001 --- /dev/null +++ b/WebAPI/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/WebAPI/.idea/jarRepositories.xml b/WebAPI/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/WebAPI/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/WebAPI/.idea/misc.xml b/WebAPI/.idea/misc.xml new file mode 100644 index 0000000..4b661a5 --- /dev/null +++ b/WebAPI/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/WebAPI/.idea/uiDesigner.xml b/WebAPI/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/WebAPI/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebAPI/.mvn/wrapper/maven-wrapper.jar b/WebAPI/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..9cc84ea Binary files /dev/null and b/WebAPI/.mvn/wrapper/maven-wrapper.jar differ diff --git a/WebAPI/.mvn/wrapper/maven-wrapper.properties b/WebAPI/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..c315043 --- /dev/null +++ b/WebAPI/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1 @@ +distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.zip diff --git a/WebAPI/WebAPI.iml b/WebAPI/WebAPI.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/WebAPI/WebAPI.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/WebAPI/mvnw b/WebAPI/mvnw new file mode 100644 index 0000000..5bf251c --- /dev/null +++ b/WebAPI/mvnw @@ -0,0 +1,225 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Maven2 Start Up Batch script +# +# Required ENV vars: +# ------------------ +# JAVA_HOME - location of a JDK home dir +# +# Optional ENV vars +# ----------------- +# M2_HOME - location of maven2's installed home dir +# MAVEN_OPTS - parameters passed to the Java VM when running Maven +# e.g. to debug Maven itself, use +# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +# MAVEN_SKIP_RC - flag to disable loading of mavenrc files +# ---------------------------------------------------------------------------- + +if [ -z "$MAVEN_SKIP_RC" ] ; then + + if [ -f /etc/mavenrc ] ; then + . /etc/mavenrc + fi + + if [ -f "$HOME/.mavenrc" ] ; then + . "$HOME/.mavenrc" + fi + +fi + +# OS specific support. $var _must_ be set to either true or false. +cygwin=false; +darwin=false; +mingw=false +case "`uname`" in + CYGWIN*) cygwin=true ;; + MINGW*) mingw=true;; + Darwin*) darwin=true + # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home + # See https://developer.apple.com/library/mac/qa/qa1170/_index.html + if [ -z "$JAVA_HOME" ]; then + if [ -x "/usr/libexec/java_home" ]; then + export JAVA_HOME="`/usr/libexec/java_home`" + else + export JAVA_HOME="/Library/Java/Home" + fi + fi + ;; +esac + +if [ -z "$JAVA_HOME" ] ; then + if [ -r /etc/gentoo-release ] ; then + JAVA_HOME=`java-config --jre-home` + fi +fi + +if [ -z "$M2_HOME" ] ; then + ## resolve links - $0 may be a link to maven's home + PRG="$0" + + # need this for relative symlinks + while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG="`dirname "$PRG"`/$link" + fi + done + + saveddir=`pwd` + + M2_HOME=`dirname "$PRG"`/.. + + # make it fully qualified + M2_HOME=`cd "$M2_HOME" && pwd` + + cd "$saveddir" + # echo Using m2 at $M2_HOME +fi + +# For Cygwin, ensure paths are in UNIX format before anything is touched +if $cygwin ; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --unix "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --unix "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --unix "$CLASSPATH"` +fi + +# For Migwn, ensure paths are in UNIX format before anything is touched +if $mingw ; then + [ -n "$M2_HOME" ] && + M2_HOME="`(cd "$M2_HOME"; pwd)`" + [ -n "$JAVA_HOME" ] && + JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" + # TODO classpath? +fi + +if [ -z "$JAVA_HOME" ]; then + javaExecutable="`which javac`" + if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then + # readlink(1) is not available as standard on Solaris 10. + readLink=`which readlink` + if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then + if $darwin ; then + javaHome="`dirname \"$javaExecutable\"`" + javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" + else + javaExecutable="`readlink -f \"$javaExecutable\"`" + fi + javaHome="`dirname \"$javaExecutable\"`" + javaHome=`expr "$javaHome" : '\(.*\)/bin'` + JAVA_HOME="$javaHome" + export JAVA_HOME + fi + fi +fi + +if [ -z "$JAVACMD" ] ; then + if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + else + JAVACMD="`which java`" + fi +fi + +if [ ! -x "$JAVACMD" ] ; then + echo "Error: JAVA_HOME is not defined correctly." >&2 + echo " We cannot execute $JAVACMD" >&2 + exit 1 +fi + +if [ -z "$JAVA_HOME" ] ; then + echo "Warning: JAVA_HOME environment variable is not set." +fi + +CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher + +# traverses directory structure from process work directory to filesystem root +# first directory with .mvn subdirectory is considered project base directory +find_maven_basedir() { + + if [ -z "$1" ] + then + echo "Path not specified to find_maven_basedir" + return 1 + fi + + basedir="$1" + wdir="$1" + while [ "$wdir" != '/' ] ; do + if [ -d "$wdir"/.mvn ] ; then + basedir=$wdir + break + fi + # workaround for JBEAP-8937 (on Solaris 10/Sparc) + if [ -d "${wdir}" ]; then + wdir=`cd "$wdir/.."; pwd` + fi + # end of workaround + done + echo "${basedir}" +} + +# concatenates all lines of a file +concat_lines() { + if [ -f "$1" ]; then + echo "$(tr -s '\n' ' ' < "$1")" + fi +} + +BASE_DIR=`find_maven_basedir "$(pwd)"` +if [ -z "$BASE_DIR" ]; then + exit 1; +fi + +export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} +echo $MAVEN_PROJECTBASEDIR +MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" + +# For Cygwin, switch paths to Windows format before running java +if $cygwin; then + [ -n "$M2_HOME" ] && + M2_HOME=`cygpath --path --windows "$M2_HOME"` + [ -n "$JAVA_HOME" ] && + JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` + [ -n "$CLASSPATH" ] && + CLASSPATH=`cygpath --path --windows "$CLASSPATH"` + [ -n "$MAVEN_PROJECTBASEDIR" ] && + MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` +fi + +WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +exec "$JAVACMD" \ + $MAVEN_OPTS \ + -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ + "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ + ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" diff --git a/WebAPI/mvnw.cmd b/WebAPI/mvnw.cmd new file mode 100644 index 0000000..019bd74 --- /dev/null +++ b/WebAPI/mvnw.cmd @@ -0,0 +1,143 @@ +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Maven2 Start Up Batch script +@REM +@REM Required ENV vars: +@REM JAVA_HOME - location of a JDK home dir +@REM +@REM Optional ENV vars +@REM M2_HOME - location of maven2's installed home dir +@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands +@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending +@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven +@REM e.g. to debug Maven itself, use +@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 +@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files +@REM ---------------------------------------------------------------------------- + +@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' +@echo off +@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' +@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% + +@REM set %HOME% to equivalent of $HOME +if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") + +@REM Execute a user defined script before this one +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre +@REM check for pre script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" +if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" +:skipRcPre + +@setlocal + +set ERROR_CODE=0 + +@REM To isolate internal variables from possible post scripts, we use another setlocal +@setlocal + +@REM ==== START VALIDATION ==== +if not "%JAVA_HOME%" == "" goto OkJHome + +echo. +echo Error: JAVA_HOME not found in your environment. >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +:OkJHome +if exist "%JAVA_HOME%\bin\java.exe" goto init + +echo. +echo Error: JAVA_HOME is set to an invalid directory. >&2 +echo JAVA_HOME = "%JAVA_HOME%" >&2 +echo Please set the JAVA_HOME variable in your environment to match the >&2 +echo location of your Java installation. >&2 +echo. +goto error + +@REM ==== END VALIDATION ==== + +:init + +@REM Find the project base dir, i.e. the directory that contains the folder ".mvn". +@REM Fallback to current working directory if not found. + +set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% +IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir + +set EXEC_DIR=%CD% +set WDIR=%EXEC_DIR% +:findBaseDir +IF EXIST "%WDIR%"\.mvn goto baseDirFound +cd .. +IF "%WDIR%"=="%CD%" goto baseDirNotFound +set WDIR=%CD% +goto findBaseDir + +:baseDirFound +set MAVEN_PROJECTBASEDIR=%WDIR% +cd "%EXEC_DIR%" +goto endDetectBaseDir + +:baseDirNotFound +set MAVEN_PROJECTBASEDIR=%EXEC_DIR% +cd "%EXEC_DIR%" + +:endDetectBaseDir + +IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig + +@setlocal EnableExtensions EnableDelayedExpansion +for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a +@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% + +:endReadAdditionalConfig + +SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" + +set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" +set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain + +%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* +if ERRORLEVEL 1 goto error +goto end + +:error +set ERROR_CODE=1 + +:end +@endlocal & set ERROR_CODE=%ERROR_CODE% + +if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost +@REM check for post script, once with legacy .bat ending and once with .cmd ending +if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" +if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" +:skipRcPost + +@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' +if "%MAVEN_BATCH_PAUSE%" == "on" pause + +if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% + +exit /B %ERROR_CODE% diff --git a/WebAPI/pom.xml b/WebAPI/pom.xml new file mode 100644 index 0000000..6f825bf --- /dev/null +++ b/WebAPI/pom.xml @@ -0,0 +1,80 @@ + + + 4.0.0 + + me.devkevin + WebAPI + 0.0.1-SNAPSHOT + jar + + + org.springframework.boot + spring-boot-starter-parent + 1.5.8.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + mysql + mysql-connector-java + 5.1.6 + compile + + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + javax.persistence + persistence-api + 1.0.2 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + org.projectlombok + lombok + 1.16.18 + + + + com.google.code.gson + gson + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/WebAPI/src/main/java/me/devkevin/WebAPI.java b/WebAPI/src/main/java/me/devkevin/WebAPI.java new file mode 100644 index 0000000..0f3d584 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/WebAPI.java @@ -0,0 +1,22 @@ +package me.devkevin; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.web.support.SpringBootServletInitializer; +import org.springframework.context.annotation.ComponentScan; + + +/** + * Created by DevKevin + * Project: me.devkevin.WebAPI + * Date: 22/02/2022 @ 20:22 + */ +@SpringBootApplication +@EntityScan("me.devkevin.model") +@ComponentScan({"me.devkevin.repo", "me.devkevin.model", "me.devkevin.controller"}) +public class WebAPI extends SpringBootServletInitializer { + public static void main(String[] args) { + SpringApplication.run(WebAPI.class, args); + } +} diff --git a/WebAPI/src/main/java/me/devkevin/controller/MatchController.java b/WebAPI/src/main/java/me/devkevin/controller/MatchController.java new file mode 100644 index 0000000..c9bc7e5 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/controller/MatchController.java @@ -0,0 +1,80 @@ +package me.devkevin.controller; + +import me.devkevin.model.Inventory; +import me.devkevin.model.Match; +import me.devkevin.repo.InventoryRepository; +import me.devkevin.repo.MatchesRepository; +import me.devkevin.util.Constants; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 4:10 + */ +@RestController +@RequestMapping("/api/{key}/matches") +@SuppressWarnings("SpringAutowiredFieldsWarningInspection") +public class MatchController { + + @Autowired private InventoryRepository inventoryRepository; + @Autowired private MatchesRepository matchesRepository; + + @RequestMapping("/insert/inventory") + public ResponseEntity insertInventoryData(HttpServletRequest request, + @PathVariable("key") String key) { + if (!Constants.validServerKey(key)) { + return null; + } + + String inventoryA = request.getParameter("inventorty-a"); + String inventoryB = request.getParameter("inventorty-b"); + String matchId = request.getParameter("match-id"); + + Inventory inventory = new Inventory(); + inventory.setMatchId(matchId); + inventory.setWinnerInventory(inventoryA); + inventory.setLoserInventory(inventoryB); + + this.inventoryRepository.save(inventory); + + return Constants.SUCCESS_STRING; + } + + @RequestMapping("/insert/match") + public ResponseEntity insertMatchData(HttpServletRequest request, + @PathVariable("key") String key) { + if (!Constants.validServerKey(key)) { + return null; + } + + String id = request.getParameter("match-id"); + + int winner = Integer.parseInt(request.getParameter("winners")); + int loser = Integer.parseInt(request.getParameter("losers")); + + int winnerEloBefore = Integer.parseInt(request.getParameter("winner-elo-before")); + int loserEloBefore = Integer.parseInt(request.getParameter("loser-elo-before")); + + int winnerEloAfter = Integer.parseInt(request.getParameter("winner-elo-after")); + int loserEloAfter = Integer.parseInt(request.getParameter("loser-elo-after")); + + int inventory = Integer.parseInt(request.getParameter("inventory")); + + Match match = new Match(id, inventory, winner, loser, + winnerEloBefore, loserEloBefore, + winnerEloAfter, loserEloAfter); + + this.matchesRepository.save(match); + + return Constants.SUCCESS_STRING; + } + +} + diff --git a/WebAPI/src/main/java/me/devkevin/controller/PlayerController.java b/WebAPI/src/main/java/me/devkevin/controller/PlayerController.java new file mode 100644 index 0000000..efcde58 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/controller/PlayerController.java @@ -0,0 +1,290 @@ +package me.devkevin.controller; + +import com.google.gson.JsonObject; +import me.devkevin.model.Player; +import me.devkevin.model.Punishment; +import me.devkevin.repo.PlayerRepository; +import me.devkevin.repo.PunishmentRepository; +import me.devkevin.util.Constants; +import me.devkevin.util.PlayerUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.sql.Timestamp; +import java.util.List; +import java.util.UUID; + +@RestController +@RequestMapping("/api/{key}/player") +@SuppressWarnings("SpringAutowiredFieldsWarningInspection") +public class PlayerController { + + @Autowired + private PunishmentRepository punishmentRepository; + @Autowired + private PlayerRepository playerRepository; + + public static Player getPlayer(PlayerRepository playerRepository, UUID uuid) { + Player player = playerRepository.findFirstByUniqueId(uuid.toString()); + if (player == null) { + player = new Player(); + + player.setLastLogin(player.getLastLogin()); + player.setFirstLogin(new Timestamp(System.currentTimeMillis())); + player.setUniqueId(uuid.toString()); + player.setRank(""); + player.setName(player.getName()); + player.setIpAddress(player.getIpAddress()); + + playerRepository.save(player); + } + + return player; + } + + public static Player getPlayer(PlayerRepository playerRepository, String name) { + List players = playerRepository.findByName(name); + + if (players.size() > 0) { + for (Player player : players) { + if (player.getName().equalsIgnoreCase(name)) { + return player; + } + } + } + + return null; + } + + @RequestMapping("/from_name/{name}") + public Player getData(@PathVariable(name = "key") String key, + @PathVariable(name = "name") String name, + HttpServletRequest request) { + + if (!Constants.validServerKey(key)) { + return null; + } + + return getPlayer(this.playerRepository, name); + } + + @RequestMapping("/{uuid}") + public Player getData(@PathVariable(name = "key") String key, + @PathVariable(name = "uuid") UUID uuid, + HttpServletRequest request) { + if (!Constants.validServerKey(key)) { + return null; + } + + return this.getGlobalData(key, uuid, request); + } + + @RequestMapping("/{uuid}/global") + public Player getGlobalData(@PathVariable(name = "key") String key, + @PathVariable(name = "uuid") UUID uuid, + HttpServletRequest request) { + if (!Constants.validServerKey(key)) { + return null; + } + + String name = request.getParameter("name"); + String ip = request.getParameter("ip"); + + Player player = getPlayer(this.playerRepository, uuid); + boolean changesApplied = false; + if (player.getIpAddress() == null || ip != null && !player.getIpAddress().equals(ip)) { + player.setIpAddress(ip); + changesApplied = true; + } else if (player.getName() == null || name != null && !player.getName().equals(name)) { + player.setName(name); + changesApplied = true; + } + + if (changesApplied) { + this.playerRepository.save(player); + } + + return player; + } + + @RequestMapping("/{name}/ban-info") + public ResponseEntity getBanInfo(@PathVariable(name = "key") String key, + @PathVariable(name = "name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + JsonObject object = new JsonObject(); + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + object.addProperty("response", "player-not-found"); + return new ResponseEntity<>(object.toString(), HttpStatus.OK); + } + + object.addProperty("response", "success"); + + object.addProperty("name", player.getName()); + object.addProperty("muted", player.isMuted()); + object.addProperty("banned", player.isBanned()); + object.addProperty("ip-banned", player.isIpBanned()); + object.addProperty("blacklisted", player.isBlacklisted()); + object.addProperty("ban-time", player.getBanTime() != null ? player.getBanTime().getTime() : 0); + object.addProperty("mute-time", player.getMuteTime() != null ? player.getMuteTime().getTime() : 0); + + if (player.isMuted()) { + Punishment punishment = this.punishmentRepository + .findFirstByPlayerIdAndTypeContainingOrderByTimestampDesc( + player.getPlayerId(), "MUTE"); + // Punishment punishment = punishments.get(punishments.size() - 1); + + + object.addProperty("mute-reason", punishment.getReason()); + } + + if (player.isBanned()) { + Punishment punishment = this.punishmentRepository + .findFirstByPlayerIdAndTypeContainingOrderByTimestampDesc( + player.getPlayerId(), "%BAN%"); + // Punishment punishment = punishments.get(punishments.size() - 1); + + object.addProperty("ban-reason", punishment.getReason()); + } + + if (player.isBlacklisted()) { + Punishment punishment = this.punishmentRepository + .findFirstByPlayerIdAndTypeContainingOrderByTimestampDesc( + player.getPlayerId(), "%BLACKLIST%"); + // Punishment punishment = punishments.get(punishments.size() - 1); + + object.addProperty("ban-reason", punishment.getReason()); + } + + return new ResponseEntity<>(object.toString(), HttpStatus.OK); + } + + @RequestMapping("/{uuid}/ip-check/{ip}") + public ResponseEntity doIPCheck(@PathVariable("key") String key, + @PathVariable("ip") String ip) { + if (!Constants.validServerKey(key)) { + return null; + } + + List players = this.playerRepository.findByIpAddress(ip); + + for (Player player : players) { + if (player.isBanned() || player.isIpBanned() || player.isBlacklisted()) { + return new ResponseEntity<>(true, HttpStatus.OK); + } + } + + return new ResponseEntity<>(false, HttpStatus.OK); + } + + @RequestMapping("/{name}/update-rank") + public ResponseEntity updateRank(HttpServletRequest request, + @PathVariable("key") String key, + @PathVariable("name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + return Constants.PLAYER_NOT_FOUND_STRING; + } + + player.setRank(request.getParameter("rank")); + + this.playerRepository.save(player); + + return Constants.SUCCESS_STRING; + } + + @RequestMapping("/{name}/update/last_login") + public ResponseEntity updateLastJoin(HttpServletRequest request, + @PathVariable("key") String key, + @PathVariable("name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + return Constants.PLAYER_NOT_FOUND_STRING; + } + + player.setLastLogin(request.getParameter("last_login")); + + this.playerRepository.save(player); + + return Constants.SUCCESS_STRING; + } + + @RequestMapping("/{name}/update/ip") + public ResponseEntity updateIP(HttpServletRequest request, + @PathVariable("key") String key, + @PathVariable("name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + return Constants.PLAYER_NOT_FOUND_STRING; + } + + player.setIpAddress(request.getParameter("ip")); + + this.playerRepository.save(player); + + return Constants.SUCCESS_STRING; + } + + @RequestMapping("/{name}/update/country_code") + public ResponseEntity updateCountryCode(HttpServletRequest request, + @PathVariable("key") String key, + @PathVariable("name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + return Constants.PLAYER_NOT_FOUND_STRING; + } + + player.setCountryCode(request.getParameter("country_code")); + + this.playerRepository.save(player); + + + return Constants.SUCCESS_STRING; + } + + @RequestMapping("/{name}/update/country_name") + public ResponseEntity updateCountryName(HttpServletRequest request, + @PathVariable("key") String key, + @PathVariable("name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + return Constants.PLAYER_NOT_FOUND_STRING; + } + + player.setCountryName(request.getParameter("country_name")); + + this.playerRepository.save(player); + + + return Constants.SUCCESS_STRING; + } +} diff --git a/WebAPI/src/main/java/me/devkevin/controller/PracticeController.java b/WebAPI/src/main/java/me/devkevin/controller/PracticeController.java new file mode 100644 index 0000000..964ade3 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/controller/PracticeController.java @@ -0,0 +1,207 @@ +package me.devkevin.controller; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import me.devkevin.model.Player; +import me.devkevin.model.PracticeProfile; +import me.devkevin.repo.PlayerRepository; +import me.devkevin.repo.PracticeRepository; +import me.devkevin.util.Constants; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 3:32 + */ +@RestController +@RequestMapping("/api/{key}/practice") +public class PracticeController { + private final Map fields = new HashMap<>(); + + static { + // Run this first so whenever it caches reflection data + PracticeProfile practiceData = new PracticeProfile(); + + Field[] fields = practiceData.getClass().getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + + try { + if (field.getType() == boolean.class) { + field.set(practiceData, Boolean.valueOf("false")); + } else if (field.getType() == int.class) { + field.set(practiceData, Integer.valueOf("123")); + } else if (field.getType() == double.class) { + field.set(practiceData, Double.valueOf("123")); + } else if (field.getType() == String.class) { + field.set(practiceData, "xd"); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + + @Autowired private PracticeRepository practiceRepository; + @Autowired private PlayerRepository playerRepository; + @PersistenceContext private EntityManager entityManager; + + @RequestMapping("/{uuid}") + public ResponseEntity getData(@PathVariable(name = "key") String key, + @PathVariable(name = "uuid") UUID uuid) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerController.getPlayer(this.playerRepository, uuid); + PracticeProfile practiceData = this.practiceRepository.findFirstByPlayerId(player.getPlayerId()); + + if (practiceData == null) { + return null; + } + + return new ResponseEntity<>(practiceData, HttpStatus.OK); + } + + + @RequestMapping("/leaderboards/{ladder}") + public ResponseEntity getLeaderboards(@PathVariable(name = "key") String key, + @PathVariable(name = "ladder") String ladder) { + if (!Constants.validServerKey(key)) { + return null; + } + + String columnName = this.deserializeName(ladder + "Elo"); + + List list = entityManager + .createNativeQuery("SELECT * FROM practice_season_1_data ORDER BY ? DESC LIMIT 10", PracticeProfile.class) + .setParameter(1, columnName) + .getResultList(); + list.sort((o1, o2) -> { + try { + Field field = fields.computeIfAbsent(ladder + "Elo", name -> { + try { + Field practiceField = PracticeProfile.class.getDeclaredField(name); + practiceField.setAccessible(true); + return practiceField; + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + + return null; + }); + + return Integer.compare(field.getInt(o2), field.getInt(o1)); + } catch (Exception e) { + e.printStackTrace(); + } + + return 0; + }); + + JsonArray array = new JsonArray(); + list.forEach(data -> { + JsonObject object = new JsonObject(); + Field field = fields.get(ladder + "Elo"); + if (field == null) { + return; + } + + Player player = playerRepository.findFirstByPlayerId(data.getPlayerId()); + if (player == null) { + System.out.println("wtf " + data.getPlayerId()); + return; + } + + try { + object.addProperty("name", player.getName()); + object.addProperty("elo", field.getInt(data)); + } catch (IllegalAccessException e) { + e.printStackTrace(); + return; + } + + array.add(object); + }); + + return new ResponseEntity<>(array.toString(), HttpStatus.OK); + } + + @RequestMapping("/{id}/update") + public ResponseEntity updateData(HttpServletRequest request, + @PathVariable(name = "key") String key, + @PathVariable(name = "id") int id) { + if (!Constants.validServerKey(key)) { + return null; + } + + PracticeProfile practiceData = this.practiceRepository.findFirstByPlayerId(id); + + if (practiceData == null) { + practiceData = new PracticeProfile(); + practiceData.setPlayerId(id); + } + + Field[] fields = practiceData.getClass().getDeclaredFields(); + for (Field field : fields) { + field.setAccessible(true); + + String name = this.deserializeName(field.getName()); + + String param = request.getParameter(name); + if (param == null) { + continue; + } + + try { + if (field.getType() == boolean.class) { + field.set(practiceData, Boolean.valueOf(param)); + } else if (field.getType() == int.class) { + field.set(practiceData, Integer.valueOf(param)); + } else if (field.getType() == double.class) { + field.set(practiceData, Double.valueOf(param)); + } else if (field.getType() == String.class) { + field.set(practiceData, param); + } + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + + this.practiceRepository.save(practiceData); + + return new ResponseEntity<>(practiceData, HttpStatus.OK); + } + + private String deserializeName(String name) { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < name.length(); i++) { + char c = name.toCharArray()[i]; + + if (Character.isUpperCase(c)) { + sb.append("_"); + } + + sb.append(Character.toLowerCase(c)); + } + + return sb.toString(); + } + +} diff --git a/WebAPI/src/main/java/me/devkevin/controller/PunishController.java b/WebAPI/src/main/java/me/devkevin/controller/PunishController.java new file mode 100644 index 0000000..a7b7c54 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/controller/PunishController.java @@ -0,0 +1,196 @@ +package me.devkevin.controller; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import me.devkevin.model.Player; +import me.devkevin.model.Punishment; +import me.devkevin.repo.PlayerRepository; +import me.devkevin.repo.PunishmentRepository; +import me.devkevin.util.Constants; +import me.devkevin.util.PlayerUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletRequest; +import java.sql.Timestamp; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 4:05 + */ +@RestController +@RequestMapping("/api/{key}/punishments") +@SuppressWarnings("SpringAutowiredFieldsWarningInspection") +public class PunishController { + + @Autowired private PunishmentRepository punishmentRepository; + @Autowired private PlayerRepository playerRepository; + + @RequestMapping("/fetch_by_uuid/{uuid}") + public ResponseEntity fetchByUuid(@PathVariable("key") String key, + @PathVariable("uuid") String uuid) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = this.playerRepository.findFirstByUniqueId(uuid); + + if (player == null) { + return new ResponseEntity<>(new JsonArray().toString(), HttpStatus.OK); + } + + JsonArray punishmentsJson = new JsonArray(); + + for (Punishment punishment : this.punishmentRepository.findByPlayerId(player.getPlayerId())) { + JsonObject object = new JsonObject(); + object.addProperty("id", punishment.getId()); + object.addProperty("timestamp", punishment.getTimestamp().getTime()); + object.addProperty("expiry", punishment.getExpiry() == null ? 0 : punishment.getExpiry().getTime()); + object.addProperty("server_ip", punishment.getServerIp()); + object.addProperty("reason", punishment.getReason()); + object.addProperty("type", punishment.getType()); + object.addProperty("ip", punishment.getIp()); + object.addProperty("punisherId", punishment.getPunisherId()); + object.addProperty("playerId", punishment.getPlayerId()); + + punishmentsJson.add(object); + } + + return new ResponseEntity<>(punishmentsJson.toString(), HttpStatus.OK); + } + + @RequestMapping("/fetch/{name}") + public ResponseEntity fetchPunishments(@PathVariable("key") String key, + @PathVariable("name") String name) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player = PlayerUtil.getByName(name, this.playerRepository); + if (player == null) { + return new ResponseEntity<>(new JsonArray().toString(), HttpStatus.OK); + } + + Map playerCache = new HashMap<>(); + + JsonArray array = new JsonArray(); + + List punishments = this.punishmentRepository.findByPlayerId(player.getPlayerId()); + for (Punishment punishment : punishments) { + JsonObject object = new JsonObject(); + + Player player1 = playerCache.get(punishment.getPunisherId()); + if (player1 == null) { + player1 = this.playerRepository.findFirstByPlayerId(punishment.getPunisherId()); + + playerCache.put(punishment.getPunisherId(), player1); + } + + object.addProperty("punisher", player1 == null ? "CONSOLE" : player1.getName()); + object.addProperty("timestamp", punishment.getTimestamp().getTime()); + + Long time = punishment.getExpiry() != null ? punishment.getExpiry().getTime() : null; + if (punishment.getType().toUpperCase().startsWith("PERM") || + punishment.getType().toUpperCase().startsWith("UN")) { + time = null; + } + + object.addProperty("expiry", time); + object.addProperty("reason", punishment.getReason()); + object.addProperty("type", punishment.getType()); + + array.add(object); + } + + return new ResponseEntity<>(array.toString(), HttpStatus.OK); + } + + @RequestMapping("/punish") + public ResponseEntity onPunish(HttpServletRequest request, + @PathVariable("key") String key) { + if (!Constants.validServerKey(key)) { + return null; + } + + Player player; + + String name = request.getParameter("name"); + if (name != null) { + player = PlayerUtil.getByName(name, this.playerRepository); + } else { + player = this.playerRepository.findFirstByPlayerId(Integer.parseInt(request.getParameter("player-id"))); + } + + if (player == null) { + return Constants.PLAYER_NOT_FOUND_STRING; + } + + String ip = request.getParameter("ip-address"); + if (ip == null || ip.equals("UNKNOWN")) { + ip = player.getIpAddress(); + } + + String type = request.getParameter("type").toUpperCase(); + if ((type.equals("UNBAN") && !player.isBanned()) || (type.equals("UNBLACKLIST") && !player.isBlacklisted())) { + JsonObject object = new JsonObject(); + object.addProperty("response", "not-banned"); + return new ResponseEntity<>(object.toString(), HttpStatus.OK); + } else if (type.equals("UNMUTE") && !player.isMuted()) { + JsonObject object = new JsonObject(); + object.addProperty("response", "not-muted"); + return new ResponseEntity<>(object.toString(), HttpStatus.OK); + } + + String reason = request.getParameter("reason"); + String serverIp = request.getRemoteAddr(); + + String strExpiry = request.getParameter("expiry"); + + Timestamp expiry = null; + if (strExpiry != null && !strExpiry.equals("PERM")) { + expiry = Timestamp.valueOf(strExpiry); + } + + int punisher = Integer.parseInt(request.getParameter("punisher")); + + Punishment punishment = new Punishment(); + + punishment.setPlayerId(player.getPlayerId()); + punishment.setPunisherId(punisher); + punishment.setServerIp(serverIp); + punishment.setExpiry(expiry); + punishment.setReason(reason); + punishment.setType(type); + punishment.setIp(ip); + punishment.setTimestamp(new Timestamp(System.currentTimeMillis())); + + this.punishmentRepository.save(punishment); + + boolean unPunish = type.toUpperCase().startsWith("UN"); + if (type.toUpperCase().contains("BAN")) { + player.setBanned(!unPunish); + + player.setBanTime(expiry); + } else if (type.toUpperCase().contains("MUTE")) { + player.setMuted(!unPunish); + + player.setMuteTime(expiry); + } else if (type.toUpperCase().contains("IPBAN")) { + player.setIpBanned(!unPunish); + } else if (type.toUpperCase().contains("BLACKLIST")) { + player.setBlacklisted(!unPunish); + } + + this.playerRepository.save(player); + + return Constants.SUCCESS_STRING; + } +} diff --git a/WebAPI/src/main/java/me/devkevin/model/Inventory.java b/WebAPI/src/main/java/me/devkevin/model/Inventory.java new file mode 100644 index 0000000..0a0553e --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/model/Inventory.java @@ -0,0 +1,31 @@ +package me.devkevin.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; + +import static me.devkevin.util.Constants.*; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 22/02/2022 @ 20:57 + */ +@Data @NoArgsConstructor @AllArgsConstructor @Entity(name = "practice_season_" + PRACTICE_SEASON + "_inventories") +public class Inventory implements Serializable { + + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private int id; + + private String winnerInventory; + private String loserInventory; + private String matchId; + +} diff --git a/WebAPI/src/main/java/me/devkevin/model/Match.java b/WebAPI/src/main/java/me/devkevin/model/Match.java new file mode 100644 index 0000000..5b70164 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/model/Match.java @@ -0,0 +1,34 @@ +package me.devkevin.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; + +import java.io.Serializable; + +import static me.devkevin.util.Constants.PRACTICE_SEASON; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 22/02/2022 @ 21:01 + */ +@Data @NoArgsConstructor @AllArgsConstructor @Entity(name = "practice_season" + PRACTICE_SEASON + "_matches") +public class Match implements Serializable { + @Id + private String id; + + private int inventory; + + private int winner; + private int loser; + + private int winnerEloBefore; + private int loserEloBefore; + + private int winnerEloAfter; + private int loserEloAfter; +} diff --git a/WebAPI/src/main/java/me/devkevin/model/Player.java b/WebAPI/src/main/java/me/devkevin/model/Player.java new file mode 100644 index 0000000..c0ca2af --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/model/Player.java @@ -0,0 +1,62 @@ +package me.devkevin.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.*; +import java.io.Serializable; +import java.sql.Timestamp; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 22/02/2022 @ 20:29 + */ +@Data @NoArgsConstructor @AllArgsConstructor @Entity(name = "players") +public class Player implements Serializable { + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private int playerId; + + @Column + private String ipAddress = null; + @Column + private String name = null; + + @Column(name = "uuid") + private String uniqueId; + + @Column(name = "mute_time") + private Timestamp muteTime = null; + + @Column(name = "ban_time") + private Timestamp banTime = null; + + @Column(name = "first_login") + private Timestamp firstLogin = null; + + @Column(name = "last_login") + private String lastLogin = null; + + @Column(name = "rank") + private String rank = null; + + @Column(name = "blacklisted") + private boolean blacklisted = false; + + @Column(name = "ip_banned") + private boolean ipBanned = false; + + @Column(name = "banned") + private boolean banned = false; + + @Column(name = "muted") + private boolean muted = false; + + @Column(name = "country_code") + private String countryCode; + + @Column(name = "country_name") + private String countryName; +} diff --git a/WebAPI/src/main/java/me/devkevin/model/PracticeProfile.java b/WebAPI/src/main/java/me/devkevin/model/PracticeProfile.java new file mode 100644 index 0000000..c2acf42 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/model/PracticeProfile.java @@ -0,0 +1,81 @@ +package me.devkevin.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Id; + +import java.io.Serializable; + +import static me.devkevin.util.Constants.*; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 22/02/2022 @ 21:03 + */ +@Data @NoArgsConstructor @AllArgsConstructor @Entity(name = "practice_season_" + PRACTICE_SEASON + "_profile") +public class PracticeProfile implements Serializable { + @Id + @Column(unique = true) + private int playerId; + + private int unrankedWins; + private int rankedWins; + + private int globalElo; + + // implement Kits elo & elo party, losses, wins + private int nodebuffElo; + private int nodebuffEloParty; + private int nodebuffWins; + private int nodebuffLosses; + + private int boxingElo; + private int boxingEloParty; + private int boxingWins; + private int boxingLosses; + + private int bedFightElo; + private int bedFightEloParty; + private int bedFightWins; + private int bedFightLosses; + + private int gappleElo; + private int gappleEloParty; + private int gappleWins; + private int gappleLosses; + + private int buildUHCELo; + private int buildUHCELoParty; + private int buildUHCWins; + private int buildUHCLosses; + + private int sumoElo; + private int sumoEloParty; + private int sumoWins; + private int sumoLosses; + + private int finalUHCElo; + private int finalUHCEloParty; + private int finalUHCWins; + private int finalUHCLosses; + + private int axeElo; + private int axeEloParty; + private int axeWins; + private int axeLosses; + + private int soupElo; + private int soupEloParty; + private int soupWins; + private int soupLosses; + + private int fullpvpElo; + private int fullpvpEloParty; + private int fullpvpWins; + private int fullpvpLosses; +} diff --git a/WebAPI/src/main/java/me/devkevin/model/Punishment.java b/WebAPI/src/main/java/me/devkevin/model/Punishment.java new file mode 100644 index 0000000..771422a --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/model/Punishment.java @@ -0,0 +1,40 @@ +package me.devkevin.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import java.io.Serializable; +import java.sql.Timestamp; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 3:34 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Entity(name = "punishments") +public class Punishment implements Serializable { + + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Id + private int id; + + private Timestamp timestamp; + private Timestamp expiry; + + private String serverIp; + private String reason; + private String type; + private String ip; + + private int punisherId; + private int playerId; + +} diff --git a/WebAPI/src/main/java/me/devkevin/model/Register.java b/WebAPI/src/main/java/me/devkevin/model/Register.java new file mode 100644 index 0000000..c175a8d --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/model/Register.java @@ -0,0 +1,23 @@ +package me.devkevin.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Entity; +import javax.persistence.Id; +import java.io.Serializable; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 02/03/2022 @ 18:43 + */ +@Data @NoArgsConstructor @AllArgsConstructor @Entity(name = "user") +public class Register implements Serializable { + @Id + private String uuid; + + private String password; + private String password_key; +} diff --git a/WebAPI/src/main/java/me/devkevin/repo/InventoryRepository.java b/WebAPI/src/main/java/me/devkevin/repo/InventoryRepository.java new file mode 100644 index 0000000..23aced2 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/repo/InventoryRepository.java @@ -0,0 +1,19 @@ +package me.devkevin.repo; + +import me.devkevin.model.Inventory; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 4:11 + */ +@Repository +public interface InventoryRepository extends CrudRepository { + + Inventory findByMatchId(String matchId); + + Inventory findById(int id); + +} diff --git a/WebAPI/src/main/java/me/devkevin/repo/MatchesRepository.java b/WebAPI/src/main/java/me/devkevin/repo/MatchesRepository.java new file mode 100644 index 0000000..8dc4eef --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/repo/MatchesRepository.java @@ -0,0 +1,23 @@ +package me.devkevin.repo; + +import me.devkevin.model.Match; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 3:36 + */ +@Repository +public interface MatchesRepository extends CrudRepository { + + List findByWinner(int winner); + + List findByLoser(int winner); + + Match findById(int id); + +} diff --git a/WebAPI/src/main/java/me/devkevin/repo/PlayerRepository.java b/WebAPI/src/main/java/me/devkevin/repo/PlayerRepository.java new file mode 100644 index 0000000..dfc7a1b --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/repo/PlayerRepository.java @@ -0,0 +1,27 @@ +package me.devkevin.repo; + +import me.devkevin.model.Player; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 22/02/2022 @ 20:28 + */ +@Repository +public interface PlayerRepository extends CrudRepository { + + List findByIpAddress(String ipAddress); + + List findByName(String name); + + Player findFirstByUniqueId(String uniqueId); + + List findAllByPlayerIdIn(int[] ids); + + Player findFirstByPlayerId(int id); + +} diff --git a/WebAPI/src/main/java/me/devkevin/repo/PracticeRepository.java b/WebAPI/src/main/java/me/devkevin/repo/PracticeRepository.java new file mode 100644 index 0000000..7ba698e --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/repo/PracticeRepository.java @@ -0,0 +1,17 @@ +package me.devkevin.repo; + +import me.devkevin.model.PracticeProfile; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 3:38 + */ +@Repository +public interface PracticeRepository extends CrudRepository { + + PracticeProfile findFirstByPlayerId(int id); + +} diff --git a/WebAPI/src/main/java/me/devkevin/repo/PunishmentRepository.java b/WebAPI/src/main/java/me/devkevin/repo/PunishmentRepository.java new file mode 100644 index 0000000..2fb3298 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/repo/PunishmentRepository.java @@ -0,0 +1,23 @@ +package me.devkevin.repo; + +import me.devkevin.model.Punishment; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * Created by DevKevin + * Project: WebAPI + * Date: 23/02/2022 @ 3:39 + */ +@Repository +public interface PunishmentRepository extends CrudRepository { + + Punishment findFirstByPlayerIdAndTypeContainingOrderByTimestampDesc(int id, String reason); + + List findByPlayerId(int id); + + Long countByPlayerId(int id); + +} diff --git a/WebAPI/src/main/java/me/devkevin/util/Constants.java b/WebAPI/src/main/java/me/devkevin/util/Constants.java new file mode 100644 index 0000000..ac32e71 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/util/Constants.java @@ -0,0 +1,77 @@ +package me.devkevin.util; + +import com.google.gson.JsonObject; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +public final class Constants { + + public static final ResponseEntity PLAYER_NOT_FOUND; + public static final ResponseEntity INVALID_KEY; + public static final ResponseEntity ALREADY_HAVE_PREFIX; + public static final ResponseEntity ALREADY_HAVE_KIT; + public static final ResponseEntity ALREADY_HAVE_DISGUISE; + public static final ResponseEntity PREFIX_NOT_FOUND; + public static final ResponseEntity KIT_NOT_FOUND; + public static final ResponseEntity SUCCESS; + + public static final ResponseEntity PLAYER_NOT_FOUND_STRING; + public static final ResponseEntity INVALID_KEY_STRING; + public static final ResponseEntity ALREADY_HAVE_PREFIX_STRING; + public static final ResponseEntity ALREADY_HAVE_KIT_STRING; + public static final ResponseEntity ALREADY_HAVE_DISGUISE_STRING; + public static final ResponseEntity PREFIX_NOT_FOUND_STRING; + public static final ResponseEntity KIT_NOT_FOUND_STRING; + public static final ResponseEntity SUCCESS_STRING; + + public static final String API_KEY = "czmxnvbDFJGfdf87634asdfjgcv"; + + public static final int PRACTICE_SEASON = 1; + + static { + JsonObject object = new JsonObject(); + object.addProperty("response", "player-not-found"); + PLAYER_NOT_FOUND = new ResponseEntity<>(object, HttpStatus.OK); + + object = new JsonObject(); + object.addProperty("response", "invalid-key"); + INVALID_KEY = new ResponseEntity<>(object, HttpStatus.FORBIDDEN); + + object = new JsonObject(); + object.addProperty("response", "already-have-prefix"); + ALREADY_HAVE_PREFIX = new ResponseEntity<>(object, HttpStatus.OK); + + object = new JsonObject(); + object.addProperty("response", "already-have-kit"); + ALREADY_HAVE_KIT = new ResponseEntity<>(object, HttpStatus.OK); + + object = new JsonObject(); + object.addProperty("response", "already-have-disguise"); + ALREADY_HAVE_DISGUISE = new ResponseEntity<>(object, HttpStatus.OK); + + object = new JsonObject(); + object.addProperty("response", "prefix-not-found"); + PREFIX_NOT_FOUND = new ResponseEntity<>(object, HttpStatus.OK); + + object = new JsonObject(); + object.addProperty("response", "prefix-not-found"); + KIT_NOT_FOUND = new ResponseEntity<>(object, HttpStatus.OK); + + object = new JsonObject(); + object.addProperty("response", "success"); + SUCCESS = new ResponseEntity<>(object, HttpStatus.OK); + + PLAYER_NOT_FOUND_STRING = new ResponseEntity<>(PLAYER_NOT_FOUND.getBody().toString(), HttpStatus.OK); + INVALID_KEY_STRING = new ResponseEntity<>(INVALID_KEY.getBody().toString(), HttpStatus.FORBIDDEN); + ALREADY_HAVE_PREFIX_STRING = new ResponseEntity<>(ALREADY_HAVE_PREFIX.getBody().toString(), HttpStatus.OK); + ALREADY_HAVE_KIT_STRING = new ResponseEntity<>(ALREADY_HAVE_KIT.getBody().toString(), HttpStatus.OK); + ALREADY_HAVE_DISGUISE_STRING = new ResponseEntity<>(ALREADY_HAVE_DISGUISE.getBody().toString(), HttpStatus.OK); + PREFIX_NOT_FOUND_STRING = new ResponseEntity<>(PREFIX_NOT_FOUND.getBody().toString(), HttpStatus.OK); + KIT_NOT_FOUND_STRING = new ResponseEntity<>(KIT_NOT_FOUND.getBody().toString(), HttpStatus.OK); + SUCCESS_STRING = new ResponseEntity<>(SUCCESS.getBody().toString(), HttpStatus.OK); + } + + public static boolean validServerKey(String key) { + return key.equals(Constants.API_KEY); + } +} diff --git a/WebAPI/src/main/java/me/devkevin/util/HttpUtil.java b/WebAPI/src/main/java/me/devkevin/util/HttpUtil.java new file mode 100644 index 0000000..47796ac --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/util/HttpUtil.java @@ -0,0 +1,87 @@ +package me.devkevin.util; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import javax.net.ssl.HttpsURLConnection; +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.Proxy; +import java.net.URL; +import java.util.UUID; +import java.util.logging.Logger; + +public final class HttpUtil { + + /** + * Fetch UUID from name via Mojang's API.

+ * + * @param name - Player's name to fetch + * + * @return - UUID assigned to the name provided + */ + public static UUID getUniqueIdFromName(String name) { + BufferedReader in = null; + + try { + String url = "https://api.mojang.com/profiles/minecraft"; + URL obj = new URL(url); + + HttpsURLConnection con = (HttpsURLConnection) obj.openConnection(Proxy.NO_PROXY); + + con.setRequestMethod("POST"); + con.setRequestProperty("User-Agent", "Mozilla/5.0"); + con.setRequestProperty("Content-Type", "application/json"); + + String urlParameters = "[\"" + name + "\"]"; + + con.setDoOutput(true); + DataOutputStream wr = new DataOutputStream(con.getOutputStream()); + wr.writeBytes(urlParameters); + wr.flush(); + wr.close(); + + int responseCode = con.getResponseCode(); + if (responseCode != 200) { + return null; + } + + in = new BufferedReader(new InputStreamReader(con.getInputStream())); + + JsonArray array = new JsonParser().parse(in).getAsJsonArray(); + JsonObject object = array.get(0).getAsJsonObject(); + + String uuid = object.get("uuid").getAsString().trim(); + + String[] parts = { + uuid.substring(0, 8), + uuid.substring(8, 12), + uuid.substring(12, 16), + uuid.substring(16, 20), + uuid.substring(20, 32) + }; + + return UUID.fromString(String.join("-", parts)); + } catch (Exception e) { + e.printStackTrace(); + + Logger.getGlobal().warning("!!!!!!!!!!!!!!!!!!!!!!! POTENTIAL RATE LIMITINGS ON CHECKING FOR " + name); + + } finally { + try { + if (in != null) { + in.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + Logger.getGlobal().severe("Failed to fetch UUID for " + name); + + return null; + } +} diff --git a/WebAPI/src/main/java/me/devkevin/util/PlayerUtil.java b/WebAPI/src/main/java/me/devkevin/util/PlayerUtil.java new file mode 100644 index 0000000..c978539 --- /dev/null +++ b/WebAPI/src/main/java/me/devkevin/util/PlayerUtil.java @@ -0,0 +1,42 @@ +package me.devkevin.util; + +import me.devkevin.model.Player; +import me.devkevin.repo.PlayerRepository; + +import java.util.List; +import java.util.UUID; + +/** + * Util class containing wrapper methods to fetch Player Data.

+ * + * Created by DevKevin + * Project: WebAPI + * Date: 22/02/2022 @ 20:27 + */ +public class PlayerUtil { + + public static Player getByName(String name, PlayerRepository playerRepository) { + if (name.length() > 16) { + UUID uuid = UUID.fromString(name); + + return playerRepository.findFirstByUniqueId(uuid.toString()); + } + + List players = playerRepository.findByName(name); + if (players.size() == 1) { + return players.get(0); + } + + try { + UUID uuid = HttpUtil.getUniqueIdFromName(name); + if (uuid == null) { + return null; + } + + return playerRepository.findFirstByUniqueId(uuid.toString()); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/WebAPI/src/main/resources/application.properties b/WebAPI/src/main/resources/application.properties new file mode 100644 index 0000000..f1ce484 --- /dev/null +++ b/WebAPI/src/main/resources/application.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/webapi?createDatabaseIfNotExist=true&useUnicode=yes&characterEncoding=UTF-8 +spring.datasource.username=root +spring.datasource.password=4326bdh3dafd11231fdshyg3q +spring.datasource.driver-class-name=com.mysql.jdbc.Driver +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.hibernate.ddl-auto=update \ No newline at end of file diff --git a/WebAPI/target/WebAPI-0.0.1-SNAPSHOT.jar b/WebAPI/target/WebAPI-0.0.1-SNAPSHOT.jar new file mode 100644 index 0000000..aca8f75 Binary files /dev/null and b/WebAPI/target/WebAPI-0.0.1-SNAPSHOT.jar differ diff --git a/WebAPI/target/WebAPI-0.0.1-SNAPSHOT.jar.original b/WebAPI/target/WebAPI-0.0.1-SNAPSHOT.jar.original new file mode 100644 index 0000000..57b1f2b Binary files /dev/null and b/WebAPI/target/WebAPI-0.0.1-SNAPSHOT.jar.original differ diff --git a/WebAPI/target/classes/application.properties b/WebAPI/target/classes/application.properties new file mode 100644 index 0000000..f1ce484 --- /dev/null +++ b/WebAPI/target/classes/application.properties @@ -0,0 +1,6 @@ +spring.datasource.url=jdbc:mysql://localhost:3306/webapi?createDatabaseIfNotExist=true&useUnicode=yes&characterEncoding=UTF-8 +spring.datasource.username=root +spring.datasource.password=4326bdh3dafd11231fdshyg3q +spring.datasource.driver-class-name=com.mysql.jdbc.Driver +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect +spring.jpa.hibernate.ddl-auto=update \ No newline at end of file diff --git a/WebAPI/target/classes/me/devkevin/WebAPI.class b/WebAPI/target/classes/me/devkevin/WebAPI.class new file mode 100644 index 0000000..1b6b49b Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/WebAPI.class differ diff --git a/WebAPI/target/classes/me/devkevin/controller/MatchController.class b/WebAPI/target/classes/me/devkevin/controller/MatchController.class new file mode 100644 index 0000000..e9f7c70 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/controller/MatchController.class differ diff --git a/WebAPI/target/classes/me/devkevin/controller/PlayerController.class b/WebAPI/target/classes/me/devkevin/controller/PlayerController.class new file mode 100644 index 0000000..1c840a0 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/controller/PlayerController.class differ diff --git a/WebAPI/target/classes/me/devkevin/controller/PracticeController.class b/WebAPI/target/classes/me/devkevin/controller/PracticeController.class new file mode 100644 index 0000000..b9afb35 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/controller/PracticeController.class differ diff --git a/WebAPI/target/classes/me/devkevin/controller/PunishController.class b/WebAPI/target/classes/me/devkevin/controller/PunishController.class new file mode 100644 index 0000000..94dc52d Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/controller/PunishController.class differ diff --git a/WebAPI/target/classes/me/devkevin/model/Inventory.class b/WebAPI/target/classes/me/devkevin/model/Inventory.class new file mode 100644 index 0000000..b647c38 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/model/Inventory.class differ diff --git a/WebAPI/target/classes/me/devkevin/model/Match.class b/WebAPI/target/classes/me/devkevin/model/Match.class new file mode 100644 index 0000000..2322c3d Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/model/Match.class differ diff --git a/WebAPI/target/classes/me/devkevin/model/Player.class b/WebAPI/target/classes/me/devkevin/model/Player.class new file mode 100644 index 0000000..af2b48b Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/model/Player.class differ diff --git a/WebAPI/target/classes/me/devkevin/model/PracticeProfile.class b/WebAPI/target/classes/me/devkevin/model/PracticeProfile.class new file mode 100644 index 0000000..2a04203 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/model/PracticeProfile.class differ diff --git a/WebAPI/target/classes/me/devkevin/model/Punishment.class b/WebAPI/target/classes/me/devkevin/model/Punishment.class new file mode 100644 index 0000000..cbafaa9 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/model/Punishment.class differ diff --git a/WebAPI/target/classes/me/devkevin/model/Register.class b/WebAPI/target/classes/me/devkevin/model/Register.class new file mode 100644 index 0000000..a2a209f Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/model/Register.class differ diff --git a/WebAPI/target/classes/me/devkevin/repo/InventoryRepository.class b/WebAPI/target/classes/me/devkevin/repo/InventoryRepository.class new file mode 100644 index 0000000..f96558a Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/repo/InventoryRepository.class differ diff --git a/WebAPI/target/classes/me/devkevin/repo/MatchesRepository.class b/WebAPI/target/classes/me/devkevin/repo/MatchesRepository.class new file mode 100644 index 0000000..1042554 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/repo/MatchesRepository.class differ diff --git a/WebAPI/target/classes/me/devkevin/repo/PlayerRepository.class b/WebAPI/target/classes/me/devkevin/repo/PlayerRepository.class new file mode 100644 index 0000000..817827b Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/repo/PlayerRepository.class differ diff --git a/WebAPI/target/classes/me/devkevin/repo/PracticeRepository.class b/WebAPI/target/classes/me/devkevin/repo/PracticeRepository.class new file mode 100644 index 0000000..7de23a0 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/repo/PracticeRepository.class differ diff --git a/WebAPI/target/classes/me/devkevin/repo/PunishmentRepository.class b/WebAPI/target/classes/me/devkevin/repo/PunishmentRepository.class new file mode 100644 index 0000000..bd421e2 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/repo/PunishmentRepository.class differ diff --git a/WebAPI/target/classes/me/devkevin/util/Constants.class b/WebAPI/target/classes/me/devkevin/util/Constants.class new file mode 100644 index 0000000..1b70092 Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/util/Constants.class differ diff --git a/WebAPI/target/classes/me/devkevin/util/HttpUtil.class b/WebAPI/target/classes/me/devkevin/util/HttpUtil.class new file mode 100644 index 0000000..04c8aee Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/util/HttpUtil.class differ diff --git a/WebAPI/target/classes/me/devkevin/util/PlayerUtil.class b/WebAPI/target/classes/me/devkevin/util/PlayerUtil.class new file mode 100644 index 0000000..982ad4d Binary files /dev/null and b/WebAPI/target/classes/me/devkevin/util/PlayerUtil.class differ diff --git a/WebAPI/target/maven-archiver/pom.properties b/WebAPI/target/maven-archiver/pom.properties new file mode 100644 index 0000000..acd5014 --- /dev/null +++ b/WebAPI/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Apache Maven +#Sat Mar 12 16:17:24 GMT 2022 +version=0.0.1-SNAPSHOT +groupId=me.devkevin +artifactId=WebAPI diff --git a/WebAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/WebAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..27b66e3 --- /dev/null +++ b/WebAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,19 @@ +me\devkevin\util\HttpUtil.class +me\devkevin\model\Match.class +me\devkevin\model\Register.class +me\devkevin\repo\PlayerRepository.class +me\devkevin\controller\PlayerController.class +me\devkevin\controller\PunishController.class +me\devkevin\model\Inventory.class +me\devkevin\controller\MatchController.class +me\devkevin\model\Punishment.class +me\devkevin\repo\MatchesRepository.class +me\devkevin\repo\InventoryRepository.class +me\devkevin\util\PlayerUtil.class +me\devkevin\repo\PracticeRepository.class +me\devkevin\util\Constants.class +me\devkevin\model\PracticeProfile.class +me\devkevin\WebAPI.class +me\devkevin\repo\PunishmentRepository.class +me\devkevin\controller\PracticeController.class +me\devkevin\model\Player.class diff --git a/WebAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/WebAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..38e5610 --- /dev/null +++ b/WebAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,19 @@ +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\controller\PlayerController.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\model\Inventory.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\repo\PunishmentRepository.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\controller\PunishController.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\model\Player.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\model\Match.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\model\PracticeProfile.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\util\HttpUtil.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\repo\PlayerRepository.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\model\Punishment.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\WebAPI.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\model\Register.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\util\PlayerUtil.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\repo\InventoryRepository.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\repo\MatchesRepository.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\controller\MatchController.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\repo\PracticeRepository.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\util\Constants.java +C:\Users\kevin\Desktop\Java Projects\WebAPI\src\main\java\me\devkevin\controller\PracticeController.java diff --git a/WebAPI/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/WebAPI/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/WebSocketAPI/.idea/.gitignore b/WebSocketAPI/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/WebSocketAPI/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/WebSocketAPI/.idea/compiler.xml b/WebSocketAPI/.idea/compiler.xml new file mode 100644 index 0000000..9dc0789 --- /dev/null +++ b/WebSocketAPI/.idea/compiler.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebSocketAPI/.idea/discord.xml b/WebSocketAPI/.idea/discord.xml new file mode 100644 index 0000000..d8e9561 --- /dev/null +++ b/WebSocketAPI/.idea/discord.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/WebSocketAPI/.idea/encodings.xml b/WebSocketAPI/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/WebSocketAPI/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/WebSocketAPI/.idea/jarRepositories.xml b/WebSocketAPI/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/WebSocketAPI/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/WebSocketAPI/.idea/misc.xml b/WebSocketAPI/.idea/misc.xml new file mode 100644 index 0000000..4b661a5 --- /dev/null +++ b/WebSocketAPI/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/WebSocketAPI/.idea/uiDesigner.xml b/WebSocketAPI/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/WebSocketAPI/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebSocketAPI/WebSocketAPI.iml b/WebSocketAPI/WebSocketAPI.iml new file mode 100644 index 0000000..78b2cc5 --- /dev/null +++ b/WebSocketAPI/WebSocketAPI.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/WebSocketAPI/lib/Core.jar b/WebSocketAPI/lib/Core.jar new file mode 100644 index 0000000..3e803a4 Binary files /dev/null and b/WebSocketAPI/lib/Core.jar differ diff --git a/WebSocketAPI/lib/paperspigot-1.8.8-R0.1-SNAPSHOT.jar b/WebSocketAPI/lib/paperspigot-1.8.8-R0.1-SNAPSHOT.jar new file mode 100644 index 0000000..aa2dc11 Binary files /dev/null and b/WebSocketAPI/lib/paperspigot-1.8.8-R0.1-SNAPSHOT.jar differ diff --git a/WebSocketAPI/pom.xml b/WebSocketAPI/pom.xml new file mode 100644 index 0000000..9284ba3 --- /dev/null +++ b/WebSocketAPI/pom.xml @@ -0,0 +1,107 @@ + + + 4.0.0 + + me.devkevin + WebSocketAPI + 1.0-SNAPSHOT + + + UTF-8 + + + + + + club.udrop + devspigot-api + 1.8.8-R0.1-SNAPSHOT + system + ${project.basedir}/lib/paperspigot-1.8.8-R0.1-SNAPSHOT.jar + + + + + club.udrop.core + Core + 1.0.0-SNAPSHOT + system + ${project.basedir}/lib/Core.jar + + + + org.apache.httpcomponents + httpclient + 4.5.3 + + + + org.projectlombok + lombok + 1.16.16 + provided + + + + redis.clients + jedis + 2.9.0 + compile + + + + com.zaxxer + HikariCP + 2.6.3 + compile + + + + + clean deploy + ${project.name} + + + + src/main/resources + true + + + + + + 3.6.1 + org.apache.maven.plugins + maven-compiler-plugin + + + 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/WebSocketAPI/src/main/java/me/devkevin/WebSocketAPI.java b/WebSocketAPI/src/main/java/me/devkevin/WebSocketAPI.java new file mode 100644 index 0000000..d24cddd --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/WebSocketAPI.java @@ -0,0 +1,62 @@ +package me.devkevin; + +import club.udrop.chatcolor.CC; +import lombok.Getter; +import me.devkevin.file.ConfigFile; +import me.devkevin.profile.listener.ProfileListener; +import me.devkevin.profile.manager.ProfileManager; +import me.devkevin.socket.WebSocketAPIProcessor; +import org.bukkit.Bukkit; +import org.bukkit.plugin.java.JavaPlugin; + +import static org.bukkit.Bukkit.getPluginManager; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:27 + */ +@Getter +public class WebSocketAPI extends JavaPlugin { + @Getter private static WebSocketAPI instance; + + private ConfigFile configFile; + + private ProfileManager profileManager; + private WebSocketAPIProcessor processor; + + private String apiUrl, apiKey; + + @Override + public void onEnable() { + instance = this; + + if (!WebSocketAPI.getInstance().getDescription().getAuthors().contains("DevKevin") || !WebSocketAPI.getInstance().getDescription().getName().equals("WebSocketAPI")) { + getPluginManager().disablePlugin(this); + } + + Bukkit.getConsoleSender().sendMessage(CC.STRIKETHROUGH); + Bukkit.getConsoleSender().sendMessage(CC.translate("&7[WebSocketAPI]: &aHas been enabled correctly.")); + Bukkit.getConsoleSender().sendMessage(CC.translate("&7Made by &6DevKevin")); + Bukkit.getConsoleSender().sendMessage(CC.STRIKETHROUGH); + + saveDefaultConfig(); + getConfig().options().copyDefaults(true); + saveConfig(); + + this.configFile = new ConfigFile(this, "config"); + + this.apiUrl = this.configFile.getString("api.url"); + this.apiKey = this.configFile.getString("api.key"); + + profileManager = new ProfileManager(); + processor = new WebSocketAPIProcessor(this, this.apiUrl, this.apiKey); + + this.getServer().getPluginManager().registerEvents(new ProfileListener(), this); + } + + @Override + public void onDisable() { + instance = null; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/api/AbstractCallback.java b/WebSocketAPI/src/main/java/me/devkevin/api/AbstractCallback.java new file mode 100644 index 0000000..db50efa --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/api/AbstractCallback.java @@ -0,0 +1,33 @@ +package me.devkevin.api; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.logging.Logger; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:35 + */ +@Getter @RequiredArgsConstructor +public abstract class AbstractCallback implements Callback, ErrorCallback { + private final String errorMessage; + private boolean errorCalled = false; + + @Override + public void onError(String message) { + this.errorCalled = true; + if (!this.errorMessage.isEmpty()) { + Logger.getGlobal().severe(this.errorMessage); + } + + Logger.getGlobal().severe(message); + } + + public void throwException() throws Exception { + if (this.errorCalled) { + throw new Exception(this.errorMessage); + } + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/api/AbstractRequestProcessor.java b/WebSocketAPI/src/main/java/me/devkevin/api/AbstractRequestProcessor.java new file mode 100644 index 0000000..949438c --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/api/AbstractRequestProcessor.java @@ -0,0 +1,165 @@ +package me.devkevin.api; + +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; +import org.apache.http.ParseException; +import org.apache.http.StatusLine; +import org.apache.http.client.entity.UrlEncodedFormEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.message.BasicNameValuePair; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:40 + */ +@Getter @RequiredArgsConstructor +public abstract class AbstractRequestProcessor implements RequestProcessor { + private final String apiUrl; + private final String apiKey; + + @Override + public JsonElement sendRequest(Request request) { + return this.sendRequest(request, null); + } + + @Override + public void sendRequestAsync(Request request) { + this.sendRequest(request, null, true); + } + + @Override + public void sendRequestAsync(Request request, Callback callback) { + this.sendRequest(request, callback,true); + } + + @Override + public void sendRequest(Request request, Callback callback, boolean async) { + if (async) { + this.runTaskAsynchronously(() -> this.sendRequest(request, callback)); + } else { + this.sendRequest(request, callback); + } + } + + @Override + public JsonElement sendRequest(Request request, Callback callback) { + if (!this.shouldSend()) { + + System.out.println("!!!!!!!!!!!! " + + "Attempt on main thread " + + "!!!!!!!!!!!!"); + + throw new IllegalStateException("Attempted to send an API request on the main thread."); + } + + Map data = request.toMap(); + if (data == null) { + data = new HashMap<>(); + } + + List parameters = new ArrayList<>(2); + + for (String key : data.keySet()) { + Object value = data.get(key); + parameters.add(new BasicNameValuePair(key, value == null ? null : value.toString())); + } + + CloseableHttpClient client = HttpClients.createDefault(); + try { + String url = ("http://" + this.apiUrl + "/api/" + this.apiKey + request.getPath()); + HttpPost post = new HttpPost( + url.replace(" ", "%20")); + post.setEntity(new UrlEncodedFormEntity(parameters, "UTF-8")); + + CloseableHttpResponse response = null; + try { + try { + response = client.execute(post); + } catch (Exception e) { + e.printStackTrace(); + + if (callback instanceof ErrorCallback) { + this.runTask(() + -> ((ErrorCallback) callback).onError("Error connecting to " + post.getURI().getHost() + + " : " + e.getMessage())); + } + System.out.println("Error connecting to: " + url); + System.out.println("The issue: " + e.getMessage()); + return null; + } + + StatusLine line = response.getStatusLine(); + if (line != null) { + int code = line.getStatusCode(); + if (code != 200) { + if (callback instanceof ErrorCallback) { + this.runTask(() -> ((ErrorCallback) callback).onError("Error code: " + code)); + } + + System.out.println("Error code: " + code); + System.out.println("From request: " + url); + return null; + } + } + + HttpEntity entity = response.getEntity(); + if (entity != null) { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()))) { + JsonParser parser = new JsonParser(); + JsonElement object = parser.parse(reader); + + if (callback != null) { + this.runTask(() -> callback.callback(object)); + } + + return object; + } catch (ParseException e) { + e.printStackTrace(); + + if (callback instanceof ErrorCallback) { + this.runTask(() + -> ((ErrorCallback) callback).onError("Error parsing Json: " + e.getMessage())); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (response != null) { + response.close(); + } + } + } catch (Exception e) { + e.printStackTrace(); + + if (callback instanceof ErrorCallback) { + this.runTask(() + -> ((ErrorCallback) callback).onError("Unknown error: " + e.getMessage())); + } + } finally { + try { + client.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return null; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/api/Callback.java b/WebSocketAPI/src/main/java/me/devkevin/api/Callback.java new file mode 100644 index 0000000..49a4807 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/api/Callback.java @@ -0,0 +1,12 @@ +package me.devkevin.api; + +import com.google.gson.JsonElement; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:34 + */ +public interface Callback { + void callback(JsonElement object); +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/api/ErrorCallback.java b/WebSocketAPI/src/main/java/me/devkevin/api/ErrorCallback.java new file mode 100644 index 0000000..dd1f512 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/api/ErrorCallback.java @@ -0,0 +1,10 @@ +package me.devkevin.api; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:35 + */ +public interface ErrorCallback extends Callback { + void onError(String message); +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/api/Request.java b/WebSocketAPI/src/main/java/me/devkevin/api/Request.java new file mode 100644 index 0000000..ef11303 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/api/Request.java @@ -0,0 +1,13 @@ +package me.devkevin.api; + +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:33 + */ +public interface Request { + String getPath(); + Map toMap(); +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/api/RequestProcessor.java b/WebSocketAPI/src/main/java/me/devkevin/api/RequestProcessor.java new file mode 100644 index 0000000..467159b --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/api/RequestProcessor.java @@ -0,0 +1,84 @@ +package me.devkevin.api; + +import com.google.gson.JsonElement; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:39 + */ +public interface RequestProcessor { + + /** + * Whether or not a request should be allowed to be sent. + *

+ * + * @return - If the request should be sent. + */ + boolean shouldSend(); + + /** + * Send Http Request with a callback on a separate thread or the main thread. + *

+ * + * @param request - Request to send + */ + void sendRequestAsync(Request request); + + /** + * Send Http Request with a callback on a separate thread or the main thread. + *

+ * + * @param request - Request to send + * @param callback - Callback to call with the response + */ + void sendRequestAsync(Request request, Callback callback); + + /** + * Send Http Request with a callback on a separate thread or the main thread. + *

+ * + * @param request - Request to send + * @param callback - Callback to call with the response + */ + JsonElement sendRequest(Request request, Callback callback); + + /** + * Send Http Request with a callback async + *

+ * + * @param request - Request to send + * @param callback - Callback to call with the response + * @param async - Whether the request should be sent on a separate thread. + */ + void sendRequest(Request request, Callback callback, boolean async); + + /** + * Send Http Request on the current thread + *

+ * + * @param request - Request to send + * @return - Response from the request encoded in a Json format. + */ + JsonElement sendRequest(Request request); + + /* + Task Managers + */ + + /** + * Run provided task on a separate thread. + *

+ * + * @param runnable - Task to run + */ + void runTaskAsynchronously(Runnable runnable); + + /** + * Run provided task on the main thread. + *

+ * + * @param runnable - Task to run + */ + void runTask(Runnable runnable); +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/backend/HikariDatabase.java b/WebSocketAPI/src/main/java/me/devkevin/backend/HikariDatabase.java new file mode 100644 index 0000000..799a367 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/backend/HikariDatabase.java @@ -0,0 +1,71 @@ +package me.devkevin.backend; + +import com.zaxxer.hikari.HikariDataSource; +import lombok.Getter; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * A quick and easy way to setup a connection for Hikari. Once the instance is created it is suggested to run {@link + * HikariDatabase#init(Connection)} and pass the {@link HikariDatabase#getConnection()} to test the connection and to + * run anything like table generation. + * + * @since 9/26/2017 + */ +public abstract class HikariDatabase { + @Getter private final HikariDataSource hikari; + + public HikariDatabase(String host, int port, String database, String username, String password) throws Exception { + this.hikari = new HikariDataSource(); + this.hikari.setMaximumPoolSize(10); + this.hikari.setDataSourceClassName("com.mysql.jdbc.jdbc2.optional.MysqlDataSource"); + this.hikari.addDataSourceProperty("serverName", host); + this.hikari.addDataSourceProperty("port", port); + this.hikari.addDataSourceProperty("databaseName", database); + this.hikari.addDataSourceProperty("user", username); + this.hikari.addDataSourceProperty("password", password); + } + + public HikariDatabase(String host, String database, String username, String password) throws Exception { + this(host, 3306, database, username, password); + } + + public abstract void init(Connection connection) throws Exception; + + public Connection getConnection() throws SQLException { + return this.hikari.getConnection(); + } + + public boolean cleanup(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) { + try { + if (resultSet != null) { + resultSet.close(); + } + + if (preparedStatement != null) { + preparedStatement.close(); + } + + if (connection != null) { + connection.close(); + } + + return true; + } catch (SQLException e) { + e.printStackTrace(); + } + + return false; + } + + public boolean cleanup(PreparedStatement preparedStatement, ResultSet resultSet) { + return this.cleanup(null, preparedStatement, resultSet); + } + + public boolean cleanup(PreparedStatement preparedStatement) { + return this.cleanup(null, preparedStatement, null); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/file/ConfigFile.java b/WebSocketAPI/src/main/java/me/devkevin/file/ConfigFile.java new file mode 100644 index 0000000..243740d --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/file/ConfigFile.java @@ -0,0 +1,125 @@ +package me.devkevin.file; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 20:24 + */ +public class ConfigFile { + + @Getter private File file; + @Getter private YamlConfiguration configuration; + + public ConfigFile(JavaPlugin plugin, String name) { + file = new File(plugin.getDataFolder(), name + ".yml"); + + if (!file.getParentFile().exists()) { + file.getParentFile().mkdir(); + } + + plugin.saveResource(name + ".yml", false); + + configuration = YamlConfiguration.loadConfiguration(file); + } + + public double getDouble(String path) { + if (configuration.contains(path)) { + return configuration.getDouble(path); + } + + return 0; + } + + public int getInt(String path) { + if (configuration.contains(path)) { + return configuration.getInt(path); + } + + return 0; + } + + public boolean getBoolean(String path) { + if (configuration.contains(path)) { + return configuration.getBoolean(path); + } + + return false; + } + + public String getString(String path) { + if (configuration.contains(path)) { + return ChatColor.translateAlternateColorCodes('&', configuration.getString(path)); + } + + return "ERROR: STRING NOT FOUND"; + } + + public String getString(String path, String callback, boolean colorize) { + if (configuration.contains(path)) { + if (colorize) { + return ChatColor.translateAlternateColorCodes('&', configuration.getString(path)); + } + else { + return configuration.getString(path); + } + } + + return callback; + } + + public List getReversedStringList(String path) { + List list = getStringList(path); + + if (list != null) { + int size = list.size(); + + List toReturn = new ArrayList<>(); + + for (int i = size - 1; i >= 0; i--) { + toReturn.add(list.get(i)); + } + + return toReturn; + } + + return Collections.singletonList("ERROR: STRING LIST NOT FOUND!"); + } + + public List getStringList(String path) { + if (configuration.contains(path)) { + ArrayList strings = new ArrayList<>(); + for (String string : configuration.getStringList(path)) { + strings.add(ChatColor.translateAlternateColorCodes('&', string)); + } + return strings; + } + + return Collections.singletonList("ERROR: STRING LIST NOT FOUND!"); + } + + public List getStringListOrDefault(String path, List toReturn) { + if (configuration.contains(path)) { + ArrayList strings = new ArrayList<>(); + + for (String string : configuration.getStringList(path)) { + strings.add(ChatColor.translateAlternateColorCodes('&', string)); + } + + return strings; + } + + return toReturn; + } +} + diff --git a/WebSocketAPI/src/main/java/me/devkevin/profile/Profile.java b/WebSocketAPI/src/main/java/me/devkevin/profile/Profile.java new file mode 100644 index 0000000..6015e57 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/profile/Profile.java @@ -0,0 +1,69 @@ +package me.devkevin.profile; + +import club.udrop.core.Core; +import club.udrop.core.CoreAPI; +import club.udrop.core.api.player.PlayerData; +import club.udrop.core.api.rank.RankData; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import me.devkevin.WebSocketAPI; +import me.devkevin.socket.impl.GlobalRequest; +import me.devkevin.util.wrapper.BanWrapper; +import org.bukkit.entity.Player; + +import java.net.InetAddress; +import java.util.UUID; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 14:13 + */ +@Setter +@Getter +@RequiredArgsConstructor +public class Profile { + private final WebSocketAPI plugin = WebSocketAPI.getInstance(); + + private final UUID uuid; + private final String name; + private final InetAddress ipAddress; + private RankData rank; + private BanWrapper banData; + + private int id; + + private boolean errorLoadingData; + + public BanWrapper fetchData() { + PlayerData playerData = CoreAPI.INSTANCE.getPlayerData(getUuid()); + JsonElement data = this.plugin.getProcessor().sendRequest(new GlobalRequest(this.ipAddress, this.uuid, playerData.getPlayerName())); + + this.banData = this.parseProfileData(data); + + return banData; + } + + private BanWrapper parseProfileData(JsonElement element) { + JsonObject object = element.getAsJsonObject(); + + JsonElement idElement = object.get("playerId"); + this.id = idElement.getAsInt(); + + String rank = object.get("rank").getAsString(); + if (rank != null) { + this.rank = Core.INSTANCE.getRankManagement().getRank(this.rank.getName()); + } else { + this.rank = Core.INSTANCE.getRankManagement().getDefaultRank(); + } + + return new BanWrapper("", false); + } + + public Player getPlayer() { + return WebSocketAPI.getInstance().getServer().getPlayer(this.uuid); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/profile/listener/ProfileListener.java b/WebSocketAPI/src/main/java/me/devkevin/profile/listener/ProfileListener.java new file mode 100644 index 0000000..1374d24 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/profile/listener/ProfileListener.java @@ -0,0 +1,68 @@ +package me.devkevin.profile.listener; + +import club.udrop.core.Core; +import club.udrop.core.CoreAPI; +import club.udrop.core.api.player.PlayerData; +import me.devkevin.WebSocketAPI; +import me.devkevin.profile.Profile; +import me.devkevin.socket.impl.JoinRequest; +import me.devkevin.util.StringUtil; +import me.devkevin.util.wrapper.BanWrapper; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 19:46 + */ +public class ProfileListener implements Listener { + private final WebSocketAPI plugin = WebSocketAPI.getInstance(); + + @EventHandler(priority = EventPriority.LOWEST) + public void onAsyncPlayerPreLoginLow(AsyncPlayerPreLoginEvent event) { + this.plugin.getProfileManager().addPlayer(event.getUniqueId(), event.getName(), event.getAddress()); + } + + @EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true) + public void onAsyncPlayerPreLoginHigh(AsyncPlayerPreLoginEvent event) { + if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { + return; + } + + Profile profile = this.plugin.getProfileManager().getPlayer(event.getUniqueId()); + PlayerData playerData = Core.INSTANCE.getPlayerManagement().getPlayerData(profile.getUuid()); + + BanWrapper wrapper = profile.fetchData(); + if (playerData.getPunishData().isBlacklisted() || (wrapper.isBanned() && !CoreAPI.INSTANCE.getServerData("Hub").getServerName().toLowerCase().contains("Hub"))) { + event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_BANNED, wrapper.getMessage()); + } + } + + @EventHandler(priority = EventPriority.LOW) + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + Profile profile = plugin.getProfileManager().getPlayer(player.getUniqueId()); + PlayerData playerData = CoreAPI.INSTANCE.getPlayerData(player.getUniqueId()); + + // API might be processing them slowly, so wait for the retrieve event + if (profile == null) { + player.kickPlayer(StringUtil.LOAD_ERROR); + return; + } + + this.plugin.getProcessor() + .sendRequestAsync(new JoinRequest(profile.getIpAddress(), profile.getUuid(), playerData.getPlayerName())); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + this.plugin.getProfileManager().removePlayer(player.getUniqueId()); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/profile/manager/ProfileManager.java b/WebSocketAPI/src/main/java/me/devkevin/profile/manager/ProfileManager.java new file mode 100644 index 0000000..ca930dd --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/profile/manager/ProfileManager.java @@ -0,0 +1,35 @@ +package me.devkevin.profile.manager; + +import lombok.Getter; +import me.devkevin.profile.Profile; + +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 19:47 + */ +@Getter +public class ProfileManager { + private final Map players = new HashMap<>(); + + public Profile addPlayer(UUID uuid, String name, InetAddress ipAddress) { + Profile profile = new Profile(uuid, name, ipAddress); + + this.players.put(uuid, profile); + + return profile; + } + + public Profile getPlayer(UUID uuid) { + return this.players.get(uuid); + } + + public Profile removePlayer(UUID uuid) { + return this.players.remove(uuid); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/AbstractBukkitCallback.java b/WebSocketAPI/src/main/java/me/devkevin/socket/AbstractBukkitCallback.java new file mode 100644 index 0000000..1e53cc1 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/AbstractBukkitCallback.java @@ -0,0 +1,17 @@ +package me.devkevin.socket; + +import me.devkevin.api.Callback; +import me.devkevin.api.ErrorCallback; +import org.bukkit.Bukkit; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:56 + */ +public abstract class AbstractBukkitCallback implements Callback, ErrorCallback { + @Override + public void onError(String message) { + Bukkit.getLogger().severe("[WebSocketAPI]: " + message); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/WebSocketAPIProcessor.java b/WebSocketAPI/src/main/java/me/devkevin/socket/WebSocketAPIProcessor.java new file mode 100644 index 0000000..8617f79 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/WebSocketAPIProcessor.java @@ -0,0 +1,38 @@ +package me.devkevin.socket; + +import me.devkevin.WebSocketAPI; +import me.devkevin.api.AbstractRequestProcessor; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:48 + */ +public class WebSocketAPIProcessor extends AbstractRequestProcessor { + private final WebSocketAPI plugin; + + public WebSocketAPIProcessor(WebSocketAPI plugin, String apiUrl, String apiKey) { + super(apiUrl, apiKey); + + this.plugin = plugin; + } + + @Override + public boolean shouldSend() { + return !this.plugin.getServer().isPrimaryThread(); + } + + @Override + public void runTaskAsynchronously(Runnable runnable) { + if (this.plugin.getServer().isPrimaryThread()) { + runnable.run(); + } else { + this.plugin.getServer().getScheduler().runTask(this.plugin, runnable); + } + } + + @Override + public void runTask(Runnable runnable) { + this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, runnable); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/impl/GlobalRequest.java b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/GlobalRequest.java new file mode 100644 index 0000000..410b817 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/GlobalRequest.java @@ -0,0 +1,32 @@ +package me.devkevin.socket.impl; + +import com.google.common.collect.ImmutableMap; +import lombok.RequiredArgsConstructor; +import me.devkevin.api.Request; + +import java.net.InetAddress; +import java.util.Map; +import java.util.UUID; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 19:40 + */ +@RequiredArgsConstructor +public final class GlobalRequest implements Request { + private final InetAddress address; + private final UUID uniqueId; + private final String name; + + @Override public String getPath() { + return "/player/" + this.uniqueId.toString() + "/global"; + } + + @Override public Map toMap() { + return ImmutableMap.of( + "name", this.name, + "ip", this.address.getHostAddress() + ); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/impl/IPCheckRequest.java b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/IPCheckRequest.java new file mode 100644 index 0000000..0bf7ce9 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/IPCheckRequest.java @@ -0,0 +1,29 @@ +package me.devkevin.socket.impl; + +import lombok.RequiredArgsConstructor; +import me.devkevin.api.Request; + +import java.net.InetAddress; +import java.util.Map; +import java.util.UUID; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:58 + */ +@RequiredArgsConstructor +public final class IPCheckRequest implements Request { + private final InetAddress address; + private final UUID uuid; + + @Override + public String getPath() { + return "/player/" + this.uuid.toString() + "/ip-check/" + this.address.getHostAddress(); + } + + @Override + public Map toMap() { + return null; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/impl/JoinRequest.java b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/JoinRequest.java new file mode 100644 index 0000000..1d3a884 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/JoinRequest.java @@ -0,0 +1,29 @@ +package me.devkevin.socket.impl; + +import lombok.RequiredArgsConstructor; +import me.devkevin.api.Request; + +import java.net.InetAddress; +import java.util.Map; +import java.util.UUID; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 20:14 + */ +@RequiredArgsConstructor +public final class JoinRequest implements Request { + private final InetAddress address; + private final UUID uniqueId; + + private final String name; + + @Override public String getPath() { + return "/player/" + this.uniqueId.toString() + "/joins/update/" + this.address + "/" + this.name; + } + + @Override public Map toMap() { + return null; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PlayerRequest.java b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PlayerRequest.java new file mode 100644 index 0000000..0ea684a --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PlayerRequest.java @@ -0,0 +1,69 @@ +package me.devkevin.socket.impl; + +import club.udrop.core.Core; +import club.udrop.core.api.rank.RankData; +import lombok.RequiredArgsConstructor; +import me.devkevin.api.Request; +import me.devkevin.util.MapUtil; +import me.devkevin.util.TimeUtil; + +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 4:59 + */ +@RequiredArgsConstructor +public abstract class PlayerRequest implements Request { + private final String path, name; + + @Override + public String getPath() { + return "/player/" + this.name + "/" + this.path; + } + + @Override + public Map toMap() { + return null; + } + + /** + * Wrapper classes for various Player requests. + */ + public static final class AltsRequest extends PlayerRequest { + public AltsRequest(String name) { + super("alts", name); + } + } + + public static final class BanInfoRequest extends PlayerRequest { + public BanInfoRequest(String name) { + super("ban-info", name); + } + } + + public static final class RankUpdateRequest extends PlayerRequest { + private final RankData grant; + private final long duration; + private final int givenBy; + + public RankUpdateRequest(String name, RankData grant, long duration, int givenBy) { + super("update-rank", name); + + this.grant = grant; + this.duration = duration; + this.givenBy = givenBy; + } + + @Override + public Map toMap() { + return MapUtil.of( + "given-by", this.givenBy, + "grant", Core.INSTANCE.getRankManagement().getRank(grant.getName()).getName(), + "start-time", TimeUtil.getCurrentTimestamp(), + "end-time", this.duration == -1 ? "PERM" : TimeUtil.addDuration(this.duration) + ); + } + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PunishHistoryRequest.java b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PunishHistoryRequest.java new file mode 100644 index 0000000..8136d85 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PunishHistoryRequest.java @@ -0,0 +1,26 @@ +package me.devkevin.socket.impl; + +import lombok.RequiredArgsConstructor; +import me.devkevin.api.Request; + +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 5:19 + */ +@RequiredArgsConstructor +public final class PunishHistoryRequest implements Request { + private final String name; + + @Override + public String getPath() { + return "/punishments/fetch/" + this.name; + } + + @Override + public Map toMap() { + return null; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PunishmentRequest.java b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PunishmentRequest.java new file mode 100644 index 0000000..775178f --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/socket/impl/PunishmentRequest.java @@ -0,0 +1,37 @@ +package me.devkevin.socket.impl; + +import lombok.RequiredArgsConstructor; +import me.devkevin.api.Request; +import me.devkevin.util.MapUtil; + +import java.sql.Timestamp; +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 5:21 + */ +@RequiredArgsConstructor +public final class PunishmentRequest implements Request { + private final Timestamp expiry; + private final String ipAddress, reason, name, type; + private final int playerUUID, uuid; + + @Override + public String getPath() { + return "/punishments/punish"; + } + + @Override + public Map toMap() { + return MapUtil.of( + this.name != null ? "name" : "player-uuid", this.name != null ? this.name : this.playerUUID, + "ip-address", this.ipAddress == null ? "UNKNOWN" : this.ipAddress, + "expiry", this.expiry == null ? "PERM" : this.expiry, + "reason", this.reason, + "punisher", this.uuid, + "type", this.type + ); + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/util/Duration.java b/WebSocketAPI/src/main/java/me/devkevin/util/Duration.java new file mode 100644 index 0000000..648b9a0 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/util/Duration.java @@ -0,0 +1,32 @@ +package me.devkevin.util; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 5:14 + */ +@Getter @RequiredArgsConstructor +public enum Duration { + SECOND(1000, "s"), + MINUTE(60 * SECOND.duration, "m"), + HOUR(60 * MINUTE.duration, "h"), + DAY(24 * HOUR.duration, "d"), + WEEK(7 * DAY.duration, "w"), + MONTH(30 * DAY.duration, "M"), + YEAR(365 * DAY.duration, "y"); + + private final long duration; + private final String name; + + public static Duration getByName(String name) { + for (Duration duration : values()) { + if (duration.getName().equals(name)) { + return duration; + } + } + return null; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/util/MapUtil.java b/WebSocketAPI/src/main/java/me/devkevin/util/MapUtil.java new file mode 100644 index 0000000..fb00cef --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/util/MapUtil.java @@ -0,0 +1,31 @@ +package me.devkevin.util; + +import java.util.HashMap; +import java.util.Map; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 5:08 + */ +public class MapUtil { + private MapUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + public static Map of(Object... args) { + if (args.length % 2 != 0) { + throw new IllegalArgumentException("Uneven number of arguments."); + } + + Map map = new HashMap<>(); + + for (int i = 0; i < args.length; i += 2) { + String key = args[0].toString(); + Object value = args[i + 1]; + + map.put(key, value); + } + return map; + } +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/util/StringUtil.java b/WebSocketAPI/src/main/java/me/devkevin/util/StringUtil.java new file mode 100644 index 0000000..c39bff3 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/util/StringUtil.java @@ -0,0 +1,14 @@ +package me.devkevin.util; + +import club.udrop.chatcolor.CC; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 24/02/2022 @ 14:16 + */ +public final class StringUtil { + + public static final String LOAD_ERROR = CC.RED + + "An error occurred while loading your player data. Try again later.\n" + CC.RED + "If you still have this issue, contact a staff member"; +} diff --git a/WebSocketAPI/src/main/java/me/devkevin/util/TimeUtil.java b/WebSocketAPI/src/main/java/me/devkevin/util/TimeUtil.java new file mode 100644 index 0000000..a5551ee --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/util/TimeUtil.java @@ -0,0 +1,127 @@ +package me.devkevin.util; + +import java.sql.Timestamp; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 5:13 + */ +public class TimeUtil { + private TimeUtil() { + throw new RuntimeException("Cannot instantiate a utility class."); + } + + 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 long toMillis(String time) { + if (time == null) { + return -1; + } + + String type = time.substring(time.length() - 1, time.length()); + Duration duration = Duration.getByName(type); + if (duration == null) { + return -1; + } + + int rawTime = Integer.parseInt(time.substring(0, time.length() - 1)); + + return rawTime * duration.getDuration(); + } + + public static String millisToRoundedTime(long millis) { + millis += 1L; // for good shit men + + 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/WebSocketAPI/src/main/java/me/devkevin/util/wrapper/BanWrapper.java b/WebSocketAPI/src/main/java/me/devkevin/util/wrapper/BanWrapper.java new file mode 100644 index 0000000..957bb81 --- /dev/null +++ b/WebSocketAPI/src/main/java/me/devkevin/util/wrapper/BanWrapper.java @@ -0,0 +1,17 @@ +package me.devkevin.util.wrapper; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +/** + * Represents ban data from an SQL request + * + * Created by DevKevin + * Project: WebSocketAPI + * Date: 23/02/2022 @ 14:13 + */ +@Getter @RequiredArgsConstructor +public class BanWrapper { + private final String message; + private final boolean banned; +} diff --git a/WebSocketAPI/src/main/resources/config.yml b/WebSocketAPI/src/main/resources/config.yml new file mode 100644 index 0000000..40b7461 --- /dev/null +++ b/WebSocketAPI/src/main/resources/config.yml @@ -0,0 +1,4 @@ +# The IP/URL for our WebAPI and our security key to access it +api: + url: "localhost:8080" + key: "82jnsnmdo1$dpñl1da21" \ No newline at end of file diff --git a/WebSocketAPI/src/main/resources/plugin.yml b/WebSocketAPI/src/main/resources/plugin.yml new file mode 100644 index 0000000..060fb70 --- /dev/null +++ b/WebSocketAPI/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +main: me.devkevin.WebSocketAPI +name: WebSocketAPI +author: DevKevin +version: 1.0 +depend: + - Core \ No newline at end of file diff --git a/WebSocketAPI/target/WebSocketAPI.jar b/WebSocketAPI/target/WebSocketAPI.jar new file mode 100644 index 0000000..bf507b4 Binary files /dev/null and b/WebSocketAPI/target/WebSocketAPI.jar differ diff --git a/WebSocketAPI/target/classes/config.yml b/WebSocketAPI/target/classes/config.yml new file mode 100644 index 0000000..40b7461 --- /dev/null +++ b/WebSocketAPI/target/classes/config.yml @@ -0,0 +1,4 @@ +# The IP/URL for our WebAPI and our security key to access it +api: + url: "localhost:8080" + key: "82jnsnmdo1$dpñl1da21" \ No newline at end of file diff --git a/WebSocketAPI/target/classes/me/devkevin/WebSocketAPI.class b/WebSocketAPI/target/classes/me/devkevin/WebSocketAPI.class new file mode 100644 index 0000000..4d9a8dd Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/WebSocketAPI.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/api/AbstractCallback.class b/WebSocketAPI/target/classes/me/devkevin/api/AbstractCallback.class new file mode 100644 index 0000000..68ffbd8 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/api/AbstractCallback.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/api/AbstractRequestProcessor.class b/WebSocketAPI/target/classes/me/devkevin/api/AbstractRequestProcessor.class new file mode 100644 index 0000000..640741c Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/api/AbstractRequestProcessor.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/api/Callback.class b/WebSocketAPI/target/classes/me/devkevin/api/Callback.class new file mode 100644 index 0000000..2195963 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/api/Callback.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/api/ErrorCallback.class b/WebSocketAPI/target/classes/me/devkevin/api/ErrorCallback.class new file mode 100644 index 0000000..4f19494 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/api/ErrorCallback.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/api/Request.class b/WebSocketAPI/target/classes/me/devkevin/api/Request.class new file mode 100644 index 0000000..ac0e635 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/api/Request.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/api/RequestProcessor.class b/WebSocketAPI/target/classes/me/devkevin/api/RequestProcessor.class new file mode 100644 index 0000000..ed0fa1a Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/api/RequestProcessor.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/backend/HikariDatabase.class b/WebSocketAPI/target/classes/me/devkevin/backend/HikariDatabase.class new file mode 100644 index 0000000..29e9920 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/backend/HikariDatabase.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/file/ConfigFile.class b/WebSocketAPI/target/classes/me/devkevin/file/ConfigFile.class new file mode 100644 index 0000000..07bfca8 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/file/ConfigFile.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/profile/Profile.class b/WebSocketAPI/target/classes/me/devkevin/profile/Profile.class new file mode 100644 index 0000000..e494d4c Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/profile/Profile.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/profile/listener/ProfileListener.class b/WebSocketAPI/target/classes/me/devkevin/profile/listener/ProfileListener.class new file mode 100644 index 0000000..811645e Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/profile/listener/ProfileListener.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/profile/manager/ProfileManager.class b/WebSocketAPI/target/classes/me/devkevin/profile/manager/ProfileManager.class new file mode 100644 index 0000000..0ee635d Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/profile/manager/ProfileManager.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/AbstractBukkitCallback.class b/WebSocketAPI/target/classes/me/devkevin/socket/AbstractBukkitCallback.class new file mode 100644 index 0000000..e9bba68 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/AbstractBukkitCallback.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/WebSocketAPIProcessor.class b/WebSocketAPI/target/classes/me/devkevin/socket/WebSocketAPIProcessor.class new file mode 100644 index 0000000..3485715 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/WebSocketAPIProcessor.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/GlobalRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/GlobalRequest.class new file mode 100644 index 0000000..b352a8f Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/GlobalRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/IPCheckRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/IPCheckRequest.class new file mode 100644 index 0000000..e266848 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/IPCheckRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/JoinRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/JoinRequest.class new file mode 100644 index 0000000..10ec736 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/JoinRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$AltsRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$AltsRequest.class new file mode 100644 index 0000000..6b20137 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$AltsRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$BanInfoRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$BanInfoRequest.class new file mode 100644 index 0000000..0b739d4 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$BanInfoRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$RankUpdateRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$RankUpdateRequest.class new file mode 100644 index 0000000..f9b9d04 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest$RankUpdateRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest.class new file mode 100644 index 0000000..e34a21c Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PlayerRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/PunishHistoryRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PunishHistoryRequest.class new file mode 100644 index 0000000..5f7598b Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PunishHistoryRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/socket/impl/PunishmentRequest.class b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PunishmentRequest.class new file mode 100644 index 0000000..9cb4630 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/socket/impl/PunishmentRequest.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/util/Duration.class b/WebSocketAPI/target/classes/me/devkevin/util/Duration.class new file mode 100644 index 0000000..1da660f Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/util/Duration.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/util/MapUtil.class b/WebSocketAPI/target/classes/me/devkevin/util/MapUtil.class new file mode 100644 index 0000000..4835f82 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/util/MapUtil.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/util/StringUtil.class b/WebSocketAPI/target/classes/me/devkevin/util/StringUtil.class new file mode 100644 index 0000000..2589b3f Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/util/StringUtil.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/util/TimeUtil.class b/WebSocketAPI/target/classes/me/devkevin/util/TimeUtil.class new file mode 100644 index 0000000..6a16e8f Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/util/TimeUtil.class differ diff --git a/WebSocketAPI/target/classes/me/devkevin/util/wrapper/BanWrapper.class b/WebSocketAPI/target/classes/me/devkevin/util/wrapper/BanWrapper.class new file mode 100644 index 0000000..e01db77 Binary files /dev/null and b/WebSocketAPI/target/classes/me/devkevin/util/wrapper/BanWrapper.class differ diff --git a/WebSocketAPI/target/classes/plugin.yml b/WebSocketAPI/target/classes/plugin.yml new file mode 100644 index 0000000..060fb70 --- /dev/null +++ b/WebSocketAPI/target/classes/plugin.yml @@ -0,0 +1,6 @@ +main: me.devkevin.WebSocketAPI +name: WebSocketAPI +author: DevKevin +version: 1.0 +depend: + - Core \ No newline at end of file diff --git a/WebSocketAPI/target/maven-archiver/pom.properties b/WebSocketAPI/target/maven-archiver/pom.properties new file mode 100644 index 0000000..425efe7 --- /dev/null +++ b/WebSocketAPI/target/maven-archiver/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Thu Feb 24 16:23:12 GMT 2022 +version=1.0-SNAPSHOT +groupId=me.devkevin +artifactId=WebSocketAPI diff --git a/WebSocketAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/WebSocketAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst new file mode 100644 index 0000000..0f30ce6 --- /dev/null +++ b/WebSocketAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -0,0 +1,28 @@ +me\devkevin\util\Duration.class +me\devkevin\api\AbstractCallback.class +me\devkevin\backend\HikariDatabase.class +me\devkevin\WebSocketAPI.class +me\devkevin\socket\impl\JoinRequest.class +me\devkevin\socket\impl\PlayerRequest$BanInfoRequest.class +me\devkevin\api\ErrorCallback.class +me\devkevin\profile\Profile.class +me\devkevin\socket\impl\PunishmentRequest.class +me\devkevin\socket\impl\PlayerRequest$RankUpdateRequest.class +me\devkevin\api\AbstractRequestProcessor.class +me\devkevin\util\MapUtil.class +me\devkevin\socket\AbstractBukkitCallback.class +me\devkevin\api\Callback.class +me\devkevin\socket\WebSocketAPIProcessor.class +me\devkevin\util\wrapper\BanWrapper.class +me\devkevin\socket\impl\GlobalRequest.class +me\devkevin\profile\listener\ProfileListener.class +me\devkevin\socket\impl\PlayerRequest.class +me\devkevin\socket\impl\IPCheckRequest.class +me\devkevin\socket\impl\PunishHistoryRequest.class +me\devkevin\api\RequestProcessor.class +me\devkevin\api\Request.class +me\devkevin\util\StringUtil.class +me\devkevin\profile\manager\ProfileManager.class +me\devkevin\file\ConfigFile.class +me\devkevin\socket\impl\PlayerRequest$AltsRequest.class +me\devkevin\util\TimeUtil.class diff --git a/WebSocketAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/WebSocketAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst new file mode 100644 index 0000000..393d64e --- /dev/null +++ b/WebSocketAPI/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -0,0 +1,25 @@ +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\util\MapUtil.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\impl\JoinRequest.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\api\AbstractRequestProcessor.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\profile\listener\ProfileListener.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\impl\IPCheckRequest.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\util\Duration.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\WebSocketAPIProcessor.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\AbstractBukkitCallback.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\file\ConfigFile.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\api\ErrorCallback.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\api\Request.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\backend\HikariDatabase.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\impl\PunishmentRequest.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\impl\PlayerRequest.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\util\wrapper\BanWrapper.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\WebSocketAPI.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\api\AbstractCallback.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\api\RequestProcessor.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\profile\manager\ProfileManager.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\impl\PunishHistoryRequest.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\util\TimeUtil.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\profile\Profile.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\socket\impl\GlobalRequest.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\util\StringUtil.java +C:\Users\kevin\Desktop\Java Projects\WebSocketAPI\src\main\java\me\devkevin\api\Callback.java diff --git a/WebSocketAPI/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst b/WebSocketAPI/target/maven-status/maven-compiler-plugin/testCompile/default-testCompile/inputFiles.lst new file mode 100644 index 0000000..e69de29 diff --git a/WebSocketAPI/target/original-WebSocketAPI.jar b/WebSocketAPI/target/original-WebSocketAPI.jar new file mode 100644 index 0000000..80c1f5a Binary files /dev/null and b/WebSocketAPI/target/original-WebSocketAPI.jar differ