From 70aa917cfbdd7a1297d440b666d0ca296cccf729 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Thu, 20 Mar 2025 03:27:24 +0800 Subject: [PATCH] 0.0.35 --- bukkit-loader/src/main/resources/config.yml | 10 +- .../resources/default/configuration/items.yml | 66 ++++++ .../resources/internal/configuration/gui.yml | 8 +- .../gui/custom/smithing_transform_recipe.png | Bin 0 -> 2219 bytes .../font/gui/custom/stonecutting_recipe.png | Bin 2251 -> 4344 bytes .../item/recipe/BukkitRecipeManager.java | 4 +- .../item/recipe/RecipeEventListener.java | 16 ++ .../craftengine/bukkit/util/Reflections.java | 12 + .../recipe/CustomSmithingTransformRecipe.java | 2 +- .../item/recipe/CustomStoneCuttingRecipe.java | 2 +- .../core/item/recipe/RecipeTypes.java | 4 +- .../vanilla/VanillaStoneCuttingRecipe.java | 2 +- .../core/pack/AbstractPackManager.java | 1 + .../gui/category/ItemBrowserManager.java | 4 +- .../gui/category/ItemBrowserManagerImpl.java | 207 +++++++++++++++++- gradle.properties | 4 +- 16 files changed, 326 insertions(+), 16 deletions(-) create mode 100644 bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png diff --git a/bukkit-loader/src/main/resources/config.yml b/bukkit-loader/src/main/resources/config.yml index fb908e038..125390fb7 100644 --- a/bukkit-loader/src/main/resources/config.yml +++ b/bukkit-loader/src/main/resources/config.yml @@ -26,9 +26,9 @@ resource-pack: obfuscation: enable: false seed: 0 # 0 = random seed - fake-directory: true - escape-unicode: true - break-json: true + fake-directory: false + escape-unicode: false + break-json: false resource-location: enable: true random-namespace: @@ -184,12 +184,14 @@ gui: title: "" smoking: title: "" - campfire: + campfire-cooking: title: "" crafting: title: "" stonecutting: title: "" + smithing-transform: + title: "" performance: # Maximum chain update depth when fixing client visuals diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/items.yml b/bukkit-loader/src/main/resources/resources/default/configuration/items.yml index f01d4a7b7..979df89bc 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/items.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/items.yml @@ -329,4 +329,70 @@ recipes#11: B: "minecraft:stick" result: id: default:topaz_pickaxe + count: 1 + default:topaz_helmet: + type: shaped + pattern: + - "AAA" + - "A A" + ingredients: + A: "default:topaz" + result: + id: default:topaz_helmet + count: 1 + default:topaz_chestplate: + type: shaped + pattern: + - "A A" + - "AAA" + - "AAA" + ingredients: + A: "default:topaz" + result: + id: default:topaz_chestplate + count: 1 + default:topaz_leggings: + type: shaped + pattern: + - "AAA" + - "A A" + - "A A" + ingredients: + A: "default:topaz" + result: + id: default:topaz_leggings + count: 1 + default:topaz_boots: + type: shaped + pattern: + - "A A" + - "A A" + ingredients: + A: "default:topaz" + result: + id: default:topaz_boots + count: 1 + default:topaz_bow: + type: smithing_transform + base: minecraft:bow + addition: default:topaz + template-type: default:topaz + result: + id: default:topaz_bow + count: 1 + default:topaz_crossbow: + type: smithing_transform + base: minecraft:bow + addition: default:topaz + template-type: default:topaz + result: + id: default:topaz_crossbow + count: 1 + default:topaz_rod: + type: smithing_transform + base: minecraft:fishing_rod + addition: default:topaz + template-type: default:topaz + result: + id: default:topaz_rod count: 1 \ No newline at end of file diff --git a/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml b/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml index b81da6caf..7ba729dc6 100644 --- a/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml +++ b/bukkit-loader/src/main/resources/resources/internal/configuration/gui.yml @@ -53,12 +53,18 @@ images: font: minecraft:internal file: minecraft:font/gui/custom/stonecutting_recipe.png char: '\ub008' + internal:smithing_transform_recipe: + height: 142 + ascent: 20 + font: minecraft:internal + file: minecraft:font/gui/custom/smithing_transform_recipe.png + char: '\ub009' internal:no_recipe: height: 140 ascent: 18 font: minecraft:internal file: minecraft:font/gui/custom/no_recipe.png - char: '\ub009' + char: '\ub00a' templates: internal:icon/2d: diff --git a/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png b/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png new file mode 100644 index 0000000000000000000000000000000000000000..31b6ea3e5def92f421a725cf8661f76535ff67e2 GIT binary patch literal 2219 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 delta 1494 zcmV;{1u6RYAp^02y>eSaefwW^{L9a%BKPWN%_+AW3auXJt}l zVPtu6$z?nM00SqHI-eIfVJsjrFfueRFf%VOHZ3tRIyEvnFg3C60RfYb0yC3E0~eEC z1P1{*lcWP6lZXQ~lP?62lfwl)e_9$^QUCw|Ay7jR!+5K@h z8{;Ji+#Lutvm2X2us0rHFH9-t@K5pQ<6KK)nuxtu7l ztL`d0R7cQjhf0o62Rf{BkW+}02Zo|%PWY_a@^*g3uk{uD;$?2N=`UG6H2bLWGIpU#gG#f_k1zoH$Zc6^f0Wo3)yKa42(XK7 zlBB|pBj_~&5iWY2olO!G=h;!eU$nNdt364PovgG!USYFa1I8{E(cV^e@3FZaF-#)TJ1NuZS1%lKnH$;t+vMuyQrpXB1cl?kVo0XZ>LC2jl0Y~ zk=uZCNl_!Dx;0YkM5-hStS4cuY?ftL)pU(E$?W2j>)8y%j@7og^`StXT}+jb4Hg zUgaNQre@+`lVWby+}E<1&o*xAOpw(cDL%|D?Im3{b<^XRSnU~5elK|kJAWu;+G)+I z4>r;4xE$CqiOXi7O)`Jr>a)|aItPmB16Kywx%(roP{+QJnADBg|p#WdY@r4;++uq!%E=MhVp6rwMjz!!%jj1 z0%;kMD#EX1XEK*Hk3B{#J+ej8=g}9nb}*J?zB)7LN`g^K&}hr4-1gkznBJ*zVt?Ly zI>0_>rnNgS@C|xhaOLpS_dcIAPDMx^b?*!cIi0sQSZy?wu=Or=ElPiHrJFpPza2T)6i1MTApD zVByN6F&~+$_|V97QMKo`Ju%m0PxfR__GG7v%I#dsfcxhvvr%s6S_C{W7v%ZdUl@}; w*?*dihYP`m|33lS%>kEuu6T6p3-K$!0AtP;RZi9@rT_o{07*qoM6N<$g192~>i_@% diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java index 72918957f..7f34ce945 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/BukkitRecipeManager.java @@ -195,7 +195,7 @@ public class BukkitRecipeManager implements RecipeManager { CraftEngine.instance().logger().warn("Failed to convert campfire recipe", e); } }); - BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONE_CUTTING, (key, recipe) -> { + BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.STONECUTTING, (key, recipe) -> { CustomStoneCuttingRecipe ceRecipe = (CustomStoneCuttingRecipe) recipe; List itemStacks = new ArrayList<>(); for (Holder item : ceRecipe.ingredient().items()) { @@ -383,7 +383,7 @@ public class BukkitRecipeManager implements RecipeManager { this.byId.put(id, recipe); this.byResult.computeIfAbsent(recipe.result().item().id(), k -> new ArrayList<>()).add(recipe); for (Ingredient ingredient : recipe.ingredientsInUse()) { - for (Holder holder : ingredient.items()) { + for (Holder holder : ingredient.items().stream().distinct().toList()) { this.byIngredient.computeIfAbsent(holder.value(), k -> new ArrayList<>()).add(recipe); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java index 35b3e4060..f6b0518cb 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/RecipeEventListener.java @@ -835,6 +835,7 @@ public class RecipeEventListener implements Listener { @EventHandler(ignoreCancelled = true) public void onSmithingTransform(PrepareSmithingEvent event) { + if (!ConfigManager.enableRecipeSystem()) return; SmithingInventory inventory = event.getInventory(); if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return; @@ -872,6 +873,21 @@ public class RecipeEventListener implements Listener { CustomSmithingTransformRecipe transformRecipe = (CustomSmithingTransformRecipe) ceRecipe; ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base)); event.setResult(processed); + correctSmithingRecipeUsed(inventory, ceRecipe); + } + + private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe recipe) { + Object holderOrRecipe = recipeManager.getRecipeHolderByRecipe(recipe); + if (holderOrRecipe == null) { + // it's a vanilla recipe but not injected + return; + } + try { + Object resultInventory = Reflections.field$CraftResultInventory$resultInventory.get(inventory); + Reflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe); + } catch (ReflectiveOperationException e) { + plugin.logger().warn("Failed to correct used recipe", e); + } } private OptimizedIDItem getOptimizedIDItem(@Nullable ItemStack itemStack) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index c7850595e..0e474bebd 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -4414,6 +4414,18 @@ public class Reflections { ) ); + public static final Class clazz$CraftResultInventory = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleCBClass("inventory.CraftResultInventory") + ) + ); + + public static final Field field$CraftResultInventory$resultInventory = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$CraftResultInventory, clazz$Container, 0 + ) + ); + // 1.20.5+ public static final Method method$ItemStack$hurtAndBreak = ReflectionUtils.getMethod( diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java index cda1f1288..449866c83 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTransformRecipe.java @@ -124,7 +124,7 @@ public class CustomSmithingTransformRecipe implements Recipe { @Override public Recipe create(Key id, Map arguments) { List base = MiscUtils.getAsStringList(arguments.get("base")); - List addition = MiscUtils.getAsStringList(arguments.get("addition-input")); + List addition = MiscUtils.getAsStringList(arguments.get("addition")); List template = MiscUtils.getAsStringList(arguments.get("template-type")); return new CustomSmithingTransformRecipe<>( id, diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java index 9d95bfe89..bc0cbc901 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomStoneCuttingRecipe.java @@ -36,7 +36,7 @@ public class CustomStoneCuttingRecipe extends AbstractGroupedRecipe { @Override public @NotNull Key type() { - return RecipeTypes.STONE_CUTTING; + return RecipeTypes.STONECUTTING; } public Ingredient ingredient() { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java index 523470030..4f9b7a047 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeTypes.java @@ -16,7 +16,7 @@ public class RecipeTypes { public static final Key BLASTING = Key.of("minecraft:blasting"); public static final Key SMOKING = Key.of("minecraft:smoking"); public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking"); - public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting"); + public static final Key STONECUTTING = Key.of("minecraft:stonecutting"); public static final Key SMITHING_TRANSFORM = Key.of("minecraft:smithing_transform"); public static final Key SMITHING_TRIM = Key.of("minecraft:smithing_trim"); @@ -27,7 +27,7 @@ public class RecipeTypes { register(SMOKING, CustomSmokingRecipe.FACTORY); register(BLASTING, CustomBlastingRecipe.FACTORY); register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY); - register(STONE_CUTTING, CustomStoneCuttingRecipe.FACTORY); + register(STONECUTTING, CustomStoneCuttingRecipe.FACTORY); register(SMITHING_TRANSFORM, CustomSmithingTransformRecipe.FACTORY); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java index bd032294d..864557c68 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaStoneCuttingRecipe.java @@ -19,6 +19,6 @@ public class VanillaStoneCuttingRecipe extends VanillaGroupedRecipe { @Override public Key type() { - return RecipeTypes.STONE_CUTTING; + return RecipeTypes.STONECUTTING; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index 359bd76bd..c67945b43 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -249,6 +249,7 @@ public abstract class AbstractPackManager implements PackManager { plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smelting.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/campfire.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png"); + plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/cooking_recipe.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/crafting_recipe.png"); plugin.saveResource("resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/no_recipe.png"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java index 222136c53..9586fb7ad 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManager.java @@ -65,6 +65,7 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser { public static String RECIPE_CAMPFIRE_TITLE; public static String RECIPE_CRAFTING_TITLE; public static String RECIPE_STONECUTTING_TITLE; + public static String RECIPE_SMITHING_TRANSFORM_TITLE; public static Key RECIPE_BACK; public static Key RECIPE_EXIT; public static Key RECIPE_NEXT_PAGE_AVAILABLE; @@ -100,9 +101,10 @@ public interface ItemBrowserManager extends Reloadable, ConfigSectionParser { RECIPE_BLASTING_TITLE = getOrThrow(section, "recipe.blasting.title"); RECIPE_SMELTING_TITLE = getOrThrow(section, "recipe.smelting.title"); RECIPE_SMOKING_TITLE = getOrThrow(section, "recipe.smoking.title"); - RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire.title"); + RECIPE_CAMPFIRE_TITLE = getOrThrow(section, "recipe.campfire-cooking.title"); RECIPE_CRAFTING_TITLE = getOrThrow(section, "recipe.crafting.title"); RECIPE_STONECUTTING_TITLE = getOrThrow(section, "recipe.stonecutting.title"); + RECIPE_SMITHING_TRANSFORM_TITLE = getOrThrow(section, "recipe.smithing-transform.title"); RECIPE_BACK = Key.of(getOrThrow(section, "recipe.page-navigation.return")); RECIPE_EXIT = Key.of(getOrThrow(section, "recipe.page-navigation.exit")); RECIPE_NEXT_PAGE_AVAILABLE = Key.of(getOrThrow(section, "recipe.page-navigation.next.available")); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java index 5742fe02d..2b203b19d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/gui/category/ItemBrowserManagerImpl.java @@ -349,10 +349,215 @@ public class ItemBrowserManagerImpl implements ItemBrowserManager { openCookingRecipePage(player, (CustomCookingRecipe) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage); return; } - if (recipeType == RecipeTypes.STONE_CUTTING) { + if (recipeType == RecipeTypes.STONECUTTING) { openStoneCuttingRecipePage(player, (CustomStoneCuttingRecipe) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage); return; } + if (recipeType == RecipeTypes.SMITHING_TRANSFORM) { + openSmithingTransformRecipePage(player, (CustomSmithingTransformRecipe) recipe, parentGui, recipes, index, depth, canOpenNoRecipePage); + return; + } + } + + public void openSmithingTransformRecipePage(Player player, CustomSmithingTransformRecipe recipe, Gui parentGui, List> recipes, int index, int depth, boolean canOpenNoRecipePage) { + Key previous = index > 0 ? Constants.RECIPE_PREVIOUS_PAGE_AVAILABLE : Constants.RECIPE_PREVIOUS_PAGE_BLOCK; + Key next = index + 1 < recipes.size() ? Constants.RECIPE_NEXT_PAGE_AVAILABLE : Constants.RECIPE_NEXT_PAGE_BLOCK; + Key result = recipe.result().item().id(); + GuiLayout layout = new GuiLayout( + " ", + " ", + " ABC X ", + " ^ ", + " ", + " < = > " + ) + .addIngredient('X', GuiElement.constant(this.plugin.itemManager().createWrappedItem(result, player).count(recipe.result().count()), (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(result, player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(result); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, result, e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(result); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })) + .addIngredient('^', player.hasPermission(GET_ITEM_PERMISSION) ? GuiElement.constant(this.plugin.itemManager().createWrappedItem(Constants.RECIPE_GET_ITEM, player), (e, c) -> { + c.cancel(); + player.playSound(Constants.SOUND_PICK_ITEM); + if (LEFT_CLICK.contains(c.type())) { + player.giveItem(this.plugin.itemManager().createWrappedItem(result, player)); + } else if (RIGHT_CLICK.contains(c.type())) { + Item item = this.plugin.itemManager().createWrappedItem(result, player); + player.giveItem(item.count(item.maxStackSize())); + } + }) : GuiElement.EMPTY) + .addIngredient('=', GuiElement.constant(this.plugin.itemManager().getCustomItem(parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT) + .map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.EMPTY))) + .orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + (parentGui != null ? Constants.RECIPE_BACK : Constants.RECIPE_EXIT))), + ((element, click) -> { + click.cancel(); + player.playSound(Constants.SOUND_RETURN_PAGE, 0.25f, 1); + if (parentGui != null) { + parentGui.open(player); + } else { + player.closeInventory(); + } + })) + ) + .addIngredient('>', GuiElement.constant(this.plugin.itemManager() + .getCustomItem(next) + .map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder() + .withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1)) + .withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size())) + .build()))) + .orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + next)), (e, c) -> { + c.cancel(); + if (index + 1 < recipes.size()) { + player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1); + openRecipePage(player, parentGui, recipes, index + 1, depth, canOpenNoRecipePage); + } + })) + .addIngredient('<', GuiElement.constant(this.plugin.itemManager() + .getCustomItem(previous) + .map(it -> it.buildItem(ItemBuildContext.of(player, ContextHolder.builder() + .withParameter(GuiParameters.CURRENT_PAGE, String.valueOf(index + 1)) + .withParameter(GuiParameters.MAX_PAGE, String.valueOf(recipes.size())) + .build()))) + .orElseThrow(() -> new GuiElementMissingException("Can't find gui element " + previous)), (e, c) -> { + c.cancel(); + if (index > 0) { + player.playSound(Constants.SOUND_CHANGE_PAGE, 0.25f, 1); + openRecipePage(player, parentGui, recipes, index - 1, depth, canOpenNoRecipePage); + } + })); + + + List> templates = new ArrayList<>(); + Optional.ofNullable(recipe.template()).ifPresent(it -> { + for (Holder in : it.items()) { + templates.add(this.plugin.itemManager().createWrappedItem(in.value(), player)); + } + }); + layout.addIngredient('A', templates.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(templates, (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, e.item().id(), e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })); + + List> bases = new ArrayList<>(); + Optional.ofNullable(recipe.base()).ifPresent(it -> { + for (Holder in : it.items()) { + bases.add(this.plugin.itemManager().createWrappedItem(in.value(), player)); + } + }); + layout.addIngredient('B', bases.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(bases, (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, e.item().id(), e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })); + + List> additions = new ArrayList<>(); + Optional.ofNullable(recipe.addition()).ifPresent(it -> { + for (Holder in : it.items()) { + additions.add(this.plugin.itemManager().createWrappedItem(in.value(), player)); + } + }); + layout.addIngredient('C', additions.isEmpty() ? GuiElement.EMPTY : GuiElement.recipeIngredient(additions, (e, c) -> { + c.cancel(); + if (MIDDLE_CLICK.contains(c.type()) && player.isCreativeMode() && player.hasPermission(GET_ITEM_PERMISSION) && c.itemOnCursor() == null) { + Item item = this.plugin.itemManager().createWrappedItem(e.item().id(), player); + item.count(item.maxStackSize()); + c.setItemOnCursor(item); + return; + } + if (LEFT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByResult(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } else if (canOpenNoRecipePage) { + openNoRecipePage(player, e.item().id(), e.gui(), 0); + } + } else if (RIGHT_CLICK.contains(c.type())) { + List> inRecipes = this.plugin.recipeManager().getRecipeByIngredient(e.item().id()); + if (inRecipes == recipes) return; + player.playSound(Constants.SOUND_CLICK_BUTTON); + if (!inRecipes.isEmpty()) { + openRecipePage(c.clicker(), e.gui(), inRecipes, 0, 0, canOpenNoRecipePage); + } + } + })); + + BasicGui.builder() + .layout(layout) + .inventoryClickConsumer(c -> { + if (MOVE_TO_OTHER_INV.contains(c.type()) || DOUBLE_CLICK.contains(c.type())) { + c.cancel(); + } + }) + .build() + .title(AdventureHelper.miniMessage().deserialize(Constants.RECIPE_SMITHING_TRANSFORM_TITLE, ItemBuildContext.of(player, ContextHolder.EMPTY).tagResolvers())) + .refresh() + .open(player); } public void openStoneCuttingRecipePage(Player player, CustomStoneCuttingRecipe recipe, Gui parentGui, List> recipes, int index, int depth, boolean canOpenNoRecipePage) { diff --git a/gradle.properties b/gradle.properties index 4366964ee..eb61f868c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.36 +project_version=0.0.35 config_version=15 lang_version=3 project_group=net.momirealms @@ -38,7 +38,7 @@ geantyref_version=1.3.16 zstd_version=1.5.6-9 commons_io_version=2.17.0 sparrow_nbt_version=0.3 -sparrow_util_version=0.27 +sparrow_util_version=0.29 fastutil_version=8.5.15 netty_version=4.1.119.Final joml_version=1.10.8