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 000000000..31b6ea3e5 Binary files /dev/null and b/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/smithing_transform_recipe.png differ diff --git a/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png b/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png index 3fe5819f0..3ff743370 100644 Binary files a/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png and b/bukkit-loader/src/main/resources/resources/internal/resourcepack/assets/minecraft/textures/font/gui/custom/stonecutting_recipe.png differ 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