From 917e1b51410dda5937982d495a745465003f9a8b Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Wed, 19 Mar 2025 05:26:17 +0800 Subject: [PATCH] added some recipe methods --- .../furniture/DismountListener1_20.java | 1 - .../bukkit/item/RTagItemWrapper.java | 7 ++++ .../item/factory/ComponentItemFactory.java | 18 ++++++++++ .../item/factory/UniversalItemFactory.java | 10 ++++++ .../item/recipe/BukkitRecipeManager.java | 6 ++-- .../craftengine/bukkit/util/Reflections.java | 26 ++++++++++++++ .../craftengine/core/item/AbstractItem.java | 6 ++++ .../craftengine/core/item/Item.java | 2 ++ .../craftengine/core/item/ItemFactory.java | 2 ++ .../craftengine/core/item/ItemWrapper.java | 4 +++ .../recipe/CustomSmithingTransformRecipe.java | 34 +++++++++++++++++-- 11 files changed, 110 insertions(+), 6 deletions(-) diff --git a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java index d4a230393..98fd4deea 100644 --- a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java +++ b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/DismountListener1_20.java @@ -4,7 +4,6 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.inventory.RecipeChoice; import java.util.function.BiConsumer; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java index 46d87ddd0..b8785432b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/RTagItemWrapper.java @@ -4,6 +4,8 @@ import com.saicone.rtag.RtagItem; import net.momirealms.craftengine.core.item.ItemWrapper; import org.bukkit.inventory.ItemStack; +import java.util.Map; + @SuppressWarnings("UnstableApiUsage") public class RTagItemWrapper implements ItemWrapper { private final RtagItem rtagItem; @@ -110,4 +112,9 @@ public class RTagItemWrapper implements ItemWrapper { public ItemWrapper copyWithCount(int count) { return new RTagItemWrapper(new RtagItem(this.rtagItem.loadCopy()), count); } + + @Override + public Map getData() { + return this.rtagItem.get(); + } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java index 95d371115..76254dea4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory.java @@ -1,7 +1,11 @@ package net.momirealms.craftengine.bukkit.item.factory; +import com.saicone.rtag.RtagItem; import com.saicone.rtag.data.ComponentType; +import com.saicone.rtag.item.ItemObject; +import net.momirealms.craftengine.bukkit.item.RTagItemWrapper; import net.momirealms.craftengine.bukkit.util.EnchantmentUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.item.ComponentKeys; import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.ItemWrapper; @@ -287,4 +291,18 @@ public class ComponentItemFactory extends BukkitItemFactory { if (!item.hasComponent(ComponentKeys.REPAIR_COST)) return Optional.empty(); return Optional.ofNullable((Integer) ComponentType.encodeJava(ComponentKeys.REPAIR_COST, item.getComponent(ComponentKeys.REPAIR_COST)).orElse(null)); } + + @Override + protected ItemWrapper merge(ItemWrapper item1, ItemWrapper item2) { + Object itemStack1 = item1.getLiteralObject(); + Object itemStack2 = item2.getLiteralObject(); + try { + Object itemStack3 = Reflections.method$ItemStack$transmuteCopy.invoke(itemStack1, Reflections.method$ItemStack$getItem.invoke(itemStack2), 1); + Reflections.method$ItemStack$applyComponents.invoke(itemStack3, Reflections.method$ItemStack$getComponentsPatch.invoke(itemStack2)); + return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack3)), item2.count()); + } catch (Exception e) { + this.plugin.logger().warn("Failed to merge item", e); + } + return null; + } } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java index 9be055d2f..b3179717e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/UniversalItemFactory.java @@ -1,8 +1,11 @@ package net.momirealms.craftengine.bukkit.item.factory; +import com.saicone.rtag.RtagItem; +import com.saicone.rtag.item.ItemObject; import com.saicone.rtag.tag.TagBase; import com.saicone.rtag.tag.TagCompound; import com.saicone.rtag.tag.TagList; +import net.momirealms.craftengine.bukkit.item.RTagItemWrapper; import net.momirealms.craftengine.core.item.Enchantment; import net.momirealms.craftengine.core.item.ItemWrapper; import net.momirealms.craftengine.core.plugin.CraftEngine; @@ -229,4 +232,11 @@ public class UniversalItemFactory extends BukkitItemFactory { if (!item.hasTag("RepairCost")) return Optional.empty(); return Optional.of(item.get("RepairCost")); } + + @Override + protected ItemWrapper merge(ItemWrapper item1, ItemWrapper item2) { + Object itemStack = ItemObject.copy(item2.getLiteralObject()); + ItemObject.setCustomDataTag(itemStack, ItemObject.getCustomDataTag(item1.getLiteralObject())); + return new RTagItemWrapper(new RtagItem(ItemObject.asCraftMirror(itemStack)), item2.count()); + } } \ No newline at end of file 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 3d9283b9b..370169d20 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 @@ -764,14 +764,14 @@ public class BukkitRecipeManager implements RecipeManager { baseHolders.isEmpty() ? null : Ingredient.of(baseHolders), templateHolders.isEmpty() ? null : Ingredient.of(templateHolders), additionHolders.isEmpty() ? null : Ingredient.of(additionHolders), - new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()) + new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count()), + List.of(CustomSmithingTransformRecipe.ItemDataProcessor.MERGE_ALL) ); SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(key, result, new RecipeChoice.MaterialChoice(new ArrayList<>(templateMaterials)), new RecipeChoice.MaterialChoice(new ArrayList<>(baseMaterials)), - new RecipeChoice.MaterialChoice(new ArrayList<>(additionMaterials)), - true + new RecipeChoice.MaterialChoice(new ArrayList<>(additionMaterials)) ); if (hasCustomItemInTag) { 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 cd20007d2..c7850595e 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 @@ -4977,4 +4977,30 @@ public class Reflections { clazz$CraftRecipe, clazz$Ingredient, RecipeChoice.class, boolean.class ) ); + + // 1.20.5+ + public static final Method method$ItemStack$transmuteCopy = ReflectionUtils.getMethod( + clazz$ItemStack, clazz$ItemStack, clazz$ItemLike, int.class + ); + + // 1.20.5+ + public static final Class clazz$DataComponentPatch = ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("core.component.DataComponentPatch") + ); + + // 1.20.5+ + public static final Method method$ItemStack$getComponentsPatch = Optional.ofNullable(clazz$DataComponentPatch) + .map(it -> ReflectionUtils.getMethod(clazz$ItemStack, it)) + .orElse(null); + + // 1.20.5+ + public static final Method method$ItemStack$applyComponents = Optional.ofNullable(clazz$DataComponentPatch) + .map(it -> ReflectionUtils.getMethod(clazz$ItemStack, void.class, it)) + .orElse(null); + + public static final Method method$ItemStack$getItem = requireNonNull( + ReflectionUtils.getMethod( + clazz$ItemStack, clazz$Item + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java index eda369c0c..c31af1519 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java @@ -276,4 +276,10 @@ public class AbstractItem, I> implements Item { public Object getLiteralObject() { return this.item.getLiteralObject(); } + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override + public Item merge(Item another) { + return new AbstractItem<>(this.factory, this.factory.merge(this.item, ((AbstractItem) another).item)); + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java index 8d734326d..7de763c22 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java @@ -116,4 +116,6 @@ public interface Item { boolean is(Key itemTag); Object getLiteralObject(); + + Item merge(Item another); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java index d35dc1042..c5595bef9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java @@ -108,4 +108,6 @@ public abstract class ItemFactory

, I> protected abstract void repairCost(ItemWrapper item, Integer data); protected abstract Optional repairCost(ItemWrapper item); + + protected abstract ItemWrapper merge(ItemWrapper item1, ItemWrapper item2); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java index 49af43621..241ac787e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemWrapper.java @@ -1,5 +1,7 @@ package net.momirealms.craftengine.core.item; +import java.util.Map; + public interface ItemWrapper { I getItem(); @@ -37,4 +39,6 @@ public interface ItemWrapper { void count(int amount); ItemWrapper copyWithCount(int count); + + Map getData(); } 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 e77e1f81e..03b619f5d 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 @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.item.recipe; +import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.recipe.input.RecipeInput; import net.momirealms.craftengine.core.item.recipe.input.SmithingInput; @@ -12,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.BiFunction; public class CustomSmithingTransformRecipe implements Recipe { public static final Factory FACTORY = new Factory<>(); @@ -20,18 +22,21 @@ public class CustomSmithingTransformRecipe implements Recipe { private final Ingredient base; private final Ingredient template; private final Ingredient addition; + private final List processors; public CustomSmithingTransformRecipe(Key id, @Nullable Ingredient addition, @Nullable Ingredient base, @Nullable Ingredient template, - CustomRecipeResult result + CustomRecipeResult result, + List processors ) { this.id = id; this.result = result; this.base = base; this.template = template; this.addition = addition; + this.processors = processors; } @SuppressWarnings("unchecked") @@ -82,6 +87,17 @@ public class CustomSmithingTransformRecipe implements Recipe { return result.buildItemStack(context); } + @SuppressWarnings("unchecked") + public T assemble(ItemBuildContext context, Item base) { + T result = this.result(context); + Item wrappedResult = (Item) CraftEngine.instance().itemManager().wrap(result); + Item finalResult = wrappedResult; + for (ItemDataProcessor processor : this.processors) { + finalResult = (Item) processor.apply(base, wrappedResult); + } + return finalResult.getItem(); + } + @Override public CustomRecipeResult result() { return this.result; @@ -112,7 +128,8 @@ public class CustomSmithingTransformRecipe implements Recipe { List template = MiscUtils.getAsStringList(arguments.get("template")); return new CustomSmithingTransformRecipe<>( id, - toIngredient(addition), toIngredient(base), toIngredient(template), parseResult(arguments) + toIngredient(addition), toIngredient(base), toIngredient(template), parseResult(arguments), + List.of(new ItemDataProcessor[]{}) ); } @@ -128,4 +145,17 @@ public class CustomSmithingTransformRecipe implements Recipe { return holders.isEmpty() ? null : Ingredient.of(holders); } } + + @FunctionalInterface + public interface ItemDataProcessor extends BiFunction, Item, Item> { + MergeAllDataProcessor MERGE_ALL = new MergeAllDataProcessor(); + } + + public static class MergeAllDataProcessor implements ItemDataProcessor { + + @Override + public Item apply(Item item1, Item item2) { + return item1.merge(item2); + } + } }