diff --git a/build.gradle b/build.gradle index 079a3250..e6197e7f 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'net.momirealms' -version = '1.3.0.14' +version = '1.3.0.15' repositories { mavenCentral() diff --git a/src/main/java/net/momirealms/customfishing/CustomFishing.java b/src/main/java/net/momirealms/customfishing/CustomFishing.java index 947faf1d..43aa1633 100644 --- a/src/main/java/net/momirealms/customfishing/CustomFishing.java +++ b/src/main/java/net/momirealms/customfishing/CustomFishing.java @@ -26,6 +26,8 @@ import net.momirealms.customfishing.commands.SellFishCommand; import net.momirealms.customfishing.helper.LibraryLoader; import net.momirealms.customfishing.helper.VersionHelper; import net.momirealms.customfishing.manager.*; +import net.momirealms.customfishing.object.Reflection; +import net.momirealms.customfishing.scheduler.Scheduler; import net.momirealms.customfishing.util.AdventureUtils; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; @@ -52,6 +54,7 @@ public final class CustomFishing extends JavaPlugin { private OffsetManager offsetManager; private StatisticsManager statisticsManager; private VersionHelper versionHelper; + private Scheduler scheduler; @Override public void onLoad() { @@ -76,9 +79,11 @@ public final class CustomFishing extends JavaPlugin { this.sellManager = new SellManager(this); this.bagDataManager = new BagDataManager(this); this.offsetManager = new OffsetManager(this); + this.scheduler = new Scheduler(this); this.reload(); this.registerCommands(); this.registerQuests(); + Reflection.load(); AdventureUtils.consoleMessage("[CustomFishing] Plugin Enabled!"); if (ConfigManager.bStats) new Metrics(this, 16648); if (ConfigManager.updateChecker) this.versionHelper.checkUpdate(); @@ -97,6 +102,7 @@ public final class CustomFishing extends JavaPlugin { if (this.sellManager != null) this.sellManager.disable(); if (this.statisticsManager != null) this.statisticsManager.disable(); if (this.dataManager != null) this.dataManager.disable(); + if (this.scheduler != null) scheduler.disable(); if (adventure != null) adventure.close(); } @@ -188,6 +194,10 @@ public final class CustomFishing extends JavaPlugin { public OffsetManager getOffsetManager() { return offsetManager; } + + public Scheduler getScheduler() { + return scheduler; + } public void reload() { ConfigManager.load(); diff --git a/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java b/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java index b99cf574..6412de20 100644 --- a/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java +++ b/src/main/java/net/momirealms/customfishing/data/storage/FileStorageImpl.java @@ -20,6 +20,7 @@ package net.momirealms.customfishing.data.storage; import net.momirealms.customfishing.CustomFishing; import net.momirealms.customfishing.data.PlayerSellData; import net.momirealms.customfishing.data.PlayerStatisticsData; +import net.momirealms.customfishing.manager.ConfigManager; import net.momirealms.customfishing.util.ConfigUtils; import net.momirealms.customfishing.util.InventoryUtils; import org.bukkit.Bukkit; @@ -59,7 +60,7 @@ public class FileStorageImpl implements DataStorageInterface { int size = config.getInt("size", 9); ItemStack[] itemStacks = InventoryUtils.getInventoryItems(contents); OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(uuid); - Inventory inventory = Bukkit.createInventory(null, size, "{CustomFishing_Bag_" + offlinePlayer.getName() + "}"); + Inventory inventory = InventoryUtils.createInventory(null, size, plugin.getIntegrationManager().getPlaceholderManager().parse(offlinePlayer, ConfigManager.fishingBagTitle)); if (itemStacks != null) inventory.setContents(itemStacks); return inventory; } diff --git a/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java b/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java index f3a21e1c..f4495a5b 100644 --- a/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java +++ b/src/main/java/net/momirealms/customfishing/data/storage/MySQLStorageImpl.java @@ -32,7 +32,10 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; +import java.util.Calendar; +import java.util.Map; +import java.util.Set; +import java.util.UUID; public class MySQLStorageImpl implements DataStorageInterface { @@ -80,14 +83,12 @@ public class MySQLStorageImpl implements DataStorageInterface { int size = rs.getInt(3); String contents = rs.getString(4); ItemStack[] itemStacks = InventoryUtils.getInventoryItems(contents); - if (plugin.getVersionHelper().isSpigot()) inventory = Bukkit.createInventory(null, size, AdventureUtils.replaceMiniMessage(ConfigManager.fishingBagTitle.replace("{player}", Optional.ofNullable(offlinePlayer.getName()).orElse("")))); - else inventory = Bukkit.createInventory(null, size, "{CustomFishing_Bag_" + offlinePlayer.getName() + "}"); + inventory = InventoryUtils.createInventory(null, size, plugin.getIntegrationManager().getPlaceholderManager().parse(offlinePlayer, ConfigManager.fishingBagTitle)); if (itemStacks != null) inventory.setContents(itemStacks); lockData(uuid, "fishingbag"); } else { - if (plugin.getVersionHelper().isSpigot()) inventory = Bukkit.createInventory(null, 9, AdventureUtils.replaceMiniMessage(ConfigManager.fishingBagTitle.replace("{player}", Optional.ofNullable(offlinePlayer.getName()).orElse("")))); - else inventory = Bukkit.createInventory(null, 9, "{CustomFishing_Bag_" + offlinePlayer.getName() + "}"); + inventory = InventoryUtils.createInventory(null, 9, plugin.getIntegrationManager().getPlaceholderManager().parse(offlinePlayer, ConfigManager.fishingBagTitle)); insertBagData(uuid, InventoryUtils.toBase64(inventory.getContents())); } } catch (SQLException e) { diff --git a/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java b/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java index f1d359a5..1798d6ce 100644 --- a/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java +++ b/src/main/java/net/momirealms/customfishing/fishing/competition/Competition.java @@ -28,6 +28,7 @@ import net.momirealms.customfishing.manager.ConfigManager; import net.momirealms.customfishing.manager.MessageManager; import net.momirealms.customfishing.util.AdventureUtils; import org.bukkit.Bukkit; +import org.bukkit.OfflinePlayer; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; @@ -211,7 +212,7 @@ public class Competition { return competitionConfig; } - public String getPlayerRank(Player player) { + public String getPlayerRank(OfflinePlayer player) { return Optional.ofNullable(ranking.getPlayerRank(player.getName())).orElse(MessageManager.noRank); } @@ -219,7 +220,7 @@ public class Competition { return remainingTime; } - public double getScore(Player player) { + public double getScore(OfflinePlayer player) { return Optional.ofNullable(ranking.getCompetitionPlayer(player.getName())).orElse(CompetitionPlayer.emptyPlayer).getScore(); } diff --git a/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java b/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java index ac381518..844b7fbd 100644 --- a/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java +++ b/src/main/java/net/momirealms/customfishing/integration/papi/PlaceholderManager.java @@ -22,7 +22,7 @@ import net.momirealms.customfishing.fishing.competition.Competition; import net.momirealms.customfishing.manager.MessageManager; import net.momirealms.customfishing.object.Function; import org.bukkit.Bukkit; -import org.bukkit.entity.Player; +import org.bukkit.OfflinePlayer; import java.util.ArrayList; import java.util.List; @@ -61,16 +61,15 @@ public class PlaceholderManager extends Function { if (this.statisticsPapi != null) statisticsPapi.unregister(); } - public String parse(Player player, String text) { + public String parse(OfflinePlayer player, String text) { if (hasPlaceholderAPI) { return ParseUtil.setPlaceholders(player, parseInner(player, text)); - } - else { + } else { return parseInner(player, text); } } - public String parseInner(Player player, String text) { + public String parseInner(OfflinePlayer player, String text) { List papis = detectBetterPlaceholders(text); for (String papi : papis) { text = text.replace(papi, parseSingleInner(player, papi)); @@ -78,11 +77,10 @@ public class PlaceholderManager extends Function { return text; } - public String parseSinglePlaceholder(Player player, String placeholder) { + public String parseSinglePlaceholder(OfflinePlayer player, String placeholder) { if (placeholder.startsWith("{")) { return parseSingleInner(player, placeholder); - } - else if (hasPlaceholderAPI) { + } else if (hasPlaceholderAPI) { return ParseUtil.setPlaceholders(player, placeholder); } return placeholder; @@ -113,7 +111,7 @@ public class PlaceholderManager extends Function { return hasPlaceholderAPI ? detectAllPlaceholders(text) : detectBetterPlaceholders(text); } - public String parseSingleInner(Player player, String placeholder) { + public String parseSingleInner(OfflinePlayer player, String placeholder) { switch (placeholder) { case "{player}" -> { return player.getName(); diff --git a/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java b/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java index 061b99c2..574abac3 100644 --- a/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java +++ b/src/main/java/net/momirealms/customfishing/manager/BagDataManager.java @@ -17,19 +17,15 @@ package net.momirealms.customfishing.manager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.WrappedChatComponent; import de.tr7zw.changeme.nbtapi.NBTCompound; import de.tr7zw.changeme.nbtapi.NBTItem; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.momirealms.customfishing.CustomFishing; import net.momirealms.customfishing.listener.InventoryListener; import net.momirealms.customfishing.listener.JoinQuitListener; import net.momirealms.customfishing.listener.WindowPacketListener; import net.momirealms.customfishing.object.InventoryFunction; import net.momirealms.customfishing.util.AdventureUtils; +import net.momirealms.customfishing.util.InventoryUtils; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; @@ -150,26 +146,6 @@ public class BagDataManager extends InventoryFunction { } } - @Override - public void onWindowTitlePacketSend(PacketContainer packet, Player receiver) { - StructureModifier wrappedChatComponentStructureModifier = packet.getChatComponents(); - WrappedChatComponent component = wrappedChatComponentStructureModifier.getValues().get(0); - String windowTitleJson = component.getJson(); - if (windowTitleJson.startsWith("{\"text\":\"{CustomFishing_Bag_")) { - String player = windowTitleJson.substring(28, windowTitleJson.length() - 3); - String text = ConfigManager.fishingBagTitle.replace("{player}", player); - wrappedChatComponentStructureModifier.write(0, - WrappedChatComponent.fromJson( - GsonComponentSerializer.gson().serialize( - MiniMessage.miniMessage().deserialize( - AdventureUtils.replaceLegacy(text) - ) - ) - ) - ); - } - } - @Override public void onClickInventory(InventoryClickEvent event) { final Player player = (Player) event.getWhoClicked(); @@ -178,18 +154,16 @@ public class BagDataManager extends InventoryFunction { ItemStack currentItem = event.getCurrentItem(); if (currentItem == null || currentItem.getType() == Material.AIR) return; NBTItem nbtItem = new NBTItem(currentItem); - if (!nbtItem.hasTag("CustomFishing") && !ConfigManager.bagWhiteListItems.contains(currentItem.getType())) { - event.setCancelled(true); - return; - } NBTCompound nbtCompound = nbtItem.getCompound("CustomFishing"); - if (nbtCompound == null) { + if (nbtCompound == null && !ConfigManager.bagWhiteListItems.contains(currentItem.getType())) { event.setCancelled(true); return; } - String type = nbtCompound.getString("type"); - if (!ConfigManager.canStoreLoot && type.equals("loot")) { - event.setCancelled(true); + if (nbtCompound != null) { + String type = nbtCompound.getString("type"); + if (!ConfigManager.canStoreLoot && type.equals("loot")) { + event.setCancelled(true); + } } } } @@ -231,7 +205,7 @@ public class BagDataManager extends InventoryFunction { } if (size * 9 != inventory.getSize()) { ItemStack[] itemStacks = inventory.getContents(); - Inventory newInv = plugin.getVersionHelper().isSpigot() ? Bukkit.createInventory(null, size * 9, AdventureUtils.replaceMiniMessage(ConfigManager.fishingBagTitle.replace("{player}", owner.getName()))) : Bukkit.createInventory(null, size * 9, "{CustomFishing_Bag_" + owner.getName() + "}"); + Inventory newInv = InventoryUtils.createInventory(null, size * 9, plugin.getIntegrationManager().getPlaceholderManager().parse(owner, ConfigManager.fishingBagTitle)); newInv.setContents(itemStacks); dataMap.put(owner.getUniqueId(), newInv); viewer.openInventory(newInv); diff --git a/src/main/java/net/momirealms/customfishing/manager/SellManager.java b/src/main/java/net/momirealms/customfishing/manager/SellManager.java index 71d55cb9..68a5d41e 100644 --- a/src/main/java/net/momirealms/customfishing/manager/SellManager.java +++ b/src/main/java/net/momirealms/customfishing/manager/SellManager.java @@ -17,15 +17,10 @@ package net.momirealms.customfishing.manager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.WrappedChatComponent; import de.tr7zw.changeme.nbtapi.NBTCompound; import de.tr7zw.changeme.nbtapi.NBTItem; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; -import net.kyori.adventure.text.minimessage.MiniMessage; -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.momirealms.customfishing.CustomFishing; import net.momirealms.customfishing.api.event.SellFishEvent; import net.momirealms.customfishing.data.PlayerSellData; @@ -36,6 +31,7 @@ import net.momirealms.customfishing.listener.WindowPacketListener; import net.momirealms.customfishing.object.InventoryFunction; import net.momirealms.customfishing.util.AdventureUtils; import net.momirealms.customfishing.util.ConfigUtils; +import net.momirealms.customfishing.util.InventoryUtils; import net.momirealms.customfishing.util.ItemStackUtils; import net.objecthunter.exp4j.Expression; import net.objecthunter.exp4j.ExpressionBuilder; @@ -459,23 +455,6 @@ public class SellManager extends InventoryFunction { return playerSellData.getMoney(); } - @Override - public void onWindowTitlePacketSend(PacketContainer packet, Player player) { - StructureModifier wrappedChatComponentStructureModifier = packet.getChatComponents(); - WrappedChatComponent component = wrappedChatComponentStructureModifier.getValues().get(0); - if (component.getJson().equals("{\"text\":\"{CustomFishing_Sell}\"}")) { - wrappedChatComponentStructureModifier.write(0, - WrappedChatComponent.fromJson( - GsonComponentSerializer.gson().serialize( - MiniMessage.miniMessage().deserialize( - AdventureUtils.replaceLegacy(plugin.getIntegrationManager().getPlaceholderManager().parse(player, SellManager.title)) - ) - ) - ) - ); - } - } - public class SellGUI implements InventoryHolder { private final Inventory inventory; @@ -488,7 +467,7 @@ public class SellManager extends InventoryFunction { public SellGUI(Player player) { this.player = player; - this.inventory = plugin.getVersionHelper().isSpigot() ? Bukkit.createInventory(this, guiSize, AdventureUtils.replaceMiniMessage(SellManager.title.replace("{player}", player.getName()))) : Bukkit.createInventory(this, guiSize, "{CustomFishing_Sell}"); + this.inventory = InventoryUtils.createInventory(this, guiSize, plugin.getIntegrationManager().getPlaceholderManager().parse(player, SellManager.title)); } public void open() { diff --git a/src/main/java/net/momirealms/customfishing/object/Reflection.java b/src/main/java/net/momirealms/customfishing/object/Reflection.java new file mode 100644 index 00000000..3dd55f8a --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/object/Reflection.java @@ -0,0 +1,28 @@ +package net.momirealms.customfishing.object; + +import net.momirealms.customfishing.CustomFishing; + +public class Reflection { + + public static Class textComponentClass; + public static Class componentClass; + public static Class bukkitClass; + public static Class textColorClass; + public static Class keyClass; + public static Class textDecorationClass; + public static Class textDecorationStateClass; + + public static void load() { + if (CustomFishing.getInstance().getVersionHelper().isSpigot()) return; + try { + textComponentClass = Class.forName("net;kyori;adventure;text;TextComponent".replace(";", ".")); + componentClass = Class.forName("net;kyori;adventure;text;Component".replace(";", ".")); + bukkitClass = Class.forName("org;bukkit;Bukkit".replace(";", ".")); + textColorClass = Class.forName("net;kyori;adventure;text;format;TextColor".replace(";", ".")); + keyClass = Class.forName("net;kyori;adventure;key;Key".replace(";", ".")); + textDecorationClass = Class.forName("net;kyori;adventure;text;format;TextDecoration".replace(";", ".")); + textDecorationStateClass = Class.forName("net;kyori;adventure;text;format;TextDecoration$State".replace(";", ".")); + } catch (ClassNotFoundException ignored) { + } + } +} \ No newline at end of file diff --git a/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java b/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java new file mode 100644 index 00000000..7df1801c --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/scheduler/BukkitSchedulerImpl.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customfishing.scheduler; + +import net.momirealms.customfishing.CustomFishing; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +public class BukkitSchedulerImpl implements SchedulerPlatform { + + private final CustomFishing plugin; + + public BukkitSchedulerImpl(CustomFishing plugin) { + this.plugin = plugin; + } + + @Override + public Future callSyncMethod(@NotNull Callable task) { + return Bukkit.getScheduler().callSyncMethod(plugin, task); + } + + @Override + public void runTask(Runnable runnable) { + Bukkit.getScheduler().runTask(plugin, runnable); + } +} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/Scheduler.java b/src/main/java/net/momirealms/customfishing/scheduler/Scheduler.java new file mode 100644 index 00000000..8cbdb363 --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/scheduler/Scheduler.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customfishing.scheduler; + +import net.momirealms.customfishing.CustomFishing; +import net.momirealms.customfishing.object.Function; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.*; + +public class Scheduler extends Function { + + private final ScheduledThreadPoolExecutor schedule; + private final SchedulerPlatform schedulerPlatform; + + public Scheduler(CustomFishing plugin) { + this.schedulerPlatform = new BukkitSchedulerImpl(plugin); + this.schedule = new ScheduledThreadPoolExecutor(1); + this.schedule.setMaximumPoolSize(2); + this.schedule.setKeepAliveTime(10, TimeUnit.SECONDS); + this.schedule.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); + } + + @Override + public void disable() { + this.schedule.shutdown(); + } + + public ScheduledFuture runTaskAsyncLater(Runnable runnable, long delay, TimeUnit timeUnit) { + return this.schedule.schedule(runnable, delay, timeUnit); + } + + public void runTaskAsync(Runnable runnable) { + this.schedule.execute(runnable); + } + + public void runTask(Runnable runnable) { + this.schedulerPlatform.runTask(runnable); + } + + public Future callSyncMethod(@NotNull Callable task) { + return this.schedulerPlatform.callSyncMethod(task); + } + + public ScheduledFuture runTaskTimerAsync(Runnable runnable, long delay, long interval, TimeUnit timeUnit) { + return this.schedule.scheduleAtFixedRate(runnable, delay, interval, timeUnit); + } +} diff --git a/src/main/java/net/momirealms/customfishing/scheduler/SchedulerPlatform.java b/src/main/java/net/momirealms/customfishing/scheduler/SchedulerPlatform.java new file mode 100644 index 00000000..efacf82c --- /dev/null +++ b/src/main/java/net/momirealms/customfishing/scheduler/SchedulerPlatform.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) <2022> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package net.momirealms.customfishing.scheduler; + +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.Callable; +import java.util.concurrent.Future; + +public interface SchedulerPlatform { + + Future callSyncMethod(@NotNull Callable task); + + void runTask(Runnable runnable); +} diff --git a/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java b/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java index c4b22ad5..0678e2af 100644 --- a/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java +++ b/src/main/java/net/momirealms/customfishing/util/AdventureUtils.java @@ -21,16 +21,23 @@ import net.kyori.adventure.audience.Audience; import net.kyori.adventure.key.Key; import net.kyori.adventure.sound.Sound; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.TextColor; +import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.title.Title; import net.momirealms.customfishing.CustomFishing; +import net.momirealms.customfishing.object.Reflection; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.time.Duration; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -249,4 +256,61 @@ public class AdventureUtils { } return result; } + + public static Object getPaperComponent(Component component) { + try { + Object newComponent; + if (component instanceof TextComponent textComponent) { + Method textComponentMethod = Reflection.componentClass.getMethod("text", String.class); + newComponent = textComponentMethod.invoke(null, textComponent.content()); + TextColor textColor = textComponent.color(); + if (textColor != null) { + String hex = textColor.asHexString(); + Method setColorMethod = Reflection.textComponentClass.getMethod("color", Reflection.textColorClass); + Method getColorFromHex = Reflection.textColorClass.getMethod("fromHexString", String.class); + Object hexColor = getColorFromHex.invoke(null, hex); + newComponent = setColorMethod.invoke(newComponent, hexColor); + } + Key fontKey = textComponent.font(); + if (fontKey != null) { + String namespacedKey = fontKey.asString(); + Method setKeyMethod = Reflection.textComponentClass.getMethod("font", Reflection.keyClass); + Method keyMethod = Reflection.keyClass.getMethod("key", String.class); + Object key = keyMethod.invoke(null, namespacedKey); + newComponent = setKeyMethod.invoke(newComponent, key); + } + for (Map.Entry entry : textComponent.decorations().entrySet()) { + String dec = entry.getKey().name(); + Method getTextDecoration = Reflection.textDecorationClass.getDeclaredMethod("valueOf", String.class); + Object textDecoration = getTextDecoration.invoke(null, dec); + String stat = entry.getValue().name(); + Method getState = Reflection.textDecorationStateClass.getDeclaredMethod("valueOf", String.class); + Object state = getState.invoke(null, stat); + Method applyDecorationMethod = Reflection.textComponentClass.getMethod("decoration", Reflection.textDecorationClass, Reflection.textDecorationStateClass); + newComponent = applyDecorationMethod.invoke(newComponent, textDecoration, state); + } + newComponent = setChildrenComponents(textComponent, newComponent); + } else { + Method textComponentMethod = Reflection.componentClass.getMethod("text", String.class); + newComponent = textComponentMethod.invoke(null, ""); + newComponent = setChildrenComponents(component, newComponent); + } + return newComponent; + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { + exception.printStackTrace(); + return null; + } + } + + private static Object setChildrenComponents(Component component, Object newComponent) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + List children = new ArrayList<>(); + for (Component child : component.children()) { + children.add(getPaperComponent(child)); + } + if (children.size() != 0) { + Method childrenMethod = Reflection.componentClass.getMethod("children", List.class); + newComponent = childrenMethod.invoke(newComponent, children); + } + return newComponent; + } } diff --git a/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java b/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java index a147ca91..b069bb44 100644 --- a/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java +++ b/src/main/java/net/momirealms/customfishing/util/InventoryUtils.java @@ -17,6 +17,12 @@ package net.momirealms.customfishing.util; +import net.kyori.adventure.text.Component; +import net.momirealms.customfishing.CustomFishing; +import net.momirealms.customfishing.object.Reflection; +import org.bukkit.Bukkit; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; import org.bukkit.util.io.BukkitObjectInputStream; import org.bukkit.util.io.BukkitObjectOutputStream; @@ -27,6 +33,8 @@ import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; public class InventoryUtils { @@ -115,4 +123,29 @@ public class InventoryUtils { } return stacks; } + + @NotNull + public static Inventory createInventory(InventoryHolder inventoryHolder, int size, Component component) { + try { + Method createInvMethod = Reflection.bukkitClass.getMethod("createInventory", InventoryHolder.class, int.class, Reflection.componentClass); + return (Inventory) createInvMethod.invoke(null, inventoryHolder, size, AdventureUtils.getPaperComponent(component)); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { + exception.printStackTrace(); + throw new RuntimeException("Failed to create inventory"); + } + } + + public static Inventory createInventory(InventoryHolder inventoryHolder, int size, String title) { + if (CustomFishing.getInstance().getVersionHelper().isSpigot()) { + return Bukkit.createInventory(inventoryHolder, size, AdventureUtils.replaceMiniMessage(title)); + } else { + try { + Method createInvMethod = Reflection.bukkitClass.getMethod("createInventory", InventoryHolder.class, int.class, Reflection.componentClass); + return (Inventory) createInvMethod.invoke(null, inventoryHolder, size, AdventureUtils.getPaperComponent(AdventureUtils.getComponentFromMiniMessage(title))); + } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException exception) { + exception.printStackTrace(); + throw new RuntimeException("Failed to create inventory"); + } + } + } } diff --git a/src/main/resources/competitions/default.yml b/src/main/resources/competitions/default.yml index 8b636432..5c5c715a 100644 --- a/src/main/resources/competitions/default.yml +++ b/src/main/resources/competitions/default.yml @@ -1,5 +1,4 @@ example: - # TOTAL_SCORE # CATCH_AMOUNT # MAX_SIZE