From cf435580368107d6cc88ebbb2e620f262ad66612 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Sun, 17 Aug 2025 09:55:31 +0200 Subject: [PATCH 01/16] added * for itemflag hiding in settings item --- pom.xml | 2 +- .../data/professions/ProfessionSettings.java | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 9d6f4d9..77878d8 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 16 - 1.1.1-R0.3-SNAPSHOT + 1.1.1-R0.7-SNAPSHOT diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java index d190baa..dc14c68 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java @@ -92,8 +92,12 @@ public ProfessionSettings(String profession, ConfigurationSection config) { List flagsList = config.getStringList("settings.icon.optionals.flags"); if(!flagsList.isEmpty()) { flags = new HashSet<>(); - for (String flag : flagsList) { - flags.add(ItemFlag.valueOf(flag)); + if(flagsList.contains("*")) { + flags.addAll(Arrays.asList(ItemFlag.values())); + } else { + for (String flag : flagsList) { + flags.add(ItemFlag.valueOf(flag)); + } } } color = config.getString("settings.icon.optionals.color"); @@ -147,8 +151,12 @@ public ProfessionSettings(String profession, DeserializationWorker dw) { if (optionalIconSettings.get("flags") != null) { flags = new HashSet<>(); List flagsList = (List) optionalIconSettings.get("flags"); - for (String flag : flagsList) { - flags.add(ItemFlag.valueOf(flag)); + if(flagsList.contains("*")) { + flags.addAll(Arrays.asList(ItemFlag.values())); + } else { + for (String flag : flagsList) { + flags.add(ItemFlag.valueOf(flag)); + } } } if (optionalIconSettings.get("color") != null) From b7cef4d8135db297caeee12f4b01db12a705217c Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Sun, 17 Aug 2025 09:55:31 +0200 Subject: [PATCH 02/16] added * for itemflag hiding in settings item --- pom.xml | 2 +- .../data/professions/ProfessionSettings.java | 16 ++++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 211386f..0049314 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ 16 - 1.1.1-R0.3-SNAPSHOT + 1.1.1-R0.7-SNAPSHOT diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java index d190baa..dc14c68 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java @@ -92,8 +92,12 @@ public ProfessionSettings(String profession, ConfigurationSection config) { List flagsList = config.getStringList("settings.icon.optionals.flags"); if(!flagsList.isEmpty()) { flags = new HashSet<>(); - for (String flag : flagsList) { - flags.add(ItemFlag.valueOf(flag)); + if(flagsList.contains("*")) { + flags.addAll(Arrays.asList(ItemFlag.values())); + } else { + for (String flag : flagsList) { + flags.add(ItemFlag.valueOf(flag)); + } } } color = config.getString("settings.icon.optionals.color"); @@ -147,8 +151,12 @@ public ProfessionSettings(String profession, DeserializationWorker dw) { if (optionalIconSettings.get("flags") != null) { flags = new HashSet<>(); List flagsList = (List) optionalIconSettings.get("flags"); - for (String flag : flagsList) { - flags.add(ItemFlag.valueOf(flag)); + if(flagsList.contains("*")) { + flags.addAll(Arrays.asList(ItemFlag.values())); + } else { + for (String flag : flagsList) { + flags.add(ItemFlag.valueOf(flag)); + } } } if (optionalIconSettings.get("color") != null) From edcfa80c5726f3439dc1a73267ee0beb386c746f Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Sun, 17 Aug 2025 11:29:37 +0200 Subject: [PATCH 03/16] added mechanic to disable bukkit recipes --- .../fusion/cfg/BukkitRecipeWrapper.java | 63 +++++++++++++++++++ .../studio/magemonkey/fusion/cfg/Cfg.java | 10 +++ 2 files changed, 73 insertions(+) create mode 100644 src/main/java/studio/magemonkey/fusion/cfg/BukkitRecipeWrapper.java diff --git a/src/main/java/studio/magemonkey/fusion/cfg/BukkitRecipeWrapper.java b/src/main/java/studio/magemonkey/fusion/cfg/BukkitRecipeWrapper.java new file mode 100644 index 0000000..5080b8c --- /dev/null +++ b/src/main/java/studio/magemonkey/fusion/cfg/BukkitRecipeWrapper.java @@ -0,0 +1,63 @@ +package studio.magemonkey.fusion.cfg; + +import org.bukkit.Bukkit; +import org.bukkit.Keyed; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.Recipe; +import studio.magemonkey.fusion.Fusion; + +import java.util.ArrayList; +import java.util.List; + +public class BukkitRecipeWrapper { + + public static List getRecipeKeysForMaterials(List material) { + + List entries = new ArrayList<>(); + + for (Material mat : material) { + if (mat.isAir()) continue; + ItemStack stack = new ItemStack(mat); + var recipes = Bukkit.getRecipesFor(stack); + if (recipes.isEmpty()) { + Fusion.getInstance().error("No recipes found for material: " + mat); + continue; + } + for(Recipe recipe : recipes) { + if (recipe instanceof Keyed keyed) { + NamespacedKey key = keyed.getKey(); + entries.add(key); + } else { + Bukkit.getLogger().info("Recipe has no key (likely a custom non-keyed recipe)."); + } + } + } + return entries; + } + + public static void enableBukkitRecipes(List recipes) { + for (NamespacedKey recipe : recipes) { + Recipe bukkitRecipe = Fusion.getInstance().getServer().getRecipe(recipe); + if (bukkitRecipe != null) { + Fusion.getInstance().getServer().addRecipe(bukkitRecipe); + Bukkit.getLogger().info("Enabled Bukkit recipe with key: " + recipe); + } else { + Fusion.getInstance().error("Bukkit recipe with key " + recipe + " not found."); + } + } + } + + public static void disableBukkitRecipes(List recipes) { + for (NamespacedKey recipe : recipes) { + Recipe bukkitRecipe = Fusion.getInstance().getServer().getRecipe(recipe); + if (bukkitRecipe != null) { + Fusion.getInstance().getServer().removeRecipe(recipe); + Bukkit.getLogger().info("Disabled Bukkit recipe with key: " + recipe); + } else { + Fusion.getInstance().error("Bukkit recipe with key " + recipe + " not found."); + } + } + } +} diff --git a/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java b/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java index f9d6377..b82d1b9 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java @@ -1,5 +1,7 @@ package studio.magemonkey.fusion.cfg; +import org.bukkit.Material; +import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; @@ -8,8 +10,10 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; public final class Cfg { public static String recursive = "floor(n+300^(n/7)^2)"; @@ -28,6 +32,7 @@ public final class Cfg { public static String finishMessage = "&aYou have crafting items ready for pickup! ($)"; + public static List disabledVanillaRecipes = new ArrayList<>(); // No usage inside of Cfg, just used for default values. The actual values are stored in SQLManager.class private static final DatabaseType storageType = DatabaseType.LOCAL; @@ -89,6 +94,7 @@ private static void addDefs(FileConfiguration cfg) { if (!cfg.isSet("storage.password")) cfg.set("storage.password", storagePassword); if (!cfg.isSet("useCustomFormula")) cfg.set("useCustomFormula", useCustomFormula); + if (!cfg.isSet("disabled_vanilla_recipes")) cfg.set("disabled_vanilla_recipes", disabledVanillaRecipes); } public static void init() { @@ -111,6 +117,8 @@ public static void init() { hideRecipesLimitReached = cfg.getBoolean("hideRecipesDefault.recipeLimitReached"); useCustomFormula = cfg.getBoolean("useCustomFormula"); + List materials = cfg.getStringList("disabled_vanilla_recipes").stream().map(x -> Material.valueOf(x.toUpperCase())).toList(); + disabledVanillaRecipes = BukkitRecipeWrapper.getRecipeKeysForMaterials(materials); migrateOldTypes(cfg); } @@ -124,6 +132,8 @@ private static void reload(FileConfiguration cfg, File file) { cfg.save(file); // Load the config again cfg.load(file); + + BukkitRecipeWrapper.disableBukkitRecipes(disabledVanillaRecipes); } catch (Exception e) { Fusion.getInstance().getLogger().warning("Can't load config file: " + file + ":" + e.getMessage()); } From 26adbf5c32a0e348972a453db10f6a434cc0f2f7 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Fri, 5 Sep 2025 11:58:52 +0200 Subject: [PATCH 04/16] added condition line next to requirement line to define what will be taken and what is just a condition at all --- .../fusion/cfg/CraftingRequirementsCfg.java | 4 ++++ .../fusion/data/recipes/CalculatedRecipe.java | 11 ++++++++--- src/main/resources/lang/CraftingRequirements.yml | 4 ++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/cfg/CraftingRequirementsCfg.java b/src/main/java/studio/magemonkey/fusion/cfg/CraftingRequirementsCfg.java index aef918d..e593a34 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/CraftingRequirementsCfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/CraftingRequirementsCfg.java @@ -29,6 +29,10 @@ public static String getCraftingRequirementLine(String path) { return ChatUT.hexString(config.getString(path + ".requirementLine", "&7Crafting Requirements")); } + public static String getCraftingConditionLine(String path) { + return ChatUT.hexString(config.getString(path + ".conditionLine", "&7Crafting Conditions")); + } + public static String getBossBarTitle(ItemStack item) { String itemName = item.getItemMeta() != null && item.getItemMeta().hasDisplayName() ? item.getItemMeta().getDisplayName() : ChatUT.serialize(Component.translatable(item.getTranslationKey())); diff --git a/src/main/java/studio/magemonkey/fusion/data/recipes/CalculatedRecipe.java b/src/main/java/studio/magemonkey/fusion/data/recipes/CalculatedRecipe.java index 12828b1..c63dda9 100644 --- a/src/main/java/studio/magemonkey/fusion/data/recipes/CalculatedRecipe.java +++ b/src/main/java/studio/magemonkey/fusion/data/recipes/CalculatedRecipe.java @@ -219,6 +219,10 @@ public static CalculatedRecipe create(Recipe recipe, if (masteryLine != null) lore.append(masteryLine).append('\n'); if (limitLine != null) lore.append(limitLine).append('\n'); if (!conditionLines.isEmpty()) { + String conditionLine = CraftingRequirementsCfg.getCraftingConditionLine("recipes"); + if (!conditionLine.isEmpty()) { + lore.append(conditionLine).append('\n'); + } for (Map.Entry e : conditionLines) { lore.append('\n').append(e.getValue()); } @@ -327,13 +331,14 @@ public static boolean isSimilar(ItemStack is1, ItemStack is2) { } } - // Check for flags - if (!im1.getItemFlags().isEmpty()) { + // TODO make sure this works with Divinity's specific update logic. Until then, skip it. + // Divinity Logic -> https://github.com/magemonkeystudio/divinity/blob/dev/src/main/java/studio/magemonkey/divinity/manager/listener/object/ItemUpdaterListener.java#L95 + /*if (!im1.getItemFlags().isEmpty()) { if (im1.getItemFlags().size() != im2.getItemFlags().size()) isValid = false; for (ItemFlag flag : im1.getItemFlags()) { if (!im2.getItemFlags().contains(flag)) isValid = false; } - } + }*/ // Check for custom model data if (im1.hasCustomModelData() && im2.hasCustomModelData()) { diff --git a/src/main/resources/lang/CraftingRequirements.yml b/src/main/resources/lang/CraftingRequirements.yml index d19c298..8ef2529 100644 --- a/src/main/resources/lang/CraftingRequirements.yml +++ b/src/main/resources/lang/CraftingRequirements.yml @@ -4,6 +4,8 @@ unfulfilled: "&c&l✗&r" recipes: # The line that is displayed above the crafting requirements requirementLine: "&7Crafting Requirements" + # The line that is displayed above the crafting conditions + conditionLine: "&7Crafting Conditions" # The bossbar that will be shown when manual crafting is enabled bossbar: '&5Crafting $...' # The message that is displayed when the player has learned the recipe @@ -66,6 +68,8 @@ recipes: professions: # The line that is displayed above the crafting requirements requirementLine: "&7Crafting Requirements" + # The line that is displayed above the crafting conditions + conditionLine: "&7Crafting Conditions" # The message that is displayed when the player has unlocked the profession learned: 'true': "&aYou have unlocked this profession" From 8b693f9499bb507b5a7b015f6563e22d43edb70f Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Fri, 5 Sep 2025 11:59:03 +0200 Subject: [PATCH 05/16] added auto-joining --- .../studio/magemonkey/fusion/cfg/Cfg.java | 17 ++++++++++ .../fusion/commands/CommandMechanics.java | 23 +++++++------ .../magemonkey/fusion/commands/Commands.java | 32 +++++++++++-------- .../professions/ProfessionConditions.java | 2 +- 4 files changed, 47 insertions(+), 27 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java b/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java index b82d1b9..e76f3e4 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/Cfg.java @@ -2,14 +2,20 @@ import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import studio.magemonkey.fusion.Fusion; import studio.magemonkey.fusion.cfg.sql.DatabaseType; +import studio.magemonkey.fusion.commands.CommandMechanics; +import studio.magemonkey.fusion.data.player.FusionPlayer; +import studio.magemonkey.fusion.data.player.PlayerLoader; +import studio.magemonkey.fusion.gui.BrowseGUI; import java.io.File; import java.io.IOException; +import java.sql.Array; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -33,6 +39,7 @@ public final class Cfg { public static String finishMessage = "&aYou have crafting items ready for pickup! ($)"; public static List disabledVanillaRecipes = new ArrayList<>(); + public static List autoJoinProfessions = new ArrayList<>(); // No usage inside of Cfg, just used for default values. The actual values are stored in SQLManager.class private static final DatabaseType storageType = DatabaseType.LOCAL; @@ -95,6 +102,7 @@ private static void addDefs(FileConfiguration cfg) { if (!cfg.isSet("useCustomFormula")) cfg.set("useCustomFormula", useCustomFormula); if (!cfg.isSet("disabled_vanilla_recipes")) cfg.set("disabled_vanilla_recipes", disabledVanillaRecipes); + if (!cfg.isSet("auto_join_professions")) cfg.set("auto_join_professions", autoJoinProfessions); } public static void init() { @@ -119,6 +127,7 @@ public static void init() { useCustomFormula = cfg.getBoolean("useCustomFormula"); List materials = cfg.getStringList("disabled_vanilla_recipes").stream().map(x -> Material.valueOf(x.toUpperCase())).toList(); disabledVanillaRecipes = BukkitRecipeWrapper.getRecipeKeysForMaterials(materials); + autoJoinProfessions = cfg.getStringList("auto_join_professions"); migrateOldTypes(cfg); } @@ -175,4 +184,12 @@ public static boolean setDatabaseType(DatabaseType type) { return false; } } + + public static void autoJoinProfessions(Player player) { + FusionPlayer fp = PlayerLoader.getPlayer(player); + for (String professionId : autoJoinProfessions) { + if(fp.hasProfession(professionId) && fp.hasJoined(professionId)) continue; + BrowseGUI.joinProfession(player, ProfessionsCfg.getGuiMap().get(professionId)); + } + } } diff --git a/src/main/java/studio/magemonkey/fusion/commands/CommandMechanics.java b/src/main/java/studio/magemonkey/fusion/commands/CommandMechanics.java index 8e47eee..b1413b5 100644 --- a/src/main/java/studio/magemonkey/fusion/commands/CommandMechanics.java +++ b/src/main/java/studio/magemonkey/fusion/commands/CommandMechanics.java @@ -37,8 +37,8 @@ public static void useProfession(CommandSender sender, String[] args) { return; } String[] professionArgs = args[1].split(":"); - String profession = professionArgs[0]; - Category category = null; + String profession = professionArgs[0]; + Category category = null; ProfessionGuiRegistry eq = ProfessionsCfg.getGuiMap().get(profession); @@ -111,8 +111,8 @@ public static void useProfession(CommandSender sender, String[] args) { public static void masterProfession(CommandSender sender, String[] args) { if (sender instanceof Player player) { - String guiName = args[1]; - CraftingTable table = ProfessionsCfg.getTable(guiName); + String guiName = args[1]; + CraftingTable table = ProfessionsCfg.getTable(guiName); if (table == null) { CodexEngine.get().getMessageUtil().sendMessage("fusion.notACrafting", sender, @@ -175,8 +175,7 @@ public static void forgetProfession(CommandSender sender, new MessageData("sender", sender), new MessageData("craftingTable", table)); - Bukkit.getScheduler().runTaskLater(Fusion.getInstance(), - () -> confirmation.remove(player.getUniqueId().toString()), 15 * 20L); + Bukkit.getScheduler().runTaskLater(Fusion.getInstance(), () -> confirmation.remove(player.getUniqueId().toString()), 15 * 20L); } else { CodexEngine.get() @@ -357,7 +356,7 @@ public static void setProfessionExp(CommandSender sender, String[] args) { } try { - long exp = Long.parseLong(args[4]); + long exp = Long.parseLong(args[4]); long expBefore = FusionAPI.getPlayerManager().getPlayer(player).getExperience(profession); switch (args[1].toLowerCase()) { case "add" -> FusionAPI.getEventServices() @@ -406,7 +405,7 @@ public static void setProfessionLevel(CommandSender sender, String[] args) { } try { int levelBefore = FusionAPI.getPlayerManager().getPlayer(player).getLevel(profession); - int levelAfter = Integer.parseInt(args[4]); + int levelAfter = Integer.parseInt(args[4]); if (levelAfter <= 0) levelBefore = 1; long expBefore = (long) ProfessionsCfg.getTable(profession) @@ -550,8 +549,8 @@ public static void forceLeaveProfession(@NotNull CommandSender sender, String[] return; } - String professionName = args[2]; - CraftingTable table = ProfessionsCfg.getTable(professionName); + String professionName = args[2]; + CraftingTable table = ProfessionsCfg.getTable(professionName); if (table == null) { CodexEngine.get().getMessageUtil().sendMessage("fusion.notACrafting", sender, @@ -641,8 +640,8 @@ public static void forceMaster(@NotNull CommandSender sender, String[] args) { return; } - String professionName = args[2]; - CraftingTable table = ProfessionsCfg.getTable(professionName); + String professionName = args[2]; + CraftingTable table = ProfessionsCfg.getTable(professionName); if (table == null) { CodexEngine.get().getMessageUtil().sendMessage("fusion.notACrafting", sender, diff --git a/src/main/java/studio/magemonkey/fusion/commands/Commands.java b/src/main/java/studio/magemonkey/fusion/commands/Commands.java index 09698c0..50c5dc1 100644 --- a/src/main/java/studio/magemonkey/fusion/commands/Commands.java +++ b/src/main/java/studio/magemonkey/fusion/commands/Commands.java @@ -121,17 +121,21 @@ public List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if(!(sender instanceof Player player)) + return List.of(); + List entries = new ArrayList<>(); List professions = new ArrayList<>(); - if (sender instanceof Player) { - professions = new ArrayList<>(PlayerLoader.getPlayer(((Player) sender).getUniqueId()).getProfessions()); - } + professions = new ArrayList<>(PlayerLoader.getPlayer((player).getUniqueId()).getProfessions()); if (args.length == 1) { - if ("browse".startsWith(args[0])) entries.add("browse"); + if (sender.hasPermission("fusion.browse") + && "browse".startsWith(args[0])) entries.add("browse"); + if (confirmation.containsKey(player.getUniqueId().toString()) + && "confirm".startsWith(args[0])) entries.add("confirm"); if ("stats".startsWith(args[0])) entries.add("stats"); - if ("confirm".startsWith(args[0])) entries.add("confirm"); if ("use".startsWith(args[0])) entries.add("use"); - if ("master".startsWith(args[0])) entries.add("master"); + if (sender.hasPermission("fusion.master") && + "master".startsWith(args[0])) entries.add("master"); if ("forget".startsWith(args[0])) entries.add("forget"); if ("join".startsWith(args[0])) entries.add("join"); if (sender.hasPermission("fusion.admin.use") && "storage".startsWith(args[0])) @@ -154,8 +158,8 @@ public List onTabComplete(@NotNull CommandSender sender, } } else if (args.length == 2) { if (args[0].equalsIgnoreCase("use")) { - for (String name : professions.stream().map(Profession::getName).toList()) { - if (name.startsWith(args[1])) entries.add(name); + for (String profession : professions.stream().map(Profession::getName).toList()) { + if (ProfessionsCfg.getGuiMap().containsKey(profession) && profession.startsWith(args[1])) entries.add(profession); } if (sender.hasPermission("fusion.craft.use.categories") && args[1].contains(":")) { @@ -198,14 +202,14 @@ else if (sender.hasPermission("fusion.admin.force") && (args[0].equalsIgnoreCase("forcejoin") || args[0].equalsIgnoreCase("forceleave") || args[0].equalsIgnoreCase("forcestats") || args[0].equalsIgnoreCase("forcemaster") || args[0].equalsIgnoreCase("forceshow"))) { - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.getName().startsWith(args[1])) entries.add(player.getName()); + for (Player _player : Bukkit.getOnlinePlayers()) { + if (_player.getName().startsWith(args[1])) entries.add(_player.getName()); } } } else if (args.length == 3) { if (sender.hasPermission("fusion.admin.use") && args[0].equalsIgnoreCase("use")) { - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.getName().startsWith(args[2])) entries.add(player.getName()); + for (Player _player : Bukkit.getOnlinePlayers()) { + if (_player.getName().startsWith(args[2])) entries.add(_player.getName()); } } else if ((args[0].equalsIgnoreCase("exp") || args[0].equalsIgnoreCase("level")) && sender.hasPermission( "fusion.admin")) { @@ -224,8 +228,8 @@ else if (sender.hasPermission("fusion.admin.force") && } else if (args.length == 4) { if ((args[0].equalsIgnoreCase("exp") || args[0].equalsIgnoreCase("level")) && sender.hasPermission( "fusion.admin")) { - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.getName().startsWith(args[3])) entries.add(player.getName()); + for (Player _player : Bukkit.getOnlinePlayers()) { + if (_player.getName().startsWith(args[3])) entries.add(_player.getName()); } } } diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionConditions.java b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionConditions.java index 827b3b7..409ce59 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionConditions.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionConditions.java @@ -282,7 +282,7 @@ public boolean isValid(FusionPlayer player) { new MessageData("condition.name", null), }; - if (player.hasProfession(profession)) { + if (player.hasProfession(profession) && player.hasJoined(profession)) { _player.playSound(_player.getLocation(), Sound.BLOCK_ANVIL_PLACE, 1f, 1f); CodexEngine.get().getMessageUtil().sendMessage("fusion.browse.alreadyUnlocked", _player, data); return false; From 95c0b8a16299ef38735b785e996995e06757f940 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Fri, 5 Sep 2025 11:59:20 +0200 Subject: [PATCH 06/16] fixed some event services for joining/leaving professions --- src/main/java/studio/magemonkey/fusion/Fusion.java | 3 +++ .../api/events/services/ProfessionService.java | 13 +++++++++++-- .../fusion/data/professions/Profession.java | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/Fusion.java b/src/main/java/studio/magemonkey/fusion/Fusion.java index 6572bad..69b0198 100644 --- a/src/main/java/studio/magemonkey/fusion/Fusion.java +++ b/src/main/java/studio/magemonkey/fusion/Fusion.java @@ -190,6 +190,9 @@ private void runQueueTask() { @EventHandler public void onPlayerJoin(PlayerJoinEvent event) { PlayerLoader.loadPlayer(event.getPlayer()); + if(!Cfg.autoJoinProfessions.isEmpty()) { + Cfg.autoJoinProfessions(event.getPlayer()); + } if (Cfg.craftingQueue) { notifyForQueue(event.getPlayer()); } diff --git a/src/main/java/studio/magemonkey/fusion/api/events/services/ProfessionService.java b/src/main/java/studio/magemonkey/fusion/api/events/services/ProfessionService.java index f8ca68c..95d6a29 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/services/ProfessionService.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/services/ProfessionService.java @@ -8,12 +8,16 @@ import studio.magemonkey.fusion.Fusion; import studio.magemonkey.fusion.api.FusionAPI; import studio.magemonkey.fusion.api.events.*; +import studio.magemonkey.fusion.cfg.ProfessionsCfg; import studio.magemonkey.fusion.data.player.FusionPlayer; import studio.magemonkey.fusion.data.professions.Profession; import studio.magemonkey.fusion.data.recipes.CraftingTable; +import studio.magemonkey.fusion.util.ChatUT; import studio.magemonkey.fusion.util.ExperienceManager; import studio.magemonkey.fusion.util.PlayerUtil; +import java.util.Objects; + public class ProfessionService { /** @@ -27,8 +31,11 @@ public void joinProfession(String professionName, Player player, double moneyCos ProfessionJoinEvent event = new ProfessionJoinEvent(professionName, player); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { - event.getFusionPlayer() - .addProfession(new Profession(-1, player.getUniqueId(), professionName, 0, false, true)); + if(!event.getFusionPlayer().hasProfession(professionName)) { + event.getFusionPlayer().addProfession(new Profession(-1, player.getUniqueId(), professionName, 0, false, true)); + } else { + Objects.requireNonNull(event.getFusionPlayer().getProfession(professionName)).setJoined(true); + } if (moneyCost > 0) CodexEngine.get().getVault().take(player, moneyCost); if (expCost > 0) @@ -36,6 +43,7 @@ public void joinProfession(String professionName, Player player, double moneyCos MessageData[] data = { new MessageData("profession", professionName), + new MessageData("inventoryName", ChatUT.hexString(ProfessionsCfg.getTable(professionName).getInventoryName())), new MessageData("costs.money", moneyCost), new MessageData("costs.experience", expCost), new MessageData("unlocked", event.getFusionPlayer().getJoinedProfessions().size()), @@ -58,6 +66,7 @@ public void leaveProfession(CraftingTable table, Player player) { ProfessionLeaveEvent event = new ProfessionLeaveEvent(table.getName(), player); Bukkit.getPluginManager().callEvent(event); if (!event.isCancelled()) { + event.getFusionPlayer().setJoined(table, false); event.getFusionPlayer().removeProfession(table); CodexEngine.get().getMessageUtil().sendMessage("fusion.forgotten", player, diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/Profession.java b/src/main/java/studio/magemonkey/fusion/data/professions/Profession.java index 905de12..3ddb3c3 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/Profession.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/Profession.java @@ -61,7 +61,7 @@ public void update() { } public int getLevel() { - return ProfessionsCfg.getTable(name).getLevelFunction().getLevel(exp); + return ProfessionsCfg.getGuiMap().containsKey(name) ? ProfessionsCfg.getTable(name).getLevelFunction().getLevel(exp) : 0; } public void setLevel(int level) { From 7c156d418721d3c2443ab71dc3c6b91a0f703137 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Sun, 7 Sep 2025 09:17:45 +0200 Subject: [PATCH 07/16] removed debug --- .../java/studio/magemonkey/fusion/data/player/FusionPlayer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java b/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java index 80c97e9..bd8b9cd 100644 --- a/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java +++ b/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java @@ -349,7 +349,6 @@ public void save() { } for (CraftingQueue queue : cachedQueues.values()) { SQLManager.queues().saveCraftingQueue(queue); - Bukkit.getConsoleSender().sendMessage("Saved queue for profession " + queue.getProfession() + " and category " + queue.getCategory().getName()); } SQLManager.recipeLimits().saveRecipeLimits(uuid, cachedRecipeLimits); cachedQueues.clear(); From cca604c5ddd3c026d245b6a28f684cec48312505 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Sun, 7 Sep 2025 09:18:01 +0200 Subject: [PATCH 08/16] fixed ingredient hash on craft method --- .../studio/magemonkey/fusion/gui/RecipeGui.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java b/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java index e243c29..02dfcda 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java +++ b/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java @@ -686,21 +686,18 @@ private boolean craft(int slot, boolean addToCursor) { // for (ItemStack required : requiredItems) { int need = required.getAmount(); - ItemStack neededTemplate = required.clone(); // same material+meta + IngredientFingerprint neededFingerprint = IngredientFingerprint.of(required); - // Iterate through every inventory slot to match via isSimilar() for (int slotIndex = 0; slotIndex < inv.getSize() && need > 0; slotIndex++) { ItemStack slotStack = inv.getItem(slotIndex); if (slotStack == null || slotStack.getType() == Material.AIR) continue; - // Use CalculatedRecipe.isSimilar() to match custom NBT/lore - if (!CalculatedRecipe.isSimilar(neededTemplate, slotStack)) { - continue; - } + IngredientFingerprint slotFingerprint = IngredientFingerprint.of(slotStack); + if (!neededFingerprint.equals(slotFingerprint)) continue; int available = slotStack.getAmount(); int take = Math.min(available, need); - // Subtract “take” from that slot + slotStack.setAmount(available - take); if (slotStack.getAmount() <= 0) { inv.setItem(slotIndex, null); @@ -708,8 +705,7 @@ private boolean craft(int slot, boolean addToCursor) { inv.setItem(slotIndex, slotStack); } - // Track exactly what we removed - ItemStack actuallyTaken = neededTemplate.clone(); + ItemStack actuallyTaken = required.clone(); actuallyTaken.setAmount(take); removedSoFar.add(actuallyTaken); From 4bb2545c0121feefe835bcb77bc04740e0ee8e1d Mon Sep 17 00:00:00 2001 From: Travja Date: Tue, 9 Sep 2025 01:02:11 -0600 Subject: [PATCH 09/16] Formatting --- .../fusion/api/ProfessionManager.java | 2 +- .../fusion/api/events/FusionEvent.java | 4 +- .../api/events/ProfessionGainXpEvent.java | 4 +- .../api/events/ProfessionJoinEvent.java | 2 +- .../api/events/ProfessionLeaveEvent.java | 2 +- .../api/events/ProfessionLevelUpEvent.java | 6 +- .../api/events/ProfessionMasteryEvent.java | 4 +- .../api/events/QueueItemAddedEvent.java | 6 +- .../api/events/QueueItemFinishedEvent.java | 14 +-- .../api/events/QueueItemRemovedEvent.java | 12 +-- .../api/events/services/QueueService.java | 10 +- .../magemonkey/fusion/cfg/ShowRecipesCfg.java | 6 +- .../fusion/cfg/editors/EditorRegistry.java | 2 +- .../editors/professions/RecipeEditorCfg.java | 2 +- .../professions/RecipeIconEditorCfg.java | 25 ++--- .../cfg/migrations/ProfessionMigration.java | 8 +- .../cfg/sql/tables/FusionQueuesSQL.java | 2 +- .../fusion/commands/FusionEditorCommand.java | 96 ++++++++++--------- .../professions/CalculatedProfession.java | 4 +- .../data/professions/ProfessionResults.java | 28 ++++-- .../fusion/data/queue/CraftingQueue.java | 2 +- .../fusion/data/queue/QueueItem.java | 1 - .../fusion/data/recipes/CraftingTable.java | 13 +-- .../editors/professions/ProfessionEditor.java | 2 +- .../professions/recipes/RecipeIconEditor.java | 36 ++++--- .../gui/recipe/IngredientFingerprint.java | 46 ++++----- .../gui/recipe/InventoryFingerprint.java | 18 ++-- .../fusion/gui/recipe/RecipeCacheKey.java | 12 +-- .../gui/recipe/RecipeGuiEventRouter.java | 8 +- .../magemonkey/fusion/gui/slot/Slot.java | 2 +- .../fusion/commands/ForceCommandsTest.java | 37 +++---- 31 files changed, 226 insertions(+), 190 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/api/ProfessionManager.java b/src/main/java/studio/magemonkey/fusion/api/ProfessionManager.java index 801fbe1..4428a1e 100644 --- a/src/main/java/studio/magemonkey/fusion/api/ProfessionManager.java +++ b/src/main/java/studio/magemonkey/fusion/api/ProfessionManager.java @@ -48,7 +48,7 @@ public ProfessionGuiRegistry getProfessionGui(String profession) { * This object handles all players guis individually by caching them in a map. * * @param profession The name of the profession - * @param player The Player object + * @param player The Player object * @return The profession gui object */ public ProfessionGuiRegistry openProfessionGui(String profession, Player player) { diff --git a/src/main/java/studio/magemonkey/fusion/api/events/FusionEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/FusionEvent.java index 183aa00..4462a21 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/FusionEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/FusionEvent.java @@ -37,8 +37,8 @@ public class FusionEvent extends Event implements Cancellable { * Constructor for the FusionEvent * * @param professionName The name of the profession - * @param craftingTable The crafting table - * @param player The player + * @param craftingTable The crafting table + * @param player The player */ public FusionEvent(String professionName, CraftingTable craftingTable, Player player) { this.professionName = professionName; diff --git a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionGainXpEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionGainXpEvent.java index 9cd3429..d460e5d 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionGainXpEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionGainXpEvent.java @@ -18,8 +18,8 @@ public class ProfessionGainXpEvent extends FusionEvent { * Constructor for the ProfessionGainXpEvent * * @param professionName The name of the profession - * @param player The player that gained the experience - * @param gainedExp The amount of experience gained + * @param player The player that gained the experience + * @param gainedExp The amount of experience gained */ public ProfessionGainXpEvent(String professionName, Player player, long gainedExp) { super(professionName, ProfessionsCfg.getTable(professionName), player); diff --git a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionJoinEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionJoinEvent.java index faf9673..dc2aea3 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionJoinEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionJoinEvent.java @@ -10,7 +10,7 @@ public class ProfessionJoinEvent extends FusionEvent { * Constructor for the ProfessionJoinEvent * * @param professionName The name of the profession - * @param player The player that joined the profession + * @param player The player that joined the profession */ public ProfessionJoinEvent(String professionName, Player player) { super(professionName, ProfessionsCfg.getTable(professionName), player); diff --git a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLeaveEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLeaveEvent.java index cea6091..1d71e7b 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLeaveEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLeaveEvent.java @@ -10,7 +10,7 @@ public class ProfessionLeaveEvent extends FusionEvent { * Constructor for the ProfessionLeaveEvent * * @param professionName The name of the profession - * @param player The player that left the profession + * @param player The player that left the profession */ public ProfessionLeaveEvent(String professionName, Player player) { super(professionName, ProfessionsCfg.getTable(professionName), player); diff --git a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLevelUpEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLevelUpEvent.java index f74cfb2..930bf26 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLevelUpEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionLevelUpEvent.java @@ -23,9 +23,9 @@ public class ProfessionLevelUpEvent extends FusionEvent { * Constructor for the ProfessionLevelUpEvent * * @param professionName The name of the profession - * @param player The player that leveled up - * @param previousLevel The previous level of the profession - * @param newLevel The new level of the profession + * @param player The player that leveled up + * @param previousLevel The previous level of the profession + * @param newLevel The new level of the profession */ public ProfessionLevelUpEvent(String professionName, Player player, int previousLevel, int newLevel) { super(professionName, ProfessionsCfg.getTable(professionName), player); diff --git a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionMasteryEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionMasteryEvent.java index d616306..4f8ae9e 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/ProfessionMasteryEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/ProfessionMasteryEvent.java @@ -16,8 +16,8 @@ public class ProfessionMasteryEvent extends FusionEvent { * Constructor for the ProfessionMasteryEvent * * @param professionName The name of the profession - * @param player The player that has mastered the profession - * @param hasMastered Whether the player has mastered the profession + * @param player The player that has mastered the profession + * @param hasMastered Whether the player has mastered the profession */ public ProfessionMasteryEvent(String professionName, Player player, boolean hasMastered) { super(professionName, ProfessionsCfg.getTable(professionName), player); diff --git a/src/main/java/studio/magemonkey/fusion/api/events/QueueItemAddedEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/QueueItemAddedEvent.java index 8643ae3..de96dd7 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/QueueItemAddedEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/QueueItemAddedEvent.java @@ -22,9 +22,9 @@ public class QueueItemAddedEvent extends FusionEvent { * Constructor for the QueueItemAddedEvent * * @param professionName The name of the profession - * @param player The player that added the item to the queue - * @param queue The crafting queue - * @param queueItem The queue item + * @param player The player that added the item to the queue + * @param queue The crafting queue + * @param queueItem The queue item */ public QueueItemAddedEvent(String professionName, Player player, CraftingQueue queue, QueueItem queueItem) { super(professionName, ProfessionsCfg.getTable(professionName), player); diff --git a/src/main/java/studio/magemonkey/fusion/api/events/QueueItemFinishedEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/QueueItemFinishedEvent.java index 19552a6..04db1e3 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/QueueItemFinishedEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/QueueItemFinishedEvent.java @@ -16,25 +16,25 @@ public class QueueItemFinishedEvent extends FusionEvent { /** * The crafting queue */ - private final CraftingQueue queue; + private final CraftingQueue queue; /** * The queue item */ - private final QueueItem queueItem; + private final QueueItem queueItem; /** * The result item */ @Setter - private List resultItems; + private List resultItems; /** * Constructor for the QueueItemFinishedEvent * * @param professionName The name of the profession - * @param player The player that finished the item - * @param queue The crafting queue - * @param queueItem The queue item - * @param resultItems The result items + * @param player The player that finished the item + * @param queue The crafting queue + * @param queueItem The queue item + * @param resultItems The result items */ public QueueItemFinishedEvent(String professionName, Player player, diff --git a/src/main/java/studio/magemonkey/fusion/api/events/QueueItemRemovedEvent.java b/src/main/java/studio/magemonkey/fusion/api/events/QueueItemRemovedEvent.java index d78df7f..f5b102b 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/QueueItemRemovedEvent.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/QueueItemRemovedEvent.java @@ -39,12 +39,12 @@ public class QueueItemRemovedEvent extends FusionEvent { * Constructor for the QueueItemRemovedEvent * * @param professionName The name of the profession - * @param player The player that removed the item from the queue - * @param queue The crafting queue - * @param queueItem The queue item - * @param finished Whether the item was finished - * @param refunded Whether the item was refunded - * @param refundedItems The refunded items in case `refunded` is `true` + * @param player The player that removed the item from the queue + * @param queue The crafting queue + * @param queueItem The queue item + * @param finished Whether the item was finished + * @param refunded Whether the item was refunded + * @param refundedItems The refunded items in case `refunded` is `true` */ public QueueItemRemovedEvent(String professionName, Player player, diff --git a/src/main/java/studio/magemonkey/fusion/api/events/services/QueueService.java b/src/main/java/studio/magemonkey/fusion/api/events/services/QueueService.java index 7738217..7321d62 100644 --- a/src/main/java/studio/magemonkey/fusion/api/events/services/QueueService.java +++ b/src/main/java/studio/magemonkey/fusion/api/events/services/QueueService.java @@ -143,7 +143,12 @@ public void finishQueueItem(Player player, } // Items if no commands exist if (!item.getRecipe().getResults().hasCommandsOrItems()) { - ItemStack result = event.getQueueItem().getRecipe().getDivinityRecipeMeta() == null ? event.getQueueItem().getRecipe().getSettings().getRecipeItem().getItemStack() + ItemStack result = + event.getQueueItem().getRecipe().getDivinityRecipeMeta() == null ? event.getQueueItem() + .getRecipe() + .getSettings() + .getRecipeItem() + .getItemStack() : event.getQueueItem().getRecipe().getDivinityRecipeMeta().generateItem(); // If there is no space in the inventory, drop the items Collection notAdded = player.getInventory().addItem(result).values(); @@ -165,7 +170,8 @@ public void finishQueueItem(Player player, if (itemStack != null) { Collection remainings = player.getInventory().addItem(itemStack).values(); if (!remainings.isEmpty()) { - remainings.forEach(_item -> player.getWorld().dropItemNaturally(player.getLocation(), _item)); + remainings.forEach(_item -> player.getWorld() + .dropItemNaturally(player.getLocation(), _item)); } } } diff --git a/src/main/java/studio/magemonkey/fusion/cfg/ShowRecipesCfg.java b/src/main/java/studio/magemonkey/fusion/cfg/ShowRecipesCfg.java index e49c40c..990d505 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/ShowRecipesCfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/ShowRecipesCfg.java @@ -96,10 +96,10 @@ private static void readData() { } public static ItemStack getRecipeIcon(Recipe recipe, RecipeItem ingredient) { - String itemName = Utils.getItemName(recipe.getSettings().getRecipeItem().getItemStack()); - String name = ChatUT.hexString(config.getString("recipeItem.name", "&7$") + String itemName = Utils.getItemName(recipe.getSettings().getRecipeItem().getItemStack()); + String name = ChatUT.hexString(config.getString("recipeItem.name", "&7$") .replace(MessageUtil.getReplacement("name"), itemName)); - List lore = config.getStringList("recipeItem.lore"); + List lore = config.getStringList("recipeItem.lore"); lore.replaceAll(s -> ChatUT.hexString(s.replace(MessageUtil.getReplacement("ingredient"), Utils.getItemName(ingredient.getItemStack())) .replace(MessageUtil.getReplacement("profession"), recipe.getTable().getInventoryName()) diff --git a/src/main/java/studio/magemonkey/fusion/cfg/editors/EditorRegistry.java b/src/main/java/studio/magemonkey/fusion/cfg/editors/EditorRegistry.java index 8056c4f..e9c5427 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/editors/EditorRegistry.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/editors/EditorRegistry.java @@ -39,7 +39,7 @@ public class EditorRegistry { @Getter private static RecipeEditorCfg recipeEditorCfg; @Getter - private static RecipeIconEditorCfg recipeIconEditorCfg; + private static RecipeIconEditorCfg recipeIconEditorCfg; @Getter private static CategoryEditorCfg categoryEditorCfg; @Getter diff --git a/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeEditorCfg.java b/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeEditorCfg.java index 3a15a10..86dbb27 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeEditorCfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeEditorCfg.java @@ -166,7 +166,7 @@ public ItemStack getSubIcon(Recipe recipe, String icon) { } i += newLines; continue; - } else if (lore.get(i).contains(MessageUtil.getReplacement("items"))) { + } else if (lore.get(i).contains(MessageUtil.getReplacement("items"))) { lore.remove(i); int newLines = 1; for (String line : recipe.getResults().getItemNames()) { diff --git a/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeIconEditorCfg.java b/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeIconEditorCfg.java index 71f9437..650c1e9 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeIconEditorCfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/editors/professions/RecipeIconEditorCfg.java @@ -38,12 +38,13 @@ public Map getIcons(Recipe recipe) { } public ItemStack getIcon(Recipe recipe, String icon) { - Material material = Material.valueOf(config.getString("icons." + icon + ".material", "STONE").toUpperCase()); - int amount = config.getInt("icons." + icon + ".amount", 1); - int durability = config.getInt("icons." + icon + ".durability", 0); - boolean unbreakable = config.getBoolean("icon." + icon + ".unbreakable", false); - String name = config.getString("icons." + icon + ".name", "&cInvalid Item: &4" + icon); - List lore = config.getStringList("icons." + icon + ".lore"); + Material material = + Material.valueOf(config.getString("icons." + icon + ".material", "STONE").toUpperCase()); + int amount = config.getInt("icons." + icon + ".amount", 1); + int durability = config.getInt("icons." + icon + ".durability", 0); + boolean unbreakable = config.getBoolean("icon." + icon + ".unbreakable", false); + String name = config.getString("icons." + icon + ".name", "&cInvalid Item: &4" + icon); + List lore = config.getStringList("icons." + icon + ".lore"); ProfessionSettings settings = recipe.getSettings(); for (int i = 0; i < lore.size(); i++) { @@ -105,14 +106,16 @@ public ItemStack getIcon(Recipe recipe, String icon) { } lore.set(i, ChatUT.hexString(lore.get(i) .replace(MessageUtil.getReplacement("name"), settings.getName() != null ? settings.getName() : "") - .replace(MessageUtil.getReplacement("customModelData"), String.valueOf(settings.getCustomModelData())) + .replace(MessageUtil.getReplacement("customModelData"), + String.valueOf(settings.getCustomModelData())) .replace(MessageUtil.getReplacement("unbreakable"), String.valueOf(settings.isUnbreakable())) - .replace(MessageUtil.getReplacement("color"), settings.getColor() != null ? settings.getColor() : "") + .replace(MessageUtil.getReplacement("color"), + settings.getColor() != null ? settings.getColor() : "") .replace(MessageUtil.getReplacement("cancelDrop"), String.valueOf(settings.isCancelDrop())))); } - Map enchants = config.getEnchantmentSection("icons." + icon + ".enchants"); - List flags = config.getItemFlags("icons." + icon + ".flags"); - ItemFlag[] itemFlags = flags.toArray(new ItemFlag[0]); + Map enchants = config.getEnchantmentSection("icons." + icon + ".enchants"); + List flags = config.getItemFlags("icons." + icon + ".flags"); + ItemFlag[] itemFlags = flags.toArray(new ItemFlag[0]); return ItemBuilder.newItem(material) .amount(amount) .durability(durability) diff --git a/src/main/java/studio/magemonkey/fusion/cfg/migrations/ProfessionMigration.java b/src/main/java/studio/magemonkey/fusion/cfg/migrations/ProfessionMigration.java index fbdb883..09f011d 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/migrations/ProfessionMigration.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/migrations/ProfessionMigration.java @@ -125,14 +125,14 @@ public static void migrate(FileConfiguration config, String toVersion) { migrations.put("1.3", (config) -> { List> recipes = config.getMapList("recipes"); for (Map recipe : recipes) { - Map results = (Map) recipe.get("results"); + Map results = (Map) recipe.get("results"); Map settings = (Map) recipe.get("settings"); - if(results == null) continue; - if(settings == null) + if (results == null) continue; + if (settings == null) settings = new LinkedHashMap<>(); String namespace = (String) results.get("item"); - if(namespace == null) continue; + if (namespace == null) continue; Map iconSettings = new LinkedHashMap<>(); iconSettings.put("item", namespace); diff --git a/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java b/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java index 4d863aa..9af7774 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java @@ -114,7 +114,7 @@ public List getQueueItems(UUID uuid, String profession, Category cate try (ResultSet result = select.executeQuery()) { while (result.next()) { String recipeStr = result.getString("RecipePath").split("\\.")[2]; - Recipe recipe = category.getRecipe(recipeStr); + Recipe recipe = category.getRecipe(recipeStr); if (recipe == null) { Fusion.getInstance() diff --git a/src/main/java/studio/magemonkey/fusion/commands/FusionEditorCommand.java b/src/main/java/studio/magemonkey/fusion/commands/FusionEditorCommand.java index f7b3482..e62d5f2 100644 --- a/src/main/java/studio/magemonkey/fusion/commands/FusionEditorCommand.java +++ b/src/main/java/studio/magemonkey/fusion/commands/FusionEditorCommand.java @@ -228,7 +228,7 @@ public List onTabComplete(@NotNull CommandSender sender, } if (editor instanceof ProfessionEditor) { ProfessionEditor professionEditor = (ProfessionEditor) editor; - EditorCriteria criteria = editorCriteria.get(player.getUniqueId()); + EditorCriteria criteria = editorCriteria.get(player.getUniqueId()); switch (criteria) { case Profession_Edit_Name: case Pattern_Edit_Name: @@ -329,7 +329,12 @@ public List onTabComplete(@NotNull CommandSender sender, case RecipeIcon_Edit_Name: if (args.length == 1) { entries.add(""); - entries.add(professionEditor.getRecipeEditor().getRecipeItemEditor().getRecipeIconEditor().getRecipe().getSettings().getName()); + entries.add(professionEditor.getRecipeEditor() + .getRecipeItemEditor() + .getRecipeIconEditor() + .getRecipe() + .getSettings() + .getName()); } break; case RecipeIcon_Edit_Color: @@ -342,8 +347,8 @@ public List onTabComplete(@NotNull CommandSender sender, break; } } else if (editor instanceof BrowseEditor) { - BrowseEditor browseEditor = (BrowseEditor) editor; - EditorCriteria criteria = editorCriteria.get(player.getUniqueId()); + BrowseEditor browseEditor = (BrowseEditor) editor; + EditorCriteria criteria = editorCriteria.get(player.getUniqueId()); switch (criteria) { case Browse_Edit_Name: if (args.length == 1) { @@ -544,8 +549,8 @@ private void updateProfessionName(ProfessionEditor professionEditor, String[] ar professionNameBuilder.append(arg).append(" "); } String professionName = professionNameBuilder.toString().trim(); - String oldName = professionEditor.getTable().getName(); - Player player = professionEditor.getPlayer(); + String oldName = professionEditor.getTable().getName(); + Player player = professionEditor.getPlayer(); professionEditor.getTable().setInventoryName(professionName); CodexEngine.get() .getMessageUtil() @@ -557,9 +562,9 @@ private void updateProfessionName(ProfessionEditor professionEditor, String[] ar } private void updateProfessionIcon(ProfessionEditor professionEditor, String[] args) { - String icon = args[0]; + String icon = args[0]; String oldIcon = professionEditor.getTable().getIconItem().getID(); - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (!isValidItem(icon)) { CodexEngine.get().getMessageUtil().sendMessage("editor.invalidItem", player, new MessageData("item", icon)); return; @@ -592,7 +597,7 @@ private void updateCategory(ProfessionEditor professionEditor, String[] args, Ed String categoryName = args[0]; String categoryIcon = args[1]; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (!isValidItem(categoryIcon)) { CodexEngine.get() .getMessageUtil() @@ -686,7 +691,7 @@ private void updatePatternItemName(Editor editor, String[] args) { private void updatePatternItem(Editor editor, String[] args) { if (editor instanceof ProfessionEditor) { ProfessionEditor professionEditor = (ProfessionEditor) editor; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (args.length < 2) { CodexEngine.get() .getMessageUtil() @@ -697,7 +702,7 @@ private void updatePatternItem(Editor editor, String[] args) { } try { Material material = Material.valueOf(args[0].toUpperCase()); - int amount = Integer.parseInt(args[1]); + int amount = Integer.parseInt(args[1]); professionEditor.getPatternItemsEditor().getPatternItemEditor().getBuilder().material(material); professionEditor.getPatternItemsEditor().getPatternItemEditor().getBuilder().amount(amount); @@ -718,7 +723,7 @@ private void updatePatternItem(Editor editor, String[] args) { } } else if (editor instanceof BrowseEditor) { BrowseEditor browseEditor = (BrowseEditor) editor; - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); if (args.length < 2) { CodexEngine.get() .getMessageUtil() @@ -729,7 +734,7 @@ private void updatePatternItem(Editor editor, String[] args) { } try { Material material = Material.valueOf(args[0].toUpperCase()); - int amount = Integer.parseInt(args[1]); + int amount = Integer.parseInt(args[1]); browseEditor.getPatternItemsEditor().getPatternItemEditor().getBuilder().material(material); browseEditor.getPatternItemsEditor().getPatternItemEditor().getBuilder().amount(amount); @@ -754,7 +759,7 @@ private void updatePatternItem(Editor editor, String[] args) { private void addPatternItemLore(Editor editor, String[] args) { if (editor instanceof ProfessionEditor) { ProfessionEditor professionEditor = (ProfessionEditor) editor; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (args.length < 1) { CodexEngine.get() .getMessageUtil() @@ -778,7 +783,7 @@ private void addPatternItemLore(Editor editor, String[] args) { new MessageData("lore", ChatUT.hexString(builder.toString()))); } else if (editor instanceof BrowseEditor) { BrowseEditor browseEditor = (BrowseEditor) editor; - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); if (args.length < 1) { CodexEngine.get() .getMessageUtil() @@ -803,7 +808,7 @@ private void addPatternItemLore(Editor editor, String[] args) { private void addPatternItemCommand(Editor editor, String[] args) { if (editor instanceof ProfessionEditor) { ProfessionEditor professionEditor = (ProfessionEditor) editor; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (args.length < 3) { CodexEngine.get() .getMessageUtil() @@ -813,7 +818,7 @@ private void addPatternItemCommand(Editor editor, String[] args) { StringBuilder commandBuilder = new StringBuilder(); try { CommandType commandType = CommandType.valueOf(args[0].toUpperCase()); - int delay = Integer.parseInt(args[1]); + int delay = Integer.parseInt(args[1]); commandBuilder = new StringBuilder(); for (int i = 2; i < args.length; i++) { commandBuilder.append(args[i]); @@ -838,7 +843,7 @@ private void addPatternItemCommand(Editor editor, String[] args) { } } else if (editor instanceof BrowseEditor) { BrowseEditor browseEditor = (BrowseEditor) editor; - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); if (args.length < 3) { CodexEngine.get() .getMessageUtil() @@ -848,7 +853,7 @@ private void addPatternItemCommand(Editor editor, String[] args) { StringBuilder commandBuilder = new StringBuilder(); try { CommandType commandType = CommandType.valueOf(args[0].toUpperCase()); - int delay = Integer.parseInt(args[1]); + int delay = Integer.parseInt(args[1]); commandBuilder = new StringBuilder(); for (int i = 2; i < args.length; i++) { commandBuilder.append(args[i]); @@ -877,7 +882,7 @@ private void addPatternItemCommand(Editor editor, String[] args) { private void addPatternEnchants(Editor editor, String[] args) { if (editor instanceof ProfessionEditor) { ProfessionEditor professionEditor = (ProfessionEditor) editor; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (args.length < 1) { CodexEngine.get() .getMessageUtil() @@ -910,7 +915,7 @@ private void addPatternEnchants(Editor editor, String[] args) { professionEditor.getPatternItemsEditor().getPatternItemEditor().reload(true); } else if (editor instanceof BrowseEditor) { BrowseEditor browseEditor = (BrowseEditor) editor; - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); if (args.length < 1) { CodexEngine.get() .getMessageUtil() @@ -947,7 +952,7 @@ private void addPatternEnchants(Editor editor, String[] args) { public void addPatternFlags(Editor editor, String[] args) { if (editor instanceof ProfessionEditor) { ProfessionEditor professionEditor = (ProfessionEditor) editor; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); if (args.length < 1) { CodexEngine.get() .getMessageUtil() @@ -975,7 +980,7 @@ public void addPatternFlags(Editor editor, String[] args) { } } else if (editor instanceof BrowseEditor) { BrowseEditor browseEditor = (BrowseEditor) editor; - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); if (args.length < 1) { CodexEngine.get() .getMessageUtil() @@ -1016,8 +1021,8 @@ private void updateRecipeName(ProfessionEditor professionEditor, String[] args) } String recipeName = args[0]; - Player player = professionEditor.getPlayer(); - String oldName = professionEditor.getRecipeEditor().getRecipeItemEditor().getRecipeName(); + Player player = professionEditor.getPlayer(); + String oldName = professionEditor.getRecipeEditor().getRecipeItemEditor().getRecipeName(); for (Recipe recipe : professionEditor.getTable().getRecipes().values()) { if (recipe.getName().equalsIgnoreCase(recipeName)) { CodexEngine.get() @@ -1047,7 +1052,7 @@ private void addRecipeCommand(ProfessionEditor professionEditor, String[] args) StringBuilder commandBuilder = new StringBuilder(); try { CommandType commandType = CommandType.valueOf(args[0].toUpperCase()); - int delay = Integer.parseInt(args[1]); + int delay = Integer.parseInt(args[1]); commandBuilder = new StringBuilder(); for (int i = 2; i < args.length; i++) { commandBuilder.append(args[i]); @@ -1085,7 +1090,7 @@ private void addRecipeItem(ProfessionEditor professionEditor, String[] args) { } try { String itemName = args[0]; - int amount = Integer.parseInt(args[1]); + int amount = Integer.parseInt(args[1]); if (!isValidItem(itemName)) { CodexEngine.get() .getMessageUtil() @@ -1119,8 +1124,8 @@ private void addNewRecipe(ProfessionEditor professionEditor, String[] args) { } try { String recipeName = args[0]; - String itemName = args[1]; - int amount = Integer.parseInt(args[2]); + String itemName = args[1]; + int amount = Integer.parseInt(args[2]); for (Recipe recipe : professionEditor.getTable().getRecipes().values()) { if (recipe.getName().equalsIgnoreCase(recipeName)) { CodexEngine.get() @@ -1188,7 +1193,7 @@ private void updateRecipeItems(ProfessionEditor professionEditor, String[] args, } try { String itemName = args[0]; - int amount = Integer.parseInt(args[1]); + int amount = Integer.parseInt(args[1]); if (!isValidItem(itemName)) { CodexEngine.get() .getMessageUtil() @@ -1316,9 +1321,9 @@ private void addRecipeConditions(ProfessionEditor professionEditor, String[] arg new MessageData("syntax", " ")); return; } - String conditionKey = args[0]; + String conditionKey = args[0]; String conditionValue = args[1]; - int level = Integer.parseInt(args[2]); + int level = Integer.parseInt(args[2]); switch (conditionKey) { case "professions": @@ -1509,9 +1514,9 @@ private void updateBrowseName(BrowseEditor browseEditor, String[] args) { for (String arg : args) { builder.append(arg).append(" "); } - String name = builder.toString().trim(); + String name = builder.toString().trim(); String oldName = browseEditor.getName(); - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); browseEditor.setName(name); CodexEngine.get() .getMessageUtil() @@ -1524,7 +1529,7 @@ private void updateBrowseName(BrowseEditor browseEditor, String[] args) { private void addNewProfession(BrowseEditor browseEditor, String[] args) { String professionName = args[0]; - Player player = browseEditor.getPlayer(); + Player player = browseEditor.getPlayer(); if (!ProfessionsCfg.getMap().containsKey(professionName)) { CodexEngine.get() .getMessageUtil() @@ -1562,7 +1567,7 @@ private void addBrowseIngredient(BrowseEditor browseEditor, String[] args) { } try { String itemName = args[0]; - int amount = Integer.parseInt(args[1]); + int amount = Integer.parseInt(args[1]); if (!isValidItem(itemName)) { CodexEngine.get() .getMessageUtil() @@ -1570,7 +1575,7 @@ private void addBrowseIngredient(BrowseEditor browseEditor, String[] args) { return; } - int i = 0; + int i = 0; boolean found = false; for (RecipeItem ingredient : browseEditor.getBrowseProfessionsEditor() .getBrowseProfessionEditor() @@ -1622,9 +1627,9 @@ private void addBrowseConditions(BrowseEditor browseEditor, String[] args) { new MessageData("syntax", " ")); return; } - String conditionKey = args[0]; + String conditionKey = args[0]; String conditionValue = args[1]; - int level = Integer.parseInt(args[2]); + int level = Integer.parseInt(args[2]); switch (conditionKey) { case "professions": @@ -1812,7 +1817,7 @@ public void updateRecipeIconName(ProfessionEditor professionEditor, String[] arg } String iconName = args[0]; - Player player = professionEditor.getPlayer(); + Player player = professionEditor.getPlayer(); professionEditor.getRecipeEditor().getRecipeItemEditor().getRecipe().getSettings().setName(iconName); CodexEngine.get() .getMessageUtil() @@ -1836,7 +1841,7 @@ public void addRecipeIconLore(ProfessionEditor professionEditor, String[] args) for (String arg : args) { loreBuilder.append(arg).append(" "); } - String lore = loreBuilder.toString().trim(); + String lore = loreBuilder.toString().trim(); Player player = professionEditor.getPlayer(); professionEditor.getRecipeEditor().getRecipeItemEditor().getRecipe().getSettings().getLore().add(lore); CodexEngine.get() @@ -1897,8 +1902,9 @@ public void updateRecipeIconColor(ProfessionEditor professionEditor, String[] ar Player player = professionEditor.getPlayer(); try { - String[] data = args[0].split(","); - Color color = Color.fromRGB(Integer.parseInt(data[0]), Integer.parseInt(data[1]), Integer.parseInt(data[2])); + String[] data = args[0].split(","); + Color color = + Color.fromRGB(Integer.parseInt(data[0]), Integer.parseInt(data[1]), Integer.parseInt(data[2])); professionEditor.getRecipeEditor().getRecipeItemEditor().getRecipe().getSettings().setColor(args[0]); CodexEngine.get() .getMessageUtil() @@ -1924,7 +1930,7 @@ public void addRecipeIconCommand(ProfessionEditor professionEditor, String[] arg StringBuilder commandBuilder = new StringBuilder(); try { CommandType commandType = CommandType.valueOf(args[0].toUpperCase()); - int delay = Integer.parseInt(args[1]); + int delay = Integer.parseInt(args[1]); commandBuilder = new StringBuilder(); for (int i = 2; i < args.length; i++) { commandBuilder.append(args[i]); @@ -1962,7 +1968,7 @@ public void addRecipeIconEnchants(ProfessionEditor professionEditor, String[] ar } try { Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(args[0].toLowerCase())); - int level = Integer.parseInt(args[1]); + int level = Integer.parseInt(args[1]); if (enchantment == null) { CodexEngine.get() .getMessageUtil() diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/CalculatedProfession.java b/src/main/java/studio/magemonkey/fusion/data/professions/CalculatedProfession.java index dfc5df7..a022eec 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/CalculatedProfession.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/CalculatedProfession.java @@ -87,13 +87,13 @@ public static CalculatedProfession create(ProfessionConditions conditions, List> eqItems = Recipe.getItems(items); - Collection localPattern = new HashSet<>(conditions.getRequiredItems()); + Collection localPattern = new HashSet<>(conditions.getRequiredItems()); for (Iterator it = localPattern.iterator(); it.hasNext(); ) { RecipeItem recipeItem = it.next(); ItemStack recipeItemStack = recipeItem.getItemStack(); ItemStack recipeItemStackOne = recipeItemStack.clone(); recipeItemStackOne.setAmount(1); - Pair eqEntry = null; + Pair eqEntry = null; for (Pair entry : eqItems) { ItemStack item = entry.getKey().clone(); if (CalculatedRecipe.isSimilar(recipeItemStackOne, item)) { diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionResults.java b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionResults.java index 2fe2b08..c71b128 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionResults.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionResults.java @@ -20,11 +20,11 @@ public class ProfessionResults implements ConfigurationSerializable { private final String profession; // Rewards - private long professionExp; - private int vanillaExp; - private List items = new LinkedList<>(); - private List itemNames = new LinkedList<>(); - private List commands = new LinkedList<>(); + private long professionExp; + private int vanillaExp; + private List items = new LinkedList<>(); + private List itemNames = new LinkedList<>(); + private List commands = new LinkedList<>(); public ProfessionResults(String profession, long professionExp, @@ -46,8 +46,14 @@ public ProfessionResults(String profession, ConfigurationSection config) { this.profession = profession; this.professionExp = config.getLong("rewards.professionExp"); this.vanillaExp = config.getInt("rewards.vanillaExp"); - this.commands = config.getList("rewards.commands", new LinkedList<>()).stream().map(entry -> new DelayedCommand()).collect(Collectors.toList()); - this.itemNames = config.getList("rewards.items", new LinkedList<>()).stream().map(Object::toString).collect(Collectors.toList()); + this.commands = config.getList("rewards.commands", new LinkedList<>()) + .stream() + .map(entry -> new DelayedCommand()) + .collect(Collectors.toList()); + this.itemNames = config.getList("rewards.items", new LinkedList<>()) + .stream() + .map(Object::toString) + .collect(Collectors.toList()); for (String itemName : itemNames) { this.items.add(RecipeItem.fromConfig(itemName)); } @@ -72,7 +78,8 @@ public ProfessionResults(String profession, DeserializationWorker dw) { this.vanillaExp = 0; } - List> commands = (List>) resultsSection.getOrDefault("commands", new ArrayList<>()); + List> commands = + (List>) resultsSection.getOrDefault("commands", new ArrayList<>()); if (commands != null) { for (Map command : commands) { this.commands.add(new DelayedCommand(command)); @@ -94,7 +101,8 @@ public ProfessionResults(String profession, DeserializationWorker dw) { Map resultMap = new HashMap<>(); resultMap.put("professionExp", this.professionExp); resultMap.put("vanillaExp", this.vanillaExp); - resultMap.put("commands", new ArrayList<>(this.commands.stream().map(DelayedCommand::serialize).collect(Collectors.toList()))); + resultMap.put("commands", + new ArrayList<>(this.commands.stream().map(DelayedCommand::serialize).collect(Collectors.toList()))); resultMap.put("items", new ArrayList<>(this.itemNames)); return SerializationBuilder.start(4).append("results", resultMap).build(); } @@ -113,6 +121,6 @@ public static ProfessionResults copy(ProfessionResults results) { } public boolean hasCommandsOrItems() { - return professionExp > 0 || vanillaExp > 0 || !commands.isEmpty() || !itemNames.isEmpty(); + return professionExp > 0 || vanillaExp > 0 || !commands.isEmpty() || !itemNames.isEmpty(); } } diff --git a/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java b/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java index 6ebbc9d..a7d1c53 100644 --- a/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java +++ b/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java @@ -68,7 +68,7 @@ public CraftingQueue(Player player, String profession, Category category) { continue; } int remaining = item.getRecipe().getCraftingTime() - item.getSavedSeconds(); - int apply = Math.min(offlineSeconds, remaining); + int apply = Math.min(offlineSeconds, remaining); item.progressOffline(apply); offlineSeconds -= apply; } diff --git a/src/main/java/studio/magemonkey/fusion/data/queue/QueueItem.java b/src/main/java/studio/magemonkey/fusion/data/queue/QueueItem.java index ba3c94f..b0b2871 100644 --- a/src/main/java/studio/magemonkey/fusion/data/queue/QueueItem.java +++ b/src/main/java/studio/magemonkey/fusion/data/queue/QueueItem.java @@ -6,7 +6,6 @@ import lombok.Setter; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import studio.magemonkey.fusion.cfg.Cfg; import studio.magemonkey.fusion.cfg.ProfessionsCfg; import studio.magemonkey.fusion.data.professions.pattern.Category; import studio.magemonkey.fusion.data.recipes.Recipe; diff --git a/src/main/java/studio/magemonkey/fusion/data/recipes/CraftingTable.java b/src/main/java/studio/magemonkey/fusion/data/recipes/CraftingTable.java index a74e7ae..42cc65d 100644 --- a/src/main/java/studio/magemonkey/fusion/data/recipes/CraftingTable.java +++ b/src/main/java/studio/magemonkey/fusion/data/recipes/CraftingTable.java @@ -138,10 +138,10 @@ public CraftingTable(Map map) throws MissingProviderException, M for (Map recipeData : recipesSection) { long rStart = System.currentTimeMillis(); try { - Map settings = (Map) recipeData.get("settings"); - Map iconSettings = (Map) settings.get("icon"); + Map settings = (Map) recipeData.get("settings"); + Map iconSettings = (Map) settings.get("icon"); - String itemResult = (String) iconSettings.get("item"); + String itemResult = (String) iconSettings.get("item"); // TODO First contact with ResultItem / Icon if (itemResult.startsWith("DIVINITY_item_generator")) { buildDivinityResultItem(recipeData, itemResult); @@ -255,11 +255,12 @@ private void buildDivinityResultItem(Map recipeData, String itemResult) { } String recipeName = (String) recipeData.get("name"); - int i = 0; + int i = 0; for (Map.Entry> nameEntry : names.entrySet()) { for (String name : nameEntry.getValue()) { - DivinityRecipeMeta meta = new DivinityRecipeMeta(recipeName, entry, level, amount, nameEntry.getKey(), name); - Recipe recipe = new Recipe(this, (Map) recipeData, meta); + DivinityRecipeMeta meta = + new DivinityRecipeMeta(recipeName, entry, level, amount, nameEntry.getKey(), name); + Recipe recipe = new Recipe(this, (Map) recipeData, meta); recipe.setName(recipe.getName() + "::" + i); recipes.put(recipe.getName(), recipe); if (category != null) { diff --git a/src/main/java/studio/magemonkey/fusion/gui/editors/professions/ProfessionEditor.java b/src/main/java/studio/magemonkey/fusion/gui/editors/professions/ProfessionEditor.java index 3a77727..3f4f6b8 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/editors/professions/ProfessionEditor.java +++ b/src/main/java/studio/magemonkey/fusion/gui/editors/professions/ProfessionEditor.java @@ -31,7 +31,7 @@ public class ProfessionEditor extends Editor implements Listener { private PatternItemsEditor categoryPatternItemEditor; private PatternEditor categoryPatternEditor; private CategoryEditor categoryEditor; - private RecipeEditor recipeEditor; + private RecipeEditor recipeEditor; public ProfessionEditor(Player player, String profession) { super(null, EditorRegistry.getProfessionEditorCfg().getTitle(profession), 45); diff --git a/src/main/java/studio/magemonkey/fusion/gui/editors/professions/recipes/RecipeIconEditor.java b/src/main/java/studio/magemonkey/fusion/gui/editors/professions/recipes/RecipeIconEditor.java index 6674f44..a466071 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/editors/professions/recipes/RecipeIconEditor.java +++ b/src/main/java/studio/magemonkey/fusion/gui/editors/professions/recipes/RecipeIconEditor.java @@ -57,19 +57,21 @@ public void onInventoryClick(InventoryClickEvent event) { switch (event.getSlot()) { case 10 -> { - if(event.isLeftClick()) { + if (event.isLeftClick()) { FusionEditorCommand.suggestUsage(player, EditorCriteria.RecipeIcon_Edit_Name, "/fusion-editor " + recipe.getSettings().getName()); - } else if(event.isRightClick()){ + } else if (event.isRightClick()) { recipe.getSettings().setName(null); hasChanges = true; } } case 11 -> { if (event.isLeftClick()) { - FusionEditorCommand.suggestUsage(player, EditorCriteria.RecipeIcon_Edit_Lore, "/fusion-editor "); - } else if(event.isRightClick()){ + FusionEditorCommand.suggestUsage(player, + EditorCriteria.RecipeIcon_Edit_Lore, + "/fusion-editor "); + } else if (event.isRightClick()) { if (recipe.getSettings().getLore().isEmpty()) { return; } @@ -86,18 +88,22 @@ public void onInventoryClick(InventoryClickEvent event) { recipe.getSettings().setCustomModelData(recipe.getSettings().getCustomModelData() + amount); } else if (event.isRightClick()) { if (recipe.getSettings().getCustomModelData() == -1) return; - recipe.getSettings().setCustomModelData(Math.max(recipe.getSettings().getCustomModelData() - amount, -1)); + recipe.getSettings() + .setCustomModelData(Math.max(recipe.getSettings().getCustomModelData() - amount, -1)); } hasChanges = true; } case 16 -> { if (event.isLeftClick()) { - FusionEditorCommand.suggestUsage(player, EditorCriteria.RecipeIcon_Add_Commands, "/fusion-editor "); - } else if(event.isRightClick()){ + FusionEditorCommand.suggestUsage(player, + EditorCriteria.RecipeIcon_Add_Commands, + "/fusion-editor "); + } else if (event.isRightClick()) { if (recipe.getSettings().getCommandsOnClick().isEmpty()) { return; } - DelayedCommand command = new ArrayList<>(recipe.getSettings().getCommandsOnClick()).get(recipe.getSettings().getCommandsOnClick().size() - 1); + DelayedCommand command = new ArrayList<>(recipe.getSettings().getCommandsOnClick()).get( + recipe.getSettings().getCommandsOnClick().size() - 1); recipe.getSettings().getCommandsOnClick().remove(command); hasChanges = true; } @@ -108,11 +114,11 @@ public void onInventoryClick(InventoryClickEvent event) { return; } case 29 -> { - if(event.isLeftClick()) { + if (event.isLeftClick()) { FusionEditorCommand.suggestUsage(player, EditorCriteria.RecipeIcon_Edit_Color, "/fusion-editor " + recipe.getSettings().getColor()); - } else if(event.isRightClick()){ + } else if (event.isRightClick()) { recipe.getSettings().setColor(null); hasChanges = true; } @@ -132,20 +138,24 @@ public void onInventoryClick(InventoryClickEvent event) { } // Get last entry and remove it Enchantment lastEnchantment = - new ArrayList<>(recipe.getSettings().getEnchantments().keySet()).get(recipe.getSettings().getEnchantments().size() - 1); + new ArrayList<>(recipe.getSettings().getEnchantments().keySet()).get( + recipe.getSettings().getEnchantments().size() - 1); recipe.getSettings().getEnchantments().remove(lastEnchantment); hasChanges = true; } } case 33 -> { if (event.isLeftClick()) { - FusionEditorCommand.suggestUsage(player, EditorCriteria.RecipeIcon_Add_Flags, "/fusion-editor "); + FusionEditorCommand.suggestUsage(player, + EditorCriteria.RecipeIcon_Add_Flags, + "/fusion-editor "); } else if (event.isRightClick()) { if (recipe.getSettings().getFlags().isEmpty()) { return; } // Remove the last flag from the set - ItemFlag lastFlag = new ArrayList<>(recipe.getSettings().getFlags()).get(recipe.getSettings().getFlags().size() - 1); + ItemFlag lastFlag = new ArrayList<>(recipe.getSettings().getFlags()).get( + recipe.getSettings().getFlags().size() - 1); recipe.getSettings().getFlags().remove(lastFlag); hasChanges = true; } diff --git a/src/main/java/studio/magemonkey/fusion/gui/recipe/IngredientFingerprint.java b/src/main/java/studio/magemonkey/fusion/gui/recipe/IngredientFingerprint.java index d8c0aa7..ff9de7e 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/recipe/IngredientFingerprint.java +++ b/src/main/java/studio/magemonkey/fusion/gui/recipe/IngredientFingerprint.java @@ -8,24 +8,24 @@ /** * Immutable fingerprint for an ItemStack that matches CalculatedRecipe.isSimilar(...) logic. - * + *

* We compare: - * - Material - * - customModelData (if present) - * - displayName (if present) - * - lore lines (if present) - * - all enchantments (if present) - * - unbreakable flag - * - durability (if Damageable) + * - Material + * - customModelData (if present) + * - displayName (if present) + * - lore lines (if present) + * - all enchantments (if present) + * - unbreakable flag + * - durability (if Damageable) */ public class IngredientFingerprint { - private final Material type; - private final int customModelData; - private final String displayName; - private final List lore; + private final Material type; + private final int customModelData; + private final String displayName; + private final List lore; private final Map enchantments; - private final boolean unbreakable; - private final int durability; + private final boolean unbreakable; + private final int durability; public IngredientFingerprint(Material type, int customModelData, @@ -43,17 +43,19 @@ public IngredientFingerprint(Material type, this.durability = durability; } - /** Build an IngredientFingerprint by examining a live ItemStack. */ + /** + * Build an IngredientFingerprint by examining a live ItemStack. + */ public static IngredientFingerprint of(ItemStack is) { - Material mat = is.getType(); + Material mat = is.getType(); ItemMeta meta = is.getItemMeta(); - int cmd = 0; - String name = ""; - List loreList = Collections.emptyList(); + int cmd = 0; + String name = ""; + List loreList = Collections.emptyList(); Map enchantsMap = Collections.emptyMap(); - boolean unbreak = false; - int dmg = 0; + boolean unbreak = false; + int dmg = 0; if (meta != null) { if (meta.hasCustomModelData()) { @@ -65,7 +67,7 @@ public static IngredientFingerprint of(ItemStack is) { if (meta.hasLore()) { loreList = new ArrayList<>(Objects.requireNonNull(meta.getLore())); } - Map raw = meta.getEnchants(); + Map raw = meta.getEnchants(); if (!raw.isEmpty()) { enchantsMap = new HashMap<>(raw); } diff --git a/src/main/java/studio/magemonkey/fusion/gui/recipe/InventoryFingerprint.java b/src/main/java/studio/magemonkey/fusion/gui/recipe/InventoryFingerprint.java index d2b0688..1418129 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/recipe/InventoryFingerprint.java +++ b/src/main/java/studio/magemonkey/fusion/gui/recipe/InventoryFingerprint.java @@ -13,15 +13,15 @@ /** * Helper to build a small MD5 fingerprint of an entire PlayerInventory. * We incorporate: - * - Material ordinal - * - amount - * - customModelData - * - displayName - * - lore lines - * - enchantments - * - unbreakable - * - durability if Damageable - * + * - Material ordinal + * - amount + * - customModelData + * - displayName + * - lore lines + * - enchantments + * - unbreakable + * - durability if Damageable + *

* If MD5 is not available, we fall back to a simple int‐hash of slot hashCodes. */ public class InventoryFingerprint { diff --git a/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeCacheKey.java b/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeCacheKey.java index 154d1b9..49fc7c1 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeCacheKey.java +++ b/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeCacheKey.java @@ -9,16 +9,16 @@ public class RecipeCacheKey { private final String recipeId; private final byte[] inventoryHash; - private final int playerLevel; + private final int playerLevel; private final double playerMoney; // TODO add: /* - * - Vanilla Exp - * - Conditions.McMMO Map - * - Conditions.Fabled Map - * - Conditions.Aura Map - * - Conditions.ProfessionLevels Map + * - Vanilla Exp + * - Conditions.McMMO Map + * - Conditions.Fabled Map + * - Conditions.Aura Map + * - Conditions.ProfessionLevels Map */ public RecipeCacheKey(String recipeId, byte[] inventoryHash, int playerLevel, double playerMoney) { diff --git a/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java b/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java index 2f9435f..ef9204a 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java +++ b/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java @@ -29,7 +29,7 @@ public class RecipeGuiEventRouter implements Listener { * We fetch that player’s FusionPlayer via PlayerLoader.getPlayer(Player). */ private RecipeGui findGuiFor(Player player, Inventory inv) { - if(!ProfessionGuiRegistry.getLatestRecipeGui().containsKey(player.getUniqueId())) + if (!ProfessionGuiRegistry.getLatestRecipeGui().containsKey(player.getUniqueId())) return null; RecipeGui gui = ProfessionGuiRegistry.getLatestRecipeGui().get(player.getUniqueId()); if (gui.getInventory().equals(inv)) { @@ -80,7 +80,7 @@ public void onInventoryClose(InventoryCloseEvent event) { @EventHandler(ignoreCancelled = true) public void onPlayerDrop(PlayerDropItemEvent event) { - Player p = event.getPlayer(); + Player p = event.getPlayer(); RecipeGui gui = findGuiFor(p, p.getOpenInventory().getTopInventory()); if (gui == null) return; @@ -100,13 +100,13 @@ public void onItemPickup(EntityPickupItemEvent event) { @EventHandler(ignoreCancelled = true) public void onPlayerQuit(PlayerQuitEvent event) { - Player p = event.getPlayer(); + Player p = event.getPlayer(); FusionPlayer fp = PlayerLoader.getPlayer(p); if (fp == null) return; // On quit, close and remove *all* open RecipeGuis for that player RecipeGui gui = ProfessionGuiRegistry.getLatestRecipeGui().get(p.getUniqueId()); - if(gui == null) return; + if (gui == null) return; gui.close(p, gui.getInventory()); } } diff --git a/src/main/java/studio/magemonkey/fusion/gui/slot/Slot.java b/src/main/java/studio/magemonkey/fusion/gui/slot/Slot.java index e220850..8503e36 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/slot/Slot.java +++ b/src/main/java/studio/magemonkey/fusion/gui/slot/Slot.java @@ -93,7 +93,7 @@ public ItemStack canHoldItem(ItemStack item) { /** * -- GETTER -- - * Returns base slot type. + * Returns base slot type. * */ protected final SlotType slotType; diff --git a/src/test/java/studio/magemonkey/fusion/commands/ForceCommandsTest.java b/src/test/java/studio/magemonkey/fusion/commands/ForceCommandsTest.java index 8d586c1..0503766 100644 --- a/src/test/java/studio/magemonkey/fusion/commands/ForceCommandsTest.java +++ b/src/test/java/studio/magemonkey/fusion/commands/ForceCommandsTest.java @@ -2,7 +2,8 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; /** * Simple test to verify force command methods exist and have the expected signatures. @@ -16,31 +17,31 @@ public void testForceCommandMethodsExist() { // Verify that all force command methods exist as public static methods try { // Check forceJoinProfession method exists - CommandMechanics.class.getDeclaredMethod("forceJoinProfession", - org.bukkit.command.CommandSender.class, String[].class); - + CommandMechanics.class.getDeclaredMethod("forceJoinProfession", + org.bukkit.command.CommandSender.class, String[].class); + // Check forceLeaveProfession method exists - CommandMechanics.class.getDeclaredMethod("forceLeaveProfession", - org.bukkit.command.CommandSender.class, String[].class); - + CommandMechanics.class.getDeclaredMethod("forceLeaveProfession", + org.bukkit.command.CommandSender.class, String[].class); + // Check forceStats method exists - CommandMechanics.class.getDeclaredMethod("forceStats", - org.bukkit.command.CommandSender.class, String[].class); - + CommandMechanics.class.getDeclaredMethod("forceStats", + org.bukkit.command.CommandSender.class, String[].class); + // Check forceMaster method exists - CommandMechanics.class.getDeclaredMethod("forceMaster", - org.bukkit.command.CommandSender.class, String[].class); - + CommandMechanics.class.getDeclaredMethod("forceMaster", + org.bukkit.command.CommandSender.class, String[].class); + // Check forceShow method exists - CommandMechanics.class.getDeclaredMethod("forceShow", - org.bukkit.command.CommandSender.class, String[].class); - + CommandMechanics.class.getDeclaredMethod("forceShow", + org.bukkit.command.CommandSender.class, String[].class); + } catch (NoSuchMethodException e) { fail("Force command method not found: " + e.getMessage()); } } - @Test + @Test public void testCommandArgumentValidation() { // This test documents expected argument patterns for force commands // forcejoin = 3 args @@ -48,7 +49,7 @@ public void testCommandArgumentValidation() { // forcestats = 2 args // forcemaster = 3 args // forceshow = 2 args - + // Test would verify argument length checking but requires mocking the full environment assertTrue(true, "Force commands require 2-3 arguments as documented"); } From b418ce3774da9ef0750e0c69c556696fcd8aa20c Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Sun, 14 Sep 2025 18:54:02 +0200 Subject: [PATCH 10/16] fixed categories not being openable when registered in the gui --- .../java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java | 1 - .../java/studio/magemonkey/fusion/commands/Commands.java | 3 +-- .../studio/magemonkey/fusion/data/player/FusionPlayer.java | 1 + .../fusion/data/professions/ProfessionSettings.java | 2 +- src/main/java/studio/magemonkey/fusion/gui/CategoryGui.java | 5 ++++- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java b/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java index e91be64..d1f70ee 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java @@ -121,7 +121,6 @@ private static void loadProfessions(File root) { cfgs.put(ct.getName(), cfg); files.put(ct.getName(), file); injectProfessionLevelConfig(ct, file); - } catch (Exception e) { e.printStackTrace(); Fusion.getInstance().getLogger().warning("Can't load crafting table: " + e.getMessage()); diff --git a/src/main/java/studio/magemonkey/fusion/commands/Commands.java b/src/main/java/studio/magemonkey/fusion/commands/Commands.java index 50c5dc1..9af8c83 100644 --- a/src/main/java/studio/magemonkey/fusion/commands/Commands.java +++ b/src/main/java/studio/magemonkey/fusion/commands/Commands.java @@ -125,8 +125,7 @@ public List onTabComplete(@NotNull CommandSender sender, return List.of(); List entries = new ArrayList<>(); - List professions = new ArrayList<>(); - professions = new ArrayList<>(PlayerLoader.getPlayer((player).getUniqueId()).getProfessions()); + List professions = new ArrayList<>(PlayerLoader.getPlayer((player).getUniqueId()).getProfessions()); if (args.length == 1) { if (sender.hasPermission("fusion.browse") && "browse".startsWith(args[0])) entries.add("browse"); diff --git a/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java b/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java index bd8b9cd..465418a 100644 --- a/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java +++ b/src/main/java/studio/magemonkey/fusion/data/player/FusionPlayer.java @@ -3,6 +3,7 @@ import lombok.Getter; import lombok.Setter; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.entity.Player; import org.jetbrains.annotations.Nullable; import studio.magemonkey.fusion.cfg.sql.SQLManager; diff --git a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java index dc14c68..7a4cba6 100644 --- a/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java +++ b/src/main/java/studio/magemonkey/fusion/data/professions/ProfessionSettings.java @@ -274,7 +274,7 @@ private void generateIcon(String namespace) { meta = potionMeta; } builder = builder.data(meta); - this.recipeItem = new RecipeCustomItem(builder, iconReference.getAmount(), false); + this.recipeItem = new RecipeCustomItem(builder, 1, false); } } diff --git a/src/main/java/studio/magemonkey/fusion/gui/CategoryGui.java b/src/main/java/studio/magemonkey/fusion/gui/CategoryGui.java index 1f1a423..55924e8 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/CategoryGui.java +++ b/src/main/java/studio/magemonkey/fusion/gui/CategoryGui.java @@ -36,6 +36,7 @@ public class CategoryGui implements Listener { private final CraftingTable table; private Inventory inventory; + private final Map allCategoriesMap = new HashMap<>(); private final Map categories = new HashMap<>(); private int page = 0; private int nextPage = -1; @@ -103,6 +104,8 @@ public void reloadCategories() { : CodexEngine.get().getVault().getBalance(player)) }); + allCategories.forEach((category) -> allCategoriesMap.putIfAbsent(category.getName(), new RecipeGui(player, table, category))); + for (int k = (page * pageSize), e = Math.min(slots.length, allCategoryArray.length); (k < allCategoryArray.length) && (i < e); k++, i++) { @@ -255,7 +258,7 @@ private void nextPage() { public void open(Player player, Category category) { if (category == null) open(player); else { - for (RecipeGui gui : categories.values()) { + for (RecipeGui gui : allCategoriesMap.values()) { if (gui.getCategory().equals(category)) { gui.open(player); return; From d18c7967d261b7c01b72f9a2ac31927944c03034 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:38:57 +0200 Subject: [PATCH 11/16] remove latest gui on leave --- .../magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java b/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java index ef9204a..c5de114 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java +++ b/src/main/java/studio/magemonkey/fusion/gui/recipe/RecipeGuiEventRouter.java @@ -108,5 +108,6 @@ public void onPlayerQuit(PlayerQuitEvent event) { RecipeGui gui = ProfessionGuiRegistry.getLatestRecipeGui().get(p.getUniqueId()); if (gui == null) return; gui.close(p, gui.getInventory()); + ProfessionGuiRegistry.getLatestRecipeGui().remove(p.getUniqueId()); } } From 02e07a61d946b865faefd21e534da9b72f718771 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Tue, 16 Sep 2025 22:39:28 +0200 Subject: [PATCH 12/16] caching money to reduce lags through db-connections --- .../magemonkey/fusion/gui/RecipeGui.java | 6 +- .../magemonkey/fusion/hook/VaultHook.java | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 src/main/java/studio/magemonkey/fusion/hook/VaultHook.java diff --git a/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java b/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java index 02dfcda..81d107c 100644 --- a/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java +++ b/src/main/java/studio/magemonkey/fusion/gui/RecipeGui.java @@ -47,12 +47,12 @@ import studio.magemonkey.fusion.gui.recipe.InventoryFingerprint; import studio.magemonkey.fusion.gui.recipe.RecipeCacheKey; import studio.magemonkey.fusion.gui.slot.Slot; +import studio.magemonkey.fusion.hook.VaultHook; import studio.magemonkey.fusion.util.ChatUT; import studio.magemonkey.fusion.util.ExperienceManager; import studio.magemonkey.fusion.util.PlayerUtil; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; @Getter public class RecipeGui implements Listener { @@ -264,9 +264,7 @@ public void reloadRecipes() { // byte[] newHash = InventoryFingerprint.fingerprint(player); int newLevel = table.getLevelFunction().getLevel(player); - double newMoney = (CodexEngine.get().getVault() == null) - ? 0.0 - : CodexEngine.get().getVault().getBalance(player); + double newMoney = VaultHook.getBalance(player); boolean invChanged = !Arrays.equals(newHash, lastInventoryHash); boolean levelChanged = (newLevel != lastSeenLevel); diff --git a/src/main/java/studio/magemonkey/fusion/hook/VaultHook.java b/src/main/java/studio/magemonkey/fusion/hook/VaultHook.java new file mode 100644 index 0000000..029c31c --- /dev/null +++ b/src/main/java/studio/magemonkey/fusion/hook/VaultHook.java @@ -0,0 +1,67 @@ +package studio.magemonkey.fusion.hook; + +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; +import studio.magemonkey.codex.CodexEngine; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.function.Consumer; + +public class VaultHook { + + private static BukkitTask task; + private static Map> storedBalances = new HashMap<>(); + private static int thresholdSeconds = 10; + + public static double getBalance(Player player) { + if (storedBalances.containsKey(player.getUniqueId())) { + Pair balanceData = storedBalances.get(player.getUniqueId()); + double balance = balanceData.getLeft(); + LocalDateTime timestamp = balanceData.getRight(); + if (timestamp.plusSeconds(thresholdSeconds).isBefore(LocalDateTime.now())) { + double updatedBalance = CodexEngine.get().getVault() != null ? CodexEngine.get().getVault().getBalance(player) : 0.0; + storedBalances.put(player.getUniqueId(), Pair.of(updatedBalance, LocalDateTime.now())); + return updatedBalance; + } else { + return balance; + } + } else { + double balance = CodexEngine.get().getVault() != null ? CodexEngine.get().getVault().getBalance(player) : 0.0; + storedBalances.put(player.getUniqueId(), Pair.of(balance, LocalDateTime.now())); + return balance; + } + } + + public static void startMoneyUpdateTask() { + // Schedule a repeating task to update all stored balances every thresholdSeconds + task = Bukkit.getScheduler().runTaskTimerAsynchronously(CodexEngine.get(), () -> { + for (UUID uuid : storedBalances.keySet()) { + Player player = Bukkit.getPlayer(uuid); + if (player != null && player.isOnline()) { + getBalanceAsync(player, balance -> { + storedBalances.put(uuid, Pair.of(balance, LocalDateTime.now())); + }); + } + } + }, thresholdSeconds * 20L, thresholdSeconds * 20L); + } + + public static void cancelMoneyUpdateTask() { + if (task != null) { + task.cancel(); + task = null; + } + } + + private static void getBalanceAsync(Player player, Consumer moneyConsumer) { + Bukkit.getScheduler().runTaskAsynchronously(CodexEngine.get(), () -> { + double balance = CodexEngine.get().getVault() != null ? CodexEngine.get().getVault().getBalance(player) : 0.0; + moneyConsumer.accept(balance); + }); + } +} From b9c341ce9e2b324948f4a7f3b5da8ea8365ae30d Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Wed, 17 Sep 2025 11:20:43 +0200 Subject: [PATCH 13/16] added debug for issue handling with queue data loss on rejoining --- .../studio/magemonkey/fusion/data/queue/CraftingQueue.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java b/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java index a7d1c53..68117a3 100644 --- a/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java +++ b/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java @@ -12,6 +12,7 @@ import studio.magemonkey.fusion.cfg.Cfg; import studio.magemonkey.fusion.cfg.ProfessionsCfg; import studio.magemonkey.fusion.cfg.sql.SQLManager; +import studio.magemonkey.fusion.data.player.FusionPlayer; import studio.magemonkey.fusion.data.player.PlayerLoader; import studio.magemonkey.fusion.data.professions.pattern.Category; import studio.magemonkey.fusion.data.recipes.Recipe; @@ -50,6 +51,10 @@ public CraftingQueue(Player player, String profession, Category category) { * queue sequentially. All items are saved with the same timestamp when * saved, so use the first item's timestamp to calculate the offline duration. */ + if(!queue.isEmpty()) { + Fusion.getInstance().getLogger().warning("[Debug] Loaded " + queue.size() + " items for " + player.getName() + " in " + profession + " - " + category.getName() + ": ItemPaths:" + queue.stream().map(item -> item.getRecipe().getRecipePath()).toList()); + } + if (Cfg.updateQueueOffline && !queue.isEmpty()) { long now = System.currentTimeMillis(); // find the first unfinished item From 9aadc3e2814c8ba9981a513d39b8a94f107be620 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Wed, 17 Sep 2025 23:38:07 +0200 Subject: [PATCH 14/16] fixed queue data loss with properly configured primary keys --- .../java/studio/magemonkey/fusion/Fusion.java | 4 +-- .../cfg/sql/tables/FusionQueuesSQL.java | 30 +++++-------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/Fusion.java b/src/main/java/studio/magemonkey/fusion/Fusion.java index 69b0198..59eb78d 100644 --- a/src/main/java/studio/magemonkey/fusion/Fusion.java +++ b/src/main/java/studio/magemonkey/fusion/Fusion.java @@ -127,8 +127,8 @@ public void onEnable() { LevelFunction.generate(200); this.getCommand("craft").setExecutor(new Commands()); this.getCommand("fusion-editor").setExecutor(new FusionEditorCommand()); - getServer().getPluginManager().registerEvents(this, this); - Bukkit.getPluginManager().registerEvents(new RecipeGuiEventRouter(), this); + registerListener(this); + registerListener(new RecipeGuiEventRouter()); runQueueTask(); if (hookManager.isHooked(HookType.PlaceholderAPI)) { diff --git a/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java b/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java index 9af7774..8c2050b 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/sql/tables/FusionQueuesSQL.java @@ -22,7 +22,7 @@ public class FusionQueuesSQL { public FusionQueuesSQL() { try (PreparedStatement create = SQLManager.connection() .prepareStatement("CREATE TABLE IF NOT EXISTS " + Table + "(" - + "Id long," + + "Id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY," + "UUID varchar(36), " + "RecipePath varchar(100)," + "CraftingTime numeric," @@ -37,33 +37,17 @@ public FusionQueuesSQL() { } } - public long getNextId() { - try (PreparedStatement select = SQLManager.connection().prepareStatement("SELECT Count(Id) FROM " + Table)) { - ResultSet result = select.executeQuery(); - if (result.next()) { - return result.getLong(1); - } - } catch (SQLException e) { - Fusion.getInstance() - .getLogger() - .warning("[SQL:FusionQueuesSQL:getNextId] Something went wrong with the sql-connection: " - + e.getMessage()); - } - return 0; - } - public boolean setQueueItem(UUID uuid, QueueItem item) { if (item == null) return false; if (item.getId() == -1) { try (PreparedStatement insert = SQLManager.connection() .prepareStatement("INSERT INTO " + Table - + "(Id, UUID, RecipePath, Timestamp, CraftingTime, SavedSeconds) VALUES (?,?,?,?,?,?)")) { - insert.setLong(1, getNextId()); - insert.setString(2, uuid.toString()); - insert.setString(3, item.getRecipePath()); - insert.setLong(4, item.getTimestamp()); - insert.setLong(5, item.getRecipe().getCraftingTime()); - insert.setLong(6, item.getSavedSeconds()); + + "(UUID, RecipePath, Timestamp, CraftingTime, SavedSeconds) VALUES (?,?,?,?,?)")) { + insert.setString(1, uuid.toString()); + insert.setString(2, item.getRecipePath()); + insert.setLong(3, item.getTimestamp()); + insert.setLong(4, item.getRecipe().getCraftingTime()); + insert.setLong(5, item.getSavedSeconds()); insert.execute(); return true; } catch (SQLException e) { From 362ff2a5074532c3d477b8c8276a565a564383c0 Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Wed, 17 Sep 2025 23:38:32 +0200 Subject: [PATCH 15/16] removed debug --- .../studio/magemonkey/fusion/data/queue/CraftingQueue.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java b/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java index 68117a3..def10b6 100644 --- a/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java +++ b/src/main/java/studio/magemonkey/fusion/data/queue/CraftingQueue.java @@ -51,10 +51,6 @@ public CraftingQueue(Player player, String profession, Category category) { * queue sequentially. All items are saved with the same timestamp when * saved, so use the first item's timestamp to calculate the offline duration. */ - if(!queue.isEmpty()) { - Fusion.getInstance().getLogger().warning("[Debug] Loaded " + queue.size() + " items for " + player.getName() + " in " + profession + " - " + category.getName() + ": ItemPaths:" + queue.stream().map(item -> item.getRecipe().getRecipePath()).toList()); - } - if (Cfg.updateQueueOffline && !queue.isEmpty()) { long now = System.currentTimeMillis(); // find the first unfinished item From 2f6666a9c071c0fdcb88c6766f38272133e53b9e Mon Sep 17 00:00:00 2001 From: MaksyKun <77341370+MaksyKun@users.noreply.github.com> Date: Thu, 18 Sep 2025 23:04:16 +0200 Subject: [PATCH 16/16] fixed skull meta on queued items --- .../magemonkey/fusion/cfg/ProfessionsCfg.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java b/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java index d1f70ee..ec69b80 100644 --- a/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java +++ b/src/main/java/studio/magemonkey/fusion/cfg/ProfessionsCfg.java @@ -1,13 +1,16 @@ package studio.magemonkey.fusion.cfg; import lombok.Getter; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; import studio.magemonkey.codex.legacy.item.ItemBuilder; +import studio.magemonkey.codex.legacy.item.SkullBuilder; import studio.magemonkey.fusion.Fusion; import studio.magemonkey.fusion.cfg.migrations.ProfessionMigration; import studio.magemonkey.fusion.data.professions.pattern.Category; @@ -15,6 +18,7 @@ import studio.magemonkey.fusion.data.recipes.CraftingTable; import studio.magemonkey.fusion.gui.ProfessionGuiRegistry; import studio.magemonkey.fusion.hook.NexoHook; +import studio.magemonkey.fusion.util.ChatUT; import studio.magemonkey.fusion.util.Utils; import java.io.File; @@ -464,10 +468,17 @@ public static ItemStack getQueueItem(String key, QueueItem item) { .warning("Profession '" + key + "' has an unknown material: " + materialString); return new ItemStack(Material.AIR); } + if(material != result.getType()) result.setType(material); + ItemMeta meta = result.getItemMeta(); + if(meta != null) { + List lore = cfg.getStringList(path + ".lore"); + lore.replaceAll(s -> ChatUT.hexString(s.replace("%time%", Utils.getFormattedTime(item.getVisualRemainingItemTime())))); + meta.setLore(lore); + result.setItemMeta(meta); + } + - List lore = cfg.getStringList(path + ".lore"); - lore.replaceAll(s -> s.replace("%time%", Utils.getFormattedTime(item.getVisualRemainingItemTime()))); - return ItemBuilder.newItem(result).material(material).lore(lore).build(); + return result; } public static void closeAll() {