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 aaa910a99..8fa4cdf02 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 @@ -330,14 +330,12 @@ public class RecipeEventListener implements Listener { if (clicked == null) return; Material type = clicked.getType(); if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return; - if (!VersionHelper.isOrAbove1_21_2()) { - if (clicked.getState() instanceof Campfire campfire) { - try { - Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire); - BukkitInjector.injectCookingBlockEntity(blockEntity); - } catch (Exception e) { - this.plugin.logger().warn("Failed to inject cooking block entity", e); - } + if (clicked.getState() instanceof Campfire campfire) { + try { + Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(campfire); + BukkitInjector.injectCookingBlockEntity(blockEntity); + } catch (Exception e) { + this.plugin.logger().warn("Failed to inject cooking block entity", e); } } @@ -704,59 +702,90 @@ public class RecipeEventListener implements Listener { try { Object mcRecipe = Reflections.field$CraftComplexRecipe$recipe.get(complexRecipe); - if (!Reflections.clazz$RepairItemRecipe.isInstance(mcRecipe)) { + + // Repair recipe + if (Reflections.clazz$RepairItemRecipe.isInstance(mcRecipe)) { + // repair item + ItemStack[] itemStacks = inventory.getMatrix(); + Pair onlyTwoItems = getTheOnlyTwoItem(itemStacks); + if (onlyTwoItems.left() == null || onlyTwoItems.right() == null) { + inventory.setResult(null); + return; + } + + Item left = plugin.itemManager().wrap(onlyTwoItems.left()); + Item right = plugin.itemManager().wrap(onlyTwoItems.right()); + if (!left.id().equals(right.id())) { + inventory.setResult(null); + return; + } + + int totalDamage = right.damage().orElse(0) + left.damage().orElse(0); + int totalMaxDamage = left.maxDamage().get() + right.maxDamage().get(); + // should be impossible, but take care + if (totalDamage >= totalMaxDamage) { + inventory.setResult(null); + return; + } + + Player player; + try { + player = (Player) Reflections.method$InventoryView$getPlayer.invoke(event.getView()); + } catch (ReflectiveOperationException e) { + plugin.logger().warn("Failed to get inventory viewer", e); + return; + } + + Optional> customItemOptional = plugin.itemManager().getCustomItem(left.id()); + if (customItemOptional.isEmpty()) { + inventory.setResult(null); + return; + } + + CustomItem customItem = customItemOptional.get(); + if (!customItem.settings().canRepair()) { + inventory.setResult(null); + return; + } + + Item newItem = customItem.buildItem(ItemBuildContext.of(plugin.adapt(player))); + int remainingDurability = totalMaxDamage - totalDamage; + int newItemDamage = Math.max(0, newItem.maxDamage().get() - remainingDurability); + newItem.damage(newItemDamage); + inventory.setResult(newItem.load()); + } else if (Reflections.clazz$ArmorDyeRecipe.isInstance(mcRecipe)) { + ItemStack[] itemStacks = inventory.getMatrix(); + Pair onlyTwoItems = getTheOnlyTwoItem(itemStacks); + if (onlyTwoItems.left() == null || onlyTwoItems.right() == null) { + inventory.setResult(null); + return; + } + + Item left = plugin.itemManager().wrap(onlyTwoItems.left()); + Item right = plugin.itemManager().wrap(onlyTwoItems.right()); + // can't be two custom items + if (left.isCustomItem() && right.isCustomItem()) { + inventory.setResult(null); + return; + } + + Optional> customLeftItem = left.getCustomItem(); + if (customLeftItem.isPresent()) { + if (!customLeftItem.get().settings().dyeable()) { + inventory.setResult(null); + } + } else { + Optional> customRightItem = right.getCustomItem(); + if (customRightItem.isPresent()) { + if (!customRightItem.get().settings().dyeable()) { + inventory.setResult(null); + } + } + } + } else { inventory.setResult(null); return; } - - // repair item - ItemStack[] itemStacks = inventory.getMatrix(); - Pair onlyTwoItems = getTheOnlyTwoItem(itemStacks); - if (onlyTwoItems.left() == null || onlyTwoItems.right() == null) { - inventory.setResult(null); - return; - } - - Item left = plugin.itemManager().wrap(onlyTwoItems.left()); - Item right = plugin.itemManager().wrap(onlyTwoItems.right()); - if (!left.id().equals(right.id())) { - inventory.setResult(null); - return; - } - - int totalDamage = right.damage().orElse(0) + left.damage().orElse(0); - int totalMaxDamage = left.maxDamage().get() + right.maxDamage().get(); - // should be impossible, but take care - if (totalDamage >= totalMaxDamage) { - inventory.setResult(null); - return; - } - - Player player; - try { - player = (Player) Reflections.method$InventoryView$getPlayer.invoke(event.getView()); - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to get inventory viewer", e); - return; - } - - Optional> customItemOptional = plugin.itemManager().getCustomItem(left.id()); - if (customItemOptional.isEmpty()) { - inventory.setResult(null); - return; - } - - CustomItem customItem = customItemOptional.get(); - if (!customItem.settings().canRepair()) { - inventory.setResult(null); - return; - } - - Item newItem = customItem.buildItem(ItemBuildContext.of(plugin.adapt(player))); - int remainingDurability = totalMaxDamage - totalDamage; - int newItemDamage = Math.max(0, newItem.maxDamage().get() - remainingDurability); - newItem.damage(newItemDamage); - inventory.setResult(newItem.load()); } catch (Exception e) { this.plugin.logger().warn("Failed to handle minecraft custom recipe", e); } 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 64f6096c4..b12714cee 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 @@ -5269,6 +5269,13 @@ public class Reflections { ) ); + public static final Class clazz$ArmorDyeRecipe = requireNonNull( + BukkitReflectionUtils.findReobfOrMojmapClass( + "world.item.crafting.RecipeArmorDye", + "world.item.crafting.ArmorDyeRecipe" + ) + ); + public static final Field field$CraftComplexRecipe$recipe = requireNonNull( ReflectionUtils.getDeclaredField( clazz$CraftComplexRecipe, clazz$CustomRecipe, 0 diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java index c536b3725..b16dcf2a0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemSettings.java @@ -27,6 +27,7 @@ public class ItemSettings { boolean renameable = true; boolean canPlaceRelatedVanillaBlock = false; ProjectileMeta projectileMeta; + boolean dyeable = false; private ItemSettings() {} @@ -56,6 +57,7 @@ public class ItemSettings { newSettings.renameable = settings.renameable; newSettings.canPlaceRelatedVanillaBlock = settings.canPlaceRelatedVanillaBlock; newSettings.projectileMeta = settings.projectileMeta; + newSettings.dyeable = settings.dyeable; return newSettings; } @@ -95,6 +97,10 @@ public class ItemSettings { return tags; } + public boolean dyeable() { + return dyeable; + } + public List repairItems() { return anvilRepairItems; } @@ -144,6 +150,11 @@ public class ItemSettings { return this; } + public ItemSettings dyeable(boolean bool) { + this.dyeable = bool; + return this; + } + @FunctionalInterface public interface Modifier { @@ -217,6 +228,10 @@ public class ItemSettings { Quaternionf rotation = MiscUtils.getAsQuaternionf(ResourceConfigUtils.get(args, "rotation-left", "rotation"), "rotation-left"); return settings -> settings.projectileMeta(new ProjectileMeta(customTridentItemId, displayType, scale, translation, rotation)); })); + registerFactory("dyeable", (value -> { + boolean bool = (boolean) value; + return settings -> settings.dyeable(bool); + })); } private static void registerFactory(String id, ItemSettings.Modifier.Factory factory) {