diff --git a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java index f009e3583..9692a7953 100644 --- a/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java +++ b/bukkit/legacy/src/main/java/net/momirealms/craftengine/bukkit/util/LegacyInventoryUtils.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.bukkit.util; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryEvent; import org.bukkit.event.inventory.PrepareAnvilEvent; import org.bukkit.inventory.AnvilInventory; import org.bukkit.inventory.Inventory; @@ -65,4 +66,8 @@ public class LegacyInventoryUtils { public static void openWorkbench(Player player) { player.openWorkbench(null, true); } + + public static Player getPlayerFromInventoryEvent(InventoryEvent event) { + return (Player) event.getView().getPlayer(); + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java index 384a1efe3..794c0e81a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/font/BukkitFontManager.java @@ -6,9 +6,9 @@ import io.papermc.paper.event.player.AsyncChatCommandDecorateEvent; import io.papermc.paper.event.player.AsyncChatDecorateEvent; import net.kyori.adventure.text.Component; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.paper.PaperReflections; import net.momirealms.craftengine.bukkit.util.ComponentUtils; +import net.momirealms.craftengine.bukkit.util.InventoryUtils; import net.momirealms.craftengine.bukkit.util.ItemStackUtils; import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils; import net.momirealms.craftengine.core.font.*; @@ -132,14 +132,7 @@ public class BukkitFontManager extends AbstractFontManager implements Listener { } ItemStack result = event.getResult(); if (ItemStackUtils.isEmpty(result)) return; - Player player; - try { - player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event)); - } catch (ReflectiveOperationException e) { - this.plugin.logger().warn("Failed to get inventory viewer", e); - return; - } - + Player player = InventoryUtils.getPlayerFromInventoryEvent(event); String renameText; if (VersionHelper.isOrAbove1_21_2()) { AnvilView anvilView = event.getView(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index 74569a54d..c612d9bec 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -14,13 +14,13 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries; -import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MItems; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries; import net.momirealms.craftengine.bukkit.util.ItemStackUtils; import net.momirealms.craftengine.bukkit.util.KeyUtils; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.*; import net.momirealms.craftengine.core.item.modifier.IdModifier; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; import net.momirealms.craftengine.core.pack.AbstractPackManager; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.context.ContextHolder; @@ -54,8 +54,8 @@ public class BukkitItemManager extends AbstractItemManager { private final ArmorEventListener armorEventListener; private final NetworkItemHandler networkItemHandler; private final Object bedrockItemHolder; - private final Item empty; - private final ItemStack emptyStack; + private final Item emptyItem; + private final UniqueIdItem emptyUniqueItem; private Set lastRegisteredPatterns = Set.of(); public BukkitItemManager(BukkitCraftEngine plugin) { @@ -71,8 +71,15 @@ public class BukkitItemManager extends AbstractItemManager { this.bedrockItemHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(Key.of("minecraft:bedrock")))).get();; this.registerCustomTrimMaterial(); this.loadLastRegisteredPatterns(); - this.empty = this.wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.instance$ItemStack$EMPTY)); - this.emptyStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.constructor$ItemStack(MItems.AIR, 1)); + + ItemStack emptyStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.instance$ItemStack$EMPTY); + this.emptyItem = this.wrap(emptyStack); + this.emptyUniqueItem = new UniqueIdItem<>(UniqueKey.AIR, this.emptyItem); + } + + @Override + public UniqueIdItem uniqueEmptyItem() { + return this.emptyUniqueItem; } @Override @@ -104,18 +111,20 @@ public class BukkitItemManager extends AbstractItemManager { @Override public Item s2c(Item item, Player player) { + if (item.isEmpty()) return item; return this.networkItemHandler.s2c(item, player).orElse(item); } @Override public Item c2s(Item item) { + if (item.isEmpty()) return item; return this.networkItemHandler.c2s(item).orElse(item); } public Optional s2c(ItemStack itemStack, Player player) { try { Item wrapped = wrap(itemStack); - if (wrapped == null) return Optional.empty(); + if (wrapped.isEmpty()) return Optional.empty(); return this.networkItemHandler.s2c(wrapped, player).map(Item::getItem); } catch (Throwable e) { Debugger.ITEM.warn(() -> "Failed to handle s2c items.", e); @@ -126,7 +135,7 @@ public class BukkitItemManager extends AbstractItemManager { public Optional c2s(ItemStack itemStack) { try { Item wrapped = wrap(itemStack); - if (wrapped == null) return Optional.empty(); + if (wrapped.isEmpty()) return Optional.empty(); return this.networkItemHandler.c2s(wrapped).map(Item::getItem); } catch (Throwable e) { Debugger.COMMON.warn(() -> "Failed to handle c2s items.", e); @@ -332,7 +341,7 @@ public class BukkitItemManager extends AbstractItemManager { @Override public @NotNull Item wrap(ItemStack itemStack) { - if (itemStack == null) return this.empty; + if (itemStack == null) return this.emptyItem; return this.factory.wrap(itemStack); } @@ -386,4 +395,45 @@ public class BukkitItemManager extends AbstractItemManager { plugin.logger().warn("Failed to init vanilla items", e); } } + + // 1.20-1.21.4 template 不为空 + // 1.21.5+ pattern 不为空 + @Override + public Item applyTrim(Item base, Item addition, Item template, Key pattern) { + Optional optionalMaterial = FastNMS.INSTANCE.method$TrimMaterials$getFromIngredient(addition.getLiteralObject()); + Optional optionalPattern = VersionHelper.isOrAbove1_21_5() ? + FastNMS.INSTANCE.method$Registry$getHolderByResourceLocation(FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_MATERIAL), KeyUtils.toResourceLocation(pattern)) : + FastNMS.INSTANCE.method$TrimPatterns$getFromTemplate(template.getLiteralObject()); + if (optionalMaterial.isPresent() && optionalPattern.isPresent()) { + Object armorTrim = FastNMS.INSTANCE.constructor$ArmorTrim(optionalMaterial.get(), optionalPattern.get()); + Object previousTrim; + if (VersionHelper.isOrAbove1_20_5()) { + previousTrim = base.getExactComponent(ComponentKeys.TRIM); + } else { + try { + previousTrim = VersionHelper.isOrAbove1_20_2() ? + ((Optional) CoreReflections.method$ArmorTrim$getTrim.invoke(null, FastNMS.INSTANCE.registryAccess(), base.getLiteralObject(), true)).orElse(null) : + ((Optional) CoreReflections.method$ArmorTrim$getTrim.invoke(null, FastNMS.INSTANCE.registryAccess(), base.getLiteralObject())).orElse(null); + } catch (ReflectiveOperationException e) { + this.plugin.logger().warn("Failed to get armor trim", e); + return this.emptyItem; + } + } + if (armorTrim.equals(previousTrim)) { + return this.emptyItem; + } + Item newItem = base.copyWithCount(1); + if (VersionHelper.isOrAbove1_20_5()) { + newItem.setExactComponent(ComponentKeys.TRIM, armorTrim); + } else { + try { + CoreReflections.method$ArmorTrim$setTrim.invoke(null, FastNMS.INSTANCE.registryAccess(), base.getLiteralObject(), armorTrim); + } catch (ReflectiveOperationException e) { + this.plugin.logger().warn("Failed to set armor trim", e); + return this.emptyItem; + } + } + } + return this.emptyItem; + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java index 0301ed6b3..fbb73a8cc 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyItemWrapper.java @@ -72,6 +72,7 @@ public class LegacyItemWrapper implements ItemWrapper { getItem().setAmount(amount); } + @SuppressWarnings("DuplicatedCode") public Object getExactTag(Object... path) { Object compoundTag = FastNMS.INSTANCE.method$ItemStack$getTag(this.nmsStack); if (compoundTag == null) return null; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java index 6fc76ac58..6c4d94cf2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/LegacyNetworkItemHandler.java @@ -45,7 +45,7 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler entry : networkData.entrySet()) { @@ -74,7 +74,7 @@ public final class LegacyNetworkItemHandler implements NetworkItemHandler> extend throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); } + @Override + protected void setExactComponent(W item, Object type, Object value) { + throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); + } + @Override protected boolean hasComponent(W item, Object type) { throw new UnsupportedOperationException("This feature is only available on 1.20.5+"); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java index 7d7421f9b..9abbd8a16 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/ComponentItemFactory1_20_5.java @@ -72,8 +72,29 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory trimMap = (Map) trim.get(); - return Optional.of(new Trim(trimMap.get("pattern"), trimMap.get("material"))); + return Optional.of(new Trim(Key.of(trimMap.get("pattern")), Key.of(trimMap.get("material")))); } @SuppressWarnings("unchecked") 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 0740673eb..1d77a5ef4 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 @@ -43,10 +43,15 @@ public class UniversalItemFactory extends BukkitItemFactory { } @Override - protected Tag getNBTTag(LegacyItemWrapper item, Object... path) { + protected Tag getTag(LegacyItemWrapper item, Object... path) { return item.getNBTTag(path); } + @Override + protected Object getExactTag(LegacyItemWrapper item, Object... path) { + return item.getExactTag(path); + } + @Override protected boolean hasTag(LegacyItemWrapper item, Object... path) { return item.hasTag(path); @@ -263,8 +268,8 @@ public class UniversalItemFactory extends BukkitItemFactory { item.remove("Trim"); return; } - item.setTag(trim.material(), "Trim", "material"); - item.setTag(trim.pattern(), "Trim", "pattern"); + item.setTag(trim.material().asString(), "Trim", "material"); + item.setTag(trim.pattern().asString(), "Trim", "pattern"); } @Override @@ -304,7 +309,7 @@ public class UniversalItemFactory extends BukkitItemFactory { String material = item.getJavaTag("Trim", "material"); String pattern = item.getJavaTag("Trim", "pattern"); if (material == null || pattern == null) return Optional.empty(); - return Optional.of(new Trim(material, pattern)); + return Optional.of(new Trim(Key.of(material), Key.of(pattern))); } @Override 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 f5cdddee2..d732280d4 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 @@ -140,6 +140,27 @@ public class BukkitRecipeManager extends AbstractRecipeManager { return null; } }); + MIXED_RECIPE_CONVERTORS.put(RecipeTypes.SMITHING_TRIM, (BukkitRecipeConvertor>) (id, recipe) -> { + try { + Object nmsRecipe = createMinecraftSmithingTrimRecipe(recipe); + if (VersionHelper.isOrAbove1_21_2()) { + nmsRecipe = CoreReflections.constructor$RecipeHolder.newInstance( + CraftBukkitReflections.method$CraftRecipe$toMinecraft.invoke(null, new NamespacedKey(id.namespace(), id.value())), nmsRecipe); + } else if (VersionHelper.isOrAbove1_20_2()) { + nmsRecipe = CoreReflections.constructor$RecipeHolder.newInstance(KeyUtils.toResourceLocation(id), nmsRecipe); + } else { + Object finalNmsRecipe0 = nmsRecipe; + return () -> registerNMSSmithingRecipe(finalNmsRecipe0); + } + Object finalNmsRecipe = nmsRecipe; + return () -> registerNMSSmithingRecipe(finalNmsRecipe); + } catch (InvalidRecipeIngredientException e) { + throw e; + } catch (Exception e) { + CraftEngine.instance().logger().warn("Failed to convert smithing trim recipe", e); + return null; + } + }); // TODO DO NOT USE BUKKIT RECIPE AS BRIDGE IN FUTURE VERSIONS, WE SHOULD DIRECTLY CONSTRUCT THOSE NMS RECIPES MIXED_RECIPE_CONVERTORS.put(RecipeTypes.SHAPED, (BukkitRecipeConvertor>) (id, recipe) -> { ShapedRecipe shapedRecipe = new ShapedRecipe(new NamespacedKey(id.namespace(), id.value()), recipe.result(ItemBuildContext.EMPTY)); @@ -439,6 +460,10 @@ public class BukkitRecipeManager extends AbstractRecipeManager { VanillaSmithingTransformRecipe recipe = this.recipeReader.readSmithingTransform(jsonObject); handleDataPackSmithingTransform(id, recipe, (this.delayedTasksOnMainThread::add)); } + case "minecraft:smithing_trim" -> { + VanillaSmithingTrimRecipe recipe = this.recipeReader.readSmithingTrim(jsonObject); + handleDataPackSmithingTrim(id, recipe, (this.delayedTasksOnMainThread::add)); + } case "minecraft:stonecutting" -> { VanillaStoneCuttingRecipe recipe = this.recipeReader.readStoneCutting(jsonObject); handleDataPackStoneCuttingRecipe(id, recipe); @@ -649,6 +674,35 @@ public class BukkitRecipeManager extends AbstractRecipeManager { this.registerInternalRecipe(id, ceRecipe); } + private void handleDataPackSmithingTrim(Key id, VanillaSmithingTrimRecipe recipe, Consumer callback) { + NamespacedKey key = new NamespacedKey(id.namespace(), id.value()); + + boolean hasCustomItemInTag; + Set additionHolders = new HashSet<>(); + hasCustomItemInTag = readVanillaIngredients(false, recipe.addition(), additionHolders::add); + Set templateHolders = new HashSet<>(); + hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.template(), templateHolders::add); + Set baseHolders = new HashSet<>(); + hasCustomItemInTag = readVanillaIngredients(hasCustomItemInTag, recipe.base(), baseHolders::add); + + CustomSmithingTrimRecipe ceRecipe = new CustomSmithingTrimRecipe<>( + id, + Ingredient.of(baseHolders), + Ingredient.of(templateHolders), + Ingredient.of(additionHolders), + Optional.ofNullable(recipe.pattern()).map(Key::of).orElse(null) + ); + + if (hasCustomItemInTag) { + Runnable converted = findNMSRecipeConvertor(ceRecipe).convert(id, ceRecipe); + callback.accept(() -> { + unregisterNMSRecipe(key); + converted.run(); + }); + } + this.registerInternalRecipe(id, ceRecipe); + } + private boolean readVanillaIngredients(boolean hasCustomItemInTag, List ingredients, Consumer holderConsumer) { for (String item : ingredients) { if (item.charAt(0) == '#') { @@ -903,4 +957,35 @@ public class BukkitRecipeManager extends AbstractRecipeManager { ); } } + + private static Object createMinecraftSmithingTrimRecipe(CustomSmithingTrimRecipe recipe) throws ReflectiveOperationException { + if (VersionHelper.isOrAbove1_21_5()) { + Object registry = FastNMS.INSTANCE.method$RegistryAccess$lookupOrThrow(FastNMS.INSTANCE.registryAccess(), MRegistries.TRIM_PATTERN); + return CoreReflections.constructor$SmithingTrimRecipe.newInstance( + toMinecraftIngredient(recipe.template()), + toMinecraftIngredient(recipe.base()), + toMinecraftIngredient(recipe.addition()), + FastNMS.INSTANCE.method$Registry$getHolderByResourceLocation(registry, KeyUtils.toResourceLocation(recipe.pattern())) + ); + } else if (VersionHelper.isOrAbove1_21_2()) { + return CoreReflections.constructor$SmithingTrimRecipe.newInstance( + toOptionalMinecraftIngredient(recipe.template()), + toOptionalMinecraftIngredient(recipe.base()), + toOptionalMinecraftIngredient(recipe.addition()) + ); + } else if (VersionHelper.isOrAbove1_20_2()) { + return CoreReflections.constructor$SmithingTrimRecipe.newInstance( + toMinecraftIngredient(recipe.template()), + toMinecraftIngredient(recipe.base()), + toMinecraftIngredient(recipe.addition()) + ); + } else { + return CoreReflections.constructor$SmithingTrimRecipe.newInstance( + KeyUtils.toResourceLocation(recipe.id()), + toMinecraftIngredient(recipe.template()), + toMinecraftIngredient(recipe.base()), + toMinecraftIngredient(recipe.addition()) + ); + } + } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java index e5036f7cd..5b5d2fd37 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/recipe/CrafterEventListener.java @@ -5,9 +5,9 @@ import net.momirealms.craftengine.bukkit.util.ItemStackUtils; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.ItemManager; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; import net.momirealms.craftengine.core.item.recipe.Recipe; import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; import net.momirealms.craftengine.core.item.recipe.input.CraftingInput; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.util.Key; @@ -52,33 +52,33 @@ public class CrafterEventListener implements Listener { Inventory inventory = crafter.getInventory(); ItemStack[] ingredients = inventory.getStorageContents(); - List> optimizedIDItems = new ArrayList<>(); + List> uniqueIdItems = new ArrayList<>(); for (ItemStack itemStack : ingredients) { if (ItemStackUtils.isEmpty(itemStack)) { - optimizedIDItems.add(RecipeEventListener.EMPTY); + uniqueIdItems.add(this.itemManager.uniqueEmptyItem()); } else { Item wrappedItem = this.itemManager.wrap(itemStack); - optimizedIDItems.add(new OptimizedIDItem<>(wrappedItem.recipeIngredientId(), itemStack)); + uniqueIdItems.add(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem)); } } CraftingInput input; if (ingredients.length == 9) { - input = CraftingInput.of(3, 3, optimizedIDItems); + input = CraftingInput.of(3, 3, uniqueIdItems); } else if (ingredients.length == 4) { - input = CraftingInput.of(2, 2, optimizedIDItems); + input = CraftingInput.of(2, 2, uniqueIdItems); } else { return; } Recipe ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPELESS, input); if (ceRecipe != null) { - event.setResult(ceRecipe.result(ItemBuildContext.EMPTY)); + event.setResult(ceRecipe.assemble(input, ItemBuildContext.EMPTY)); return; } ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input); if (ceRecipe != null) { - event.setResult(ceRecipe.result(ItemBuildContext.EMPTY)); + event.setResult(ceRecipe.assemble(input, ItemBuildContext.EMPTY)); return; } // clear result if not met 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 a0b791dcb..2f1da0cb7 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 @@ -12,6 +12,7 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflect import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRecipeTypes; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.ComponentUtils; +import net.momirealms.craftengine.bukkit.util.InventoryUtils; import net.momirealms.craftengine.bukkit.util.ItemStackUtils; import net.momirealms.craftengine.bukkit.util.LegacyInventoryUtils; import net.momirealms.craftengine.core.item.*; @@ -49,7 +50,6 @@ import java.util.Optional; @SuppressWarnings("DuplicatedCode") public class RecipeEventListener implements Listener { - public static final OptimizedIDItem EMPTY = new OptimizedIDItem<>(null, null); private final ItemManager itemManager; private final BukkitRecipeManager recipeManager; private final BukkitCraftEngine plugin; @@ -74,7 +74,7 @@ public class RecipeEventListener implements Listener { ItemStack item = event.getCurrentItem(); if (ItemStackUtils.isEmpty(item)) return; if (ItemStackUtils.isEmpty(fuelStack)) { - SingleItemInput input = new SingleItemInput<>(getOptimizedIDItem(item)); + SingleItemInput input = new SingleItemInput<>(getUniqueIdItem(item)); Key recipeType; if (furnaceInventory.getType() == InventoryType.FURNACE) { recipeType = RecipeTypes.SMELTING; @@ -351,7 +351,7 @@ public class RecipeEventListener implements Listener { if (optionalMCRecipe.isEmpty()) { return; } - SingleItemInput input = new SingleItemInput<>(getOptimizedIDItem(itemStack)); + SingleItemInput input = new SingleItemInput<>(getUniqueIdItem(itemStack)); CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) this.recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input); if (ceRecipe == null) { event.setCancelled(true); @@ -376,7 +376,7 @@ public class RecipeEventListener implements Listener { } ItemStack itemStack = event.getSource(); - SingleItemInput input = new SingleItemInput<>(getOptimizedIDItem(itemStack)); + SingleItemInput input = new SingleItemInput<>(getUniqueIdItem(itemStack)); CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) this.recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input); if (ceRecipe == null) { event.setTotalCookTime(Integer.MAX_VALUE); @@ -404,7 +404,7 @@ public class RecipeEventListener implements Listener { } ItemStack itemStack = event.getSource(); - SingleItemInput input = new SingleItemInput<>(getOptimizedIDItem(itemStack)); + SingleItemInput input = new SingleItemInput<>(getUniqueIdItem(itemStack)); CustomCampfireRecipe ceRecipe = (CustomCampfireRecipe) this.recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input); if (ceRecipe == null) { event.setCancelled(true); @@ -620,13 +620,7 @@ public class RecipeEventListener implements Listener { LegacyInventoryUtils.setRepairCostAmount(inventory, actualConsumedAmount); } - Player player; - try { - player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(VersionHelper.isOrAbove1_21() ? event.getView() : LegacyInventoryUtils.getView(event)); - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to get inventory viewer", e); - return; - } + Player player = InventoryUtils.getPlayerFromInventoryEvent(event); if (finalCost >= maxRepairCost && !plugin.adapt(player).canInstabuild()) { hasResult = false; @@ -732,13 +726,7 @@ public class RecipeEventListener implements Listener { return; } - Player player; - try { - player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView()); - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to get inventory viewer", e); - return; - } + Player player = InventoryUtils.getPlayerFromInventoryEvent(event); Optional> customItemOptional = plugin.itemManager().getCustomItem(left.id()); if (customItemOptional.isEmpty()) { @@ -860,34 +848,28 @@ public class RecipeEventListener implements Listener { CraftingInventory inventory = event.getInventory(); ItemStack[] ingredients = inventory.getMatrix(); - List> optimizedIDItems = new ArrayList<>(); + List> uniqueIdItems = new ArrayList<>(); for (ItemStack itemStack : ingredients) { - optimizedIDItems.add(getOptimizedIDItem(itemStack)); + uniqueIdItems.add(getUniqueIdItem(itemStack)); } CraftingInput input; if (ingredients.length == 9) { - input = CraftingInput.of(3, 3, optimizedIDItems); + input = CraftingInput.of(3, 3, uniqueIdItems); } else if (ingredients.length == 4) { - input = CraftingInput.of(2, 2, optimizedIDItems); + input = CraftingInput.of(2, 2, uniqueIdItems); } else { return; } - Player player; - try { - player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView()); - } catch (ReflectiveOperationException e) { - this.plugin.logger().warn("Failed to get inventory viewer", e); - return; - } + Player player = InventoryUtils.getPlayerFromInventoryEvent(event); BukkitServerPlayer serverPlayer = this.plugin.adapt(player); Key lastRecipe = serverPlayer.lastUsedRecipe(); Recipe ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPELESS, input, lastRecipe); if (ceRecipe != null) { - inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY))); + inventory.setResult(ceRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY))); serverPlayer.setLastUsedRecipe(ceRecipe.id()); if (!ceRecipe.id().equals(recipeId)) { correctCraftingRecipeUsed(inventory, ceRecipe); @@ -896,7 +878,7 @@ public class RecipeEventListener implements Listener { } ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input, lastRecipe); if (ceRecipe != null) { - inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY))); + inventory.setResult(ceRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY))); serverPlayer.setLastUsedRecipe(ceRecipe.id()); if (!ceRecipe.id().equals(recipeId)) { correctCraftingRecipeUsed(inventory, ceRecipe); @@ -923,18 +905,48 @@ public class RecipeEventListener implements Listener { @EventHandler(ignoreCancelled = true) public void onSmithingTrim(PrepareSmithingEvent event) { SmithingInventory inventory = event.getInventory(); - if (!(inventory.getRecipe() instanceof SmithingTrimRecipe)) return; + if (!(inventory.getRecipe() instanceof SmithingTrimRecipe recipe)) return; + ItemStack equipment = inventory.getInputEquipment(); - if (ItemStackUtils.isEmpty(equipment)) return; - Item wrappedEquipment = this.itemManager.wrap(equipment); - Optional> optionalCustomItem = wrappedEquipment.getCustomItem(); - if (optionalCustomItem.isEmpty()) return; - CustomItem customItem = optionalCustomItem.get(); - ItemEquipment itemEquipmentSettings = customItem.settings().equipment(); - if (itemEquipmentSettings == null) return; - // 不允许trim类型的盔甲再次被使用trim - if (itemEquipmentSettings.equipment() instanceof TrimBasedEquipment) { + if (!ItemStackUtils.isEmpty(equipment)) { + Item wrappedEquipment = this.itemManager.wrap(equipment); + Optional> optionalCustomItem = wrappedEquipment.getCustomItem(); + if (optionalCustomItem.isPresent()) { + CustomItem customItem = optionalCustomItem.get(); + ItemEquipment itemEquipmentSettings = customItem.settings().equipment(); + if (itemEquipmentSettings != null && itemEquipmentSettings.equipment() instanceof TrimBasedEquipment) { + // 不允许trim类型的盔甲再次被使用trim + event.setResult(null); + return; + } + } + } + + Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value()); + boolean isCustom = this.recipeManager.isCustomRecipe(recipeId); + // Maybe it's recipe from other plugins, then we ignore it + if (!isCustom) { + return; + } + + SmithingInput input = new SmithingInput<>( + getUniqueIdItem(inventory.getInputEquipment()), + getUniqueIdItem(inventory.getInputTemplate()), + getUniqueIdItem(inventory.getInputMineral()) + ); + + Recipe ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SMITHING_TRIM, input); + if (ceRecipe == null) { event.setResult(null); + return; + } + + Player player = InventoryUtils.getPlayerFromInventoryEvent(event); + CustomSmithingTrimRecipe trimRecipe = (CustomSmithingTrimRecipe) ceRecipe; + ItemStack result = trimRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY)); + event.setResult(result); + if (!ceRecipe.id().equals(recipeId)) { + correctSmithingRecipeUsed(inventory, ceRecipe); } } @@ -956,9 +968,9 @@ public class RecipeEventListener implements Listener { ItemStack addition = inventory.getInputMineral(); SmithingInput input = new SmithingInput<>( - getOptimizedIDItem(base), - getOptimizedIDItem(template), - getOptimizedIDItem(addition) + getUniqueIdItem(base), + getUniqueIdItem(template), + getUniqueIdItem(addition) ); Recipe ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SMITHING_TRANSFORM, input); @@ -967,16 +979,10 @@ public class RecipeEventListener implements Listener { return; } - Player player; - try { - player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView()); - } catch (ReflectiveOperationException e) { - this.plugin.logger().warn("Failed to get inventory viewer", e); - return; - } + Player player = InventoryUtils.getPlayerFromInventoryEvent(event); CustomSmithingTransformRecipe transformRecipe = (CustomSmithingTransformRecipe) ceRecipe; - ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base)); + ItemStack processed = transformRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY)); event.setResult(processed); if (!ceRecipe.id().equals(recipeId)) { correctSmithingRecipeUsed(inventory, ceRecipe); @@ -996,12 +1002,12 @@ public class RecipeEventListener implements Listener { } } - private OptimizedIDItem getOptimizedIDItem(@Nullable ItemStack itemStack) { + private UniqueIdItem getUniqueIdItem(@Nullable ItemStack itemStack) { if (ItemStackUtils.isEmpty(itemStack)) { - return EMPTY; + return this.itemManager.uniqueEmptyItem(); } else { Item wrappedItem = this.itemManager.wrap(itemStack); - return new OptimizedIDItem<>(wrappedItem.recipeIngredientId(), itemStack); + return new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java index 811dfe889..7a8016ace 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/RecipeInjector.java @@ -20,8 +20,8 @@ import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries import net.momirealms.craftengine.bukkit.util.KeyUtils; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.recipe.CustomCookingRecipe; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput; import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.ReflectionUtils; @@ -133,7 +133,7 @@ public class RecipeInjector { ); Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(wrappedItem.recipeIngredientId(), itemStack)); + SingleItemInput input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem)); CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); if (ceRecipe == null) { return Optional.empty(); @@ -179,7 +179,7 @@ public class RecipeInjector { } Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(wrappedItem.recipeIngredientId(), itemStack)); + SingleItemInput input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem)); CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); if (ceRecipe == null) { return Optional.empty(); @@ -220,7 +220,7 @@ public class RecipeInjector { ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0])); Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(wrappedItem.recipeIngredientId(), itemStack)); + SingleItemInput input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem)); CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); if (ceRecipe == null) { return Optional.empty(); @@ -265,7 +265,7 @@ public class RecipeInjector { // 获取唯一内存地址id ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0])); Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(wrappedItem.recipeIngredientId(), itemStack)); + SingleItemInput input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem)); CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); // 这个ce配方并不存在,那么应该返回空 if (ceRecipe == null) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java index 3043f71ec..9b876328a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/CoreReflections.java @@ -2290,12 +2290,24 @@ public final class CoreReflections { public static final Constructor constructor$SmithingTransformRecipe = requireNonNull( VersionHelper.isOrAbove1_21_5() - ? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, clazz$Ingredient, Optional.class, clazz$TransmuteResult) - : VersionHelper.isOrAbove1_21_2() - ? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack) - : VersionHelper.isOrAbove1_20_2() - ? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) - : ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) + ? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, clazz$Ingredient, Optional.class, clazz$TransmuteResult) + : VersionHelper.isOrAbove1_21_2() + ? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack) + : VersionHelper.isOrAbove1_20_2() + ? ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) + : ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) + ); + + public static final Class clazz$SmithingTrimRecipe = requireNonNull( + ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("world.item.crafting.SmithingTrimRecipe")) + ); + + public static final Constructor constructor$SmithingTrimRecipe = requireNonNull( + VersionHelper.isOrAbove1_21_5() ? + ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$Holder) : + VersionHelper.isOrAbove1_20_2() ? + ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient) : + ReflectionUtils.getConstructor(clazz$SmithingTrimRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient) ); public static final Method method$RecipeManager$addRecipe = requireNonNull( @@ -3771,4 +3783,35 @@ public final class CoreReflections { "world.item.BlockItem" ) ); + + public static final Class clazz$ArmorTrim = requireNonNull( + ReflectionUtils.getClazz( + VersionHelper.isOrAbove1_21_2() ? + BukkitReflectionUtils.assembleCBClass("world.item.equipment.trim.ArmorTrim") : + BukkitReflectionUtils.assembleMCClass("world.item.armortrim.ArmorTrim") + ) + ); + + public static final Field field$ArmorTrim$CODEC = requireNonNull( + ReflectionUtils.getDeclaredField(clazz$ArmorTrim, Codec.class, 0) + ); + + public static final Codec instance$ArmorTrim$CODEC; + + static { + try { + instance$ArmorTrim$CODEC = (Codec) field$ArmorTrim$CODEC.get(null); + } catch (ReflectiveOperationException e) { + throw new ReflectionInitException("Failed to initialize ArmorTrim CODEC", e); + } + } + + public static final Method method$ArmorTrim$setTrim = ReflectionUtils.getStaticMethod( + clazz$ArmorTrim, boolean.class, clazz$RegistryAccess, clazz$ItemStack, clazz$ArmorTrim + ); + + public static final Method method$ArmorTrim$getTrim = + VersionHelper.isOrAbove1_20_2() ? + ReflectionUtils.getStaticMethod(clazz$ArmorTrim, Optional.class, clazz$RegistryAccess, clazz$ItemStack, boolean.class) : + ReflectionUtils.getStaticMethod(clazz$ArmorTrim, Optional.class, clazz$RegistryAccess, clazz$ItemStack); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java index 8b4fd002f..11f5213b8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java @@ -4,8 +4,8 @@ import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager; import net.momirealms.craftengine.core.block.BlockKeys; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemKeys; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; @@ -78,14 +78,14 @@ public class InteractUtils { }); registerInteraction(BlockKeys.SOUL_CAMPFIRE, (player, item, blockState, result) -> { if (!Config.enableRecipeSystem()) return false; - return BukkitRecipeManager.instance().recipeByInput(RecipeTypes.CAMPFIRE_COOKING, new SingleItemInput<>(new OptimizedIDItem<>( - item.recipeIngredientId(), item.getItem() + return BukkitRecipeManager.instance().recipeByInput(RecipeTypes.CAMPFIRE_COOKING, new SingleItemInput<>(new UniqueIdItem<>( + item.recipeIngredientId(), item ))) != null; }); registerInteraction(BlockKeys.CAMPFIRE, (player, item, blockState, result) -> { if (!Config.enableRecipeSystem()) return false; - return BukkitRecipeManager.instance().recipeByInput(RecipeTypes.CAMPFIRE_COOKING, new SingleItemInput<>(new OptimizedIDItem<>( - item.recipeIngredientId(), item.getItem() + return BukkitRecipeManager.instance().recipeByInput(RecipeTypes.CAMPFIRE_COOKING, new SingleItemInput<>(new UniqueIdItem<>( + item.recipeIngredientId(), item ))) != null; }); registerInteraction(BlockKeys.DECORATED_POT, (player, item, blockState, result) -> true); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InventoryUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InventoryUtils.java index 5e37c14c3..49192e90c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InventoryUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InventoryUtils.java @@ -1,5 +1,8 @@ package net.momirealms.craftengine.bukkit.util; +import net.momirealms.craftengine.core.util.VersionHelper; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; @@ -7,6 +10,14 @@ public class InventoryUtils { private InventoryUtils() {} + public static Player getPlayerFromInventoryEvent(InventoryEvent event) { + if (VersionHelper.isOrAbove1_21()) { + return (Player) event.getView().getPlayer(); + } else { + return LegacyInventoryUtils.getPlayerFromInventoryEvent(event); + } + } + public static int getSuitableHotBarSlot(PlayerInventory inventory) { int selectedSlot = inventory.getHeldItemSlot(); int i; diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index 1b4014f2e..5dd4723e5 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -135,6 +135,11 @@ warning.config.recipe.smithing_transform.post_processor.missing_type: "I warning.config.recipe.smithing_transform.post_processor.invalid_type: "Issue found in file - The smithing transform recipe '' is using an invalid post processor type ''." warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "Issue found in file - The smithing transform recipe '' is missing the required argument 'components' for post-processors 'keep_components'." warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "Issue found in file - The smithing transform recipe '' is missing the required argument 'tags' for post-processors 'keep_tags'." +warning.config.recipe.smithing_transform.missing_base: "Issue found in file - The smithing transform recipe '' is missing the required 'base' argument." +warning.config.recipe.smithing_trim.missing_base: "Issue found in file - The smithing trim recipe '' is missing the required 'base' argument." +warning.config.recipe.smithing_trim.missing_template_type: "Issue found in file - The smithing trim recipe '' is missing the required 'template-type' argument." +warning.config.recipe.smithing_trim.missing_addition: "Issue found in file - The smithing trim recipe '' is missing the required 'addition' argument." +warning.config.recipe.smithing_trim.missing_pattern: "Issue found in file - The smithing trim recipe '' is missing the required 'pattern' argument." warning.config.i18n.unknown_locale: "Issue found in file - Unknown locale ''." warning.config.template.duplicate: "Issue found in file - Duplicated template ''. Please check if there is the same configuration in other files." warning.config.template.invalid: "Issue found in file - The config '' is using an invalid template ''." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 271ed135f..94f47cae9 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -135,6 +135,11 @@ warning.config.recipe.smithing_transform.post_processor.missing_type: " warning.config.recipe.smithing_transform.post_processor.invalid_type: "在文件 发现问题 - 锻造升级配方 '' 使用了无效的后处理器类型 ''" warning.config.recipe.smithing_transform.post_processor.keep_component.missing_components: "在文件 发现问题 - 锻造升级配方 '' 的 'keep_components' 后处理器缺少必需的 'components' 参数" warning.config.recipe.smithing_transform.post_processor.keep_component.missing_tags: "在文件 发现问题 - 锻造升级配方 '' 的 'keep_tags' 后处理器缺少必需的 'tags' 参数" +warning.config.recipe.smithing_transform.missing_base: "在文件 发现问题 - 锻造升级配方 '' 缺少必需的 'base' 参数" +warning.config.recipe.smithing_trim.missing_base: "在文件 发现问题 - 锻造纹饰配方 '' 缺少必需的 'base' 参数" +warning.config.recipe.smithing_trim.missing_template_type: "在文件 发现问题 - 锻造纹饰配方 '' 缺少必需的 'template-type' 参数" +warning.config.recipe.smithing_trim.missing_addition: "在文件 发现问题 - 锻造纹饰配方 '' 缺少必需的 'addition' 参数" +warning.config.recipe.smithing_trim.missing_pattern: "在文件 发现问题 - 锻造纹饰配方 '' 缺少必需的 'pattern' 参数" warning.config.i18n.unknown_locale: "在文件 发现问题 - 未知的语言环境 ''" warning.config.template.duplicate: "在文件 发现问题 - 重复的模板 '' 请检查其他文件中是否存在相同配置" warning.config.template.argument.self_increase_int.invalid_range: "在文件 发现问题 - 模板 '' 在 'self_increase_int' 参数中使用了一个起始值 '' 大于终止值 ''" 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 9da9b4d92..74f5d96a3 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 @@ -331,8 +331,13 @@ public class AbstractItem, I> implements Item { } @Override - public Tag getNBTTag(Object... path) { - return this.factory.getNBTTag(this.item, path); + public Tag getTag(Object... path) { + return this.factory.getTag(this.item, path); + } + + @Override + public Object getExactTag(Object... path) { + return this.factory.getExactTag(this.item, path); } @Override @@ -366,6 +371,11 @@ public class AbstractItem, I> implements Item { return this.factory.getExactComponent(this.item, type); } + @Override + public void setExactComponent(Object type, Object value) { + this.factory.setExactComponent(this.item, type, value); + } + @Override public Object getJavaComponent(Object type) { return this.factory.getJavaComponent(this.item, type); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java index b05558f79..28a8a599e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItemManager.java @@ -600,7 +600,7 @@ public abstract class AbstractItemManager extends AbstractModelGenerator impl Map data = MiscUtils.castToMap(obj, false); String material = data.get("material").toString().toLowerCase(Locale.ENGLISH); String pattern = data.get("pattern").toString().toLowerCase(Locale.ENGLISH); - return new TrimModifier<>(material, pattern); + return new TrimModifier<>(Key.of(material), Key.of(pattern)); }, "trim"); registerDataType((obj) -> { List components = MiscUtils.getAsStringList(obj).stream().map(Key::of).toList(); 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 1b3393aca..86b4c4729 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 @@ -141,7 +141,9 @@ public interface Item { Object getJavaTag(Object... path); - Tag getNBTTag(Object... path); + Tag getTag(Object... path); + + Object getExactTag(Object... path); Item setTag(Object value, Object... path); @@ -153,6 +155,8 @@ public interface Item { void removeComponent(Object type); + void setExactComponent(Object type, Object value); + Object getExactComponent(Object type); Object getJavaComponent(Object type); 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 f8d609f7d..d403ba310 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 @@ -38,7 +38,7 @@ public abstract class ItemFactory, I> { protected abstract Object getJavaTag(W item, Object... path); - protected abstract Tag getNBTTag(W item, Object... path); + protected abstract Tag getTag(W item, Object... path); protected abstract void setTag(W item, Object value, Object... path); @@ -50,6 +50,10 @@ public abstract class ItemFactory, I> { protected abstract Object getExactComponent(W item, Object type); + protected abstract Object getExactTag(W item, Object... path); + + protected abstract void setExactComponent(W item, Object type, Object value); + protected abstract Object getJavaComponent(W item, Object type); protected abstract JsonElement getJsonComponent(W item, Object type); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java index d499e9b92..434ae4d65 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.equipment.Equipment; import net.momirealms.craftengine.core.item.modifier.ItemDataModifier; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; import net.momirealms.craftengine.core.pack.model.LegacyOverridesModel; import net.momirealms.craftengine.core.pack.model.ModernItemModel; import net.momirealms.craftengine.core.pack.model.generation.ModelGenerator; @@ -107,4 +108,8 @@ public interface ItemManager extends Manageable, ModelGenerator { Item s2c(Item item, Player player); Item c2s(Item item); + + UniqueIdItem uniqueEmptyItem(); + + Item applyTrim(Item base, Item addition, Item template, Key pattern); } \ No newline at end of file diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/data/Trim.java b/core/src/main/java/net/momirealms/craftengine/core/item/data/Trim.java index a1e9d2e6f..e0b95d0eb 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/data/Trim.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/data/Trim.java @@ -1,4 +1,6 @@ package net.momirealms.craftengine.core.item.data; -public record Trim(String pattern, String material) { +import net.momirealms.craftengine.core.util.Key; + +public record Trim(Key pattern, Key material) { } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/equipment/TrimBasedEquipment.java b/core/src/main/java/net/momirealms/craftengine/core/item/equipment/TrimBasedEquipment.java index 46655c2ea..6023fd20d 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/equipment/TrimBasedEquipment.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/equipment/TrimBasedEquipment.java @@ -41,7 +41,7 @@ public class TrimBasedEquipment extends AbstractEquipment { @Override public List> modifiers() { return List.of( - new TrimModifier<>(AbstractPackManager.NEW_TRIM_MATERIAL, this.assetId.toString()), + new TrimModifier<>(Key.of(AbstractPackManager.NEW_TRIM_MATERIAL), this.assetId), new HideTooltipModifier<>(List.of(ComponentKeys.TRIM)) ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java index 22093aa73..1bc71cff2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/AttributeModifiersModifier.java @@ -178,7 +178,7 @@ public class AttributeModifiersModifier implements ItemDataModifier { networkData.put(ComponentKeys.ATTRIBUTE_MODIFIERS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("AttributeModifiers"); + Tag previous = item.getTag("AttributeModifiers"); if (previous != null) { networkData.put("AttributeModifiers", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ComponentModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ComponentModifier.java index b23c283f1..3dc223ca3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ComponentModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ComponentModifier.java @@ -59,7 +59,7 @@ public class ComponentModifier implements ItemDataModifier { item.setNBTComponent(entry.left(), entry.right()); } if (this.customData != null) { - CompoundTag tag = (CompoundTag) item.getNBTTag(ComponentKeys.CUSTOM_DATA); + CompoundTag tag = (CompoundTag) item.getTag(ComponentKeys.CUSTOM_DATA); if (tag != null) { for (Map.Entry entry : this.customData.entrySet()) { tag.put(entry.getKey(), entry.getValue()); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java index 2449d816b..f76bb1c78 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomModelDataModifier.java @@ -36,7 +36,7 @@ public class CustomModelDataModifier implements ItemDataModifier { networkData.put(ComponentKeys.CUSTOM_MODEL_DATA.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("CustomModelData"); + Tag previous = item.getTag("CustomModelData"); if (previous != null) { networkData.put("CustomModelData", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java index 818c67a65..ecbbbe33a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/CustomNameModifier.java @@ -46,7 +46,7 @@ public class CustomNameModifier implements ItemDataModifier { networkData.put(ComponentKeys.CUSTOM_NAME.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("display", "Name"); + Tag previous = item.getTag("display", "Name"); if (previous != null) { networkData.put("display.Name", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java index 329490661..a93bbf284 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DyedColorModifier.java @@ -36,7 +36,7 @@ public class DyedColorModifier implements ItemDataModifier { networkData.put(ComponentKeys.DYED_COLOR.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("display", "color"); + Tag previous = item.getTag("display", "color"); if (previous != null) { networkData.put("display.color", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DynamicLoreModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DynamicLoreModifier.java index a365694f7..65392a1b8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DynamicLoreModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/DynamicLoreModifier.java @@ -54,7 +54,7 @@ public class DynamicLoreModifier implements ItemDataModifier { networkData.put(ComponentKeys.LORE.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("display", "Lore"); + Tag previous = item.getTag("display", "Lore"); if (previous != null) { networkData.put("display.Lore", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java index d223c4708..9168de84a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/EnchantmentModifier.java @@ -41,7 +41,7 @@ public class EnchantmentModifier implements ItemDataModifier { networkData.put(ComponentKeys.STORED_ENCHANTMENTS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("StoredEnchantments"); + Tag previous = item.getTag("StoredEnchantments"); if (previous != null) { networkData.put("StoredEnchantments", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { @@ -57,7 +57,7 @@ public class EnchantmentModifier implements ItemDataModifier { networkData.put(ComponentKeys.ENCHANTMENTS.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("Enchantments"); + Tag previous = item.getTag("Enchantments"); if (previous != null) { networkData.put("Enchantments", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java index 847089e5e..20c2bab7c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/HideTooltipModifier.java @@ -94,7 +94,7 @@ public class HideTooltipModifier implements ItemDataModifier { } } } else { - Tag previous = item.getNBTTag("HideFlags"); + Tag previous = item.getTag("HideFlags"); if (previous != null) { networkData.put("HideFlags", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java index 587b1c467..63cfac93f 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/ItemNameModifier.java @@ -37,7 +37,7 @@ public class ItemNameModifier implements ItemDataModifier { networkData.put(ComponentKeys.ITEM_NAME.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("display", "Name"); + Tag previous = item.getTag("display", "Name"); if (previous != null) { networkData.put("display.Name", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java index f6e5e9651..6c5c88a59 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/LoreModifier.java @@ -53,7 +53,7 @@ public class LoreModifier implements ItemDataModifier { networkData.put(ComponentKeys.LORE.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("display", "Lore"); + Tag previous = item.getTag("display", "Lore"); if (previous != null) { networkData.put("display.Lore", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java index 34aaa3ffa..b264c9c33 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TagsModifier.java @@ -41,7 +41,7 @@ public class TagsModifier implements ItemDataModifier { @Override public Item prepareNetworkItem(Item item, ItemBuildContext context, CompoundTag networkData) { for (Map.Entry entry : this.arguments.entrySet()) { - Tag previous = item.getNBTTag(entry.getKey()); + Tag previous = item.getTag(entry.getKey()); if (previous != null) { networkData.put(entry.getKey(), NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java index 27650aea5..3a5a32a56 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/TrimModifier.java @@ -5,15 +5,16 @@ import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemBuildContext; import net.momirealms.craftengine.core.item.NetworkItemHandler; import net.momirealms.craftengine.core.item.data.Trim; +import net.momirealms.craftengine.core.util.Key; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.sparrow.nbt.CompoundTag; import net.momirealms.sparrow.nbt.Tag; public class TrimModifier implements ItemDataModifier { - private final String material; - private final String pattern; + private final Key material; + private final Key pattern; - public TrimModifier(String material, String pattern) { + public TrimModifier(Key material, Key pattern) { this.material = material; this.pattern = pattern; } @@ -39,7 +40,7 @@ public class TrimModifier implements ItemDataModifier { networkData.put(ComponentKeys.TRIM.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("Trim"); + Tag previous = item.getTag("Trim"); if (previous != null) { networkData.put("Trim", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java index 33ec2d9c2..b1be281a0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/modifier/UnbreakableModifier.java @@ -36,7 +36,7 @@ public class UnbreakableModifier implements ItemDataModifier { networkData.put(ComponentKeys.UNBREAKABLE.asString(), NetworkItemHandler.pack(NetworkItemHandler.Operation.REMOVE)); } } else { - Tag previous = item.getNBTTag("Unbreakable"); + Tag previous = item.getTag("Unbreakable"); if (previous != null) { networkData.put("Unbreakable", NetworkItemHandler.pack(NetworkItemHandler.Operation.ADD, previous)); } else { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java index a1e5e3303..69ec59426 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractGroupedRecipe.java @@ -1,10 +1,11 @@ package net.momirealms.craftengine.core.item.recipe; import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.item.recipe.input.RecipeInput; import net.momirealms.craftengine.core.util.Key; import org.jetbrains.annotations.Nullable; -public abstract class AbstractGroupedRecipe implements Recipe { +public abstract class AbstractGroupedRecipe implements FixedResultRecipe { protected final String group; protected final Key id; protected final CustomRecipeResult result; @@ -15,6 +16,11 @@ public abstract class AbstractGroupedRecipe implements Recipe { this.result = result; } + @Override + public T assemble(RecipeInput input, ItemBuildContext context) { + return this.result(context); + } + @Nullable public String group() { return group; diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipeManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipeManager.java index f89adad9a..3f1036f91 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipeManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/AbstractRecipeManager.java @@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.item.recipe.vanilla.VanillaRecipeReader; import net.momirealms.craftengine.core.item.recipe.vanilla.reader.VanillaRecipeReader1_20; import net.momirealms.craftengine.core.item.recipe.vanilla.reader.VanillaRecipeReader1_20_5; import net.momirealms.craftengine.core.item.recipe.vanilla.reader.VanillaRecipeReader1_21_2; +import net.momirealms.craftengine.core.item.recipe.vanilla.reader.VanillaRecipeReader1_21_5; import net.momirealms.craftengine.core.pack.LoadingSequence; import net.momirealms.craftengine.core.pack.Pack; import net.momirealms.craftengine.core.plugin.CraftEngine; @@ -41,7 +42,9 @@ public abstract class AbstractRecipeManager implements RecipeManager { } private VanillaRecipeReader initVanillaRecipeReader() { - if (VersionHelper.isOrAbove1_21_2()) { + if (VersionHelper.isOrAbove1_21_5()) { + return new VanillaRecipeReader1_21_5(); + } else if (VersionHelper.isOrAbove1_21_2()) { return new VanillaRecipeReader1_21_2(); } else if (VersionHelper.isOrAbove1_20_5()) { return new VanillaRecipeReader1_20_5(); @@ -137,7 +140,9 @@ public abstract class AbstractRecipeManager implements RecipeManager { protected void registerInternalRecipe(Key id, Recipe recipe) { this.byType.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe); this.byId.put(id, recipe); - this.byResult.computeIfAbsent(recipe.result().item().id(), k -> new ArrayList<>()).add(recipe); + if (recipe instanceof FixedResultRecipe fixedResult) { + this.byResult.computeIfAbsent(fixedResult.result().item().id(), k -> new ArrayList<>()).add(recipe); + } HashSet usedKeys = new HashSet<>(); for (Ingredient ingredient : recipe.ingredientsInUse()) { for (UniqueKey holder : ingredient.items()) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomShapedRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomShapedRecipe.java index 951ac6d96..2350a975b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomShapedRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomShapedRecipe.java @@ -106,7 +106,7 @@ public class CustomShapedRecipe extends CustomCraftingTableRecipe { } else { optional = this.ingredients.get(j + i * this.width); } - OptimizedIDItem itemStack = input.getItem(j, i); + UniqueIdItem itemStack = input.getItem(j, i); if (!Ingredient.isInstance(optional, itemStack)) { return false; } 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 c588501e4..f06dff32f 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 @@ -15,7 +15,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -public class CustomSmithingTransformRecipe implements Recipe { +public class CustomSmithingTransformRecipe implements FixedResultRecipe { public static final Factory FACTORY = new Factory<>(); private final Key id; private final CustomRecipeResult result; @@ -51,7 +51,7 @@ public class CustomSmithingTransformRecipe implements Recipe { && checkIngredient(this.addition, smithingInput.addition()); } - private boolean checkIngredient(Ingredient ingredient, OptimizedIDItem item) { + private boolean checkIngredient(Ingredient ingredient, UniqueIdItem item) { if (ingredient != null) { if (item == null || item.isEmpty()) { return false; @@ -85,13 +85,16 @@ public class CustomSmithingTransformRecipe implements Recipe { return this.id; } - @Override + @Nullable public T result(ItemBuildContext context) { return this.result.buildItemStack(context); } @SuppressWarnings("unchecked") - public T assemble(ItemBuildContext context, Item base) { + @Override + public T assemble(RecipeInput input, ItemBuildContext context) { + SmithingInput smithingInput = ((SmithingInput) input); + Item base = smithingInput.base().item(); T result = this.result(context); Item wrappedResult = (Item) CraftEngine.instance().itemManager().wrap(result); Item finalResult = wrappedResult; @@ -104,7 +107,6 @@ public class CustomSmithingTransformRecipe implements Recipe { return finalResult.getItem(); } - @Override public CustomRecipeResult result() { return this.result; } @@ -130,6 +132,9 @@ public class CustomSmithingTransformRecipe implements Recipe { @Override public Recipe create(Key id, Map arguments) { List base = MiscUtils.getAsStringList(arguments.get("base")); + if (base.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.recipe.smithing_transform.missing_base"); + } List addition = MiscUtils.getAsStringList(arguments.get("addition")); List template = MiscUtils.getAsStringList(arguments.get("template-type")); boolean mergeComponents = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("merge-components", true), "merge-components"); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java new file mode 100644 index 000000000..d643b0274 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/CustomSmithingTrimRecipe.java @@ -0,0 +1,140 @@ +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; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import net.momirealms.craftengine.core.util.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class CustomSmithingTrimRecipe implements Recipe { + public static final Factory FACTORY = new Factory<>(); + private final Key id; + private final Ingredient base; + private final Ingredient template; + private final Ingredient addition; + @Nullable // 1.21.5 + private final Key pattern; + + public CustomSmithingTrimRecipe(@NotNull Key id, + @NotNull Ingredient base, + @NotNull Ingredient template, + @NotNull Ingredient addition, + @Nullable Key pattern + ) { + this.id = id; + this.base = base; + this.template = template; + this.addition = addition; + this.pattern = pattern; + if (pattern == null && VersionHelper.isOrAbove1_21_5()) { + throw new IllegalStateException("SmithingTrimRecipe cannot have a null pattern on 1.21.5 and above."); + } + } + + @SuppressWarnings("unchecked") + @Override + public T assemble(RecipeInput input, ItemBuildContext context) { + SmithingInput smithingInput = (SmithingInput) input; + Item processed = (Item) CraftEngine.instance().itemManager().applyTrim((Item) smithingInput.base(), (Item) smithingInput.addition(), (Item) smithingInput.template(), this.pattern); + return processed.getItem(); + } + + @SuppressWarnings("unchecked") + @Override + public boolean matches(RecipeInput input) { + SmithingInput smithingInput = (SmithingInput) input; + return checkIngredient(this.base, smithingInput.base()) + && checkIngredient(this.template, smithingInput.template()) + && checkIngredient(this.addition, smithingInput.addition()); + } + + private boolean checkIngredient(Ingredient ingredient, UniqueIdItem item) { + if (ingredient != null) { + if (item == null || item.isEmpty()) { + return false; + } + return ingredient.test(item); + } else { + return item == null || item.isEmpty(); + } + } + + @Override + public List> ingredientsInUse() { + List> ingredients = new ArrayList<>(); + ingredients.add(this.base); + ingredients.add(this.template); + ingredients.add(this.addition); + return ingredients; + } + + @Override + public @NotNull Key type() { + return RecipeTypes.SMITHING_TRIM; + } + + @Override + public Key id() { + return this.id; + } + + @Nullable + public Ingredient base() { + return this.base; + } + + @Nullable + public Ingredient template() { + return template; + } + + @Nullable + public Ingredient addition() { + return addition; + } + + @Nullable + public Key pattern() { + return pattern; + } + + @SuppressWarnings({"DuplicatedCode"}) + public static class Factory implements RecipeFactory { + + @Override + public Recipe create(Key id, Map arguments) { + List base = MiscUtils.getAsStringList(arguments.get("base")); + if (base.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.recipe.smithing_trim.missing_base"); + } + List addition = MiscUtils.getAsStringList(arguments.get("addition")); + if (addition.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.recipe.smithing_trim.missing_addition"); + } + List template = MiscUtils.getAsStringList(arguments.get("template-type")); + if (template.isEmpty()) { + throw new LocalizedResourceConfigException("warning.config.recipe.smithing_trim.missing_template_type"); + } + Key pattern = VersionHelper.isOrAbove1_21_5() ? Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(arguments.get("pattern"), "warning.config.recipe.smithing_trim.missing_pattern")) : null; + return new CustomSmithingTrimRecipe<>(id, toIngredient(base), toIngredient(template), toIngredient(addition), pattern); + } + + private Ingredient toIngredient(List items) { + Set holders = new HashSet<>(); + for (String item : items) { + if (item.charAt(0) == '#') { + holders.addAll(CraftEngine.instance().itemManager().tagToItems(Key.of(item.substring(1)))); + } else { + holders.add(UniqueKey.create(Key.of(item))); + } + } + return Ingredient.of(holders); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/FixedResultRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/FixedResultRecipe.java new file mode 100644 index 000000000..cbc2df693 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/FixedResultRecipe.java @@ -0,0 +1,10 @@ +package net.momirealms.craftengine.core.item.recipe; + +import net.momirealms.craftengine.core.item.ItemBuildContext; + +public interface FixedResultRecipe extends Recipe { + + T result(ItemBuildContext context); + + CustomRecipeResult result(); +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Ingredient.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Ingredient.java index e731407d3..db368e605 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Ingredient.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Ingredient.java @@ -5,14 +5,14 @@ import net.momirealms.craftengine.core.util.UniqueKey; import java.util.*; import java.util.function.Predicate; -public class Ingredient implements Predicate>, StackedContents.IngredientInfo { +public class Ingredient implements Predicate>, StackedContents.IngredientInfo { private final List items; public Ingredient(List items) { this.items = items; } - public static boolean isInstance(Optional> optionalIngredient, OptimizedIDItem stack) { + public static boolean isInstance(Optional> optionalIngredient, UniqueIdItem stack) { return optionalIngredient.map((ingredient) -> ingredient.test(stack)) .orElseGet(stack::isEmpty); } @@ -26,9 +26,9 @@ public class Ingredient implements Predicate>, StackedCont } @Override - public boolean test(OptimizedIDItem optimizedIDItem) { + public boolean test(UniqueIdItem uniqueIdItem) { for (UniqueKey item : this.items()) { - if (optimizedIDItem.is(item)) { + if (uniqueIdItem.is(item)) { return true; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/OptimizedIDItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/OptimizedIDItem.java deleted file mode 100644 index fcc026ef6..000000000 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/OptimizedIDItem.java +++ /dev/null @@ -1,36 +0,0 @@ -package net.momirealms.craftengine.core.item.recipe; - -import net.momirealms.craftengine.core.util.UniqueKey; - -public class OptimizedIDItem { - private final T rawItem; - private final UniqueKey uniqueId; - - public OptimizedIDItem(UniqueKey uniqueId, T rawItem) { - this.uniqueId = uniqueId; - this.rawItem = rawItem; - } - - public UniqueKey id() { - return uniqueId; - } - - public T rawItem() { - return rawItem; - } - - public boolean is(UniqueKey id) { - return uniqueId == id; - } - - public boolean isEmpty() { - return uniqueId == null; - } - - @Override - public String toString() { - return "OptimizedIDItem{" + - "uniqueId=" + uniqueId + - '}'; - } -} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java index befd2940a..a07812c06 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/Recipe.java @@ -11,9 +11,7 @@ public interface Recipe { boolean matches(RecipeInput input); - T result(ItemBuildContext context); - - CustomRecipeResult result(); + T assemble(RecipeInput input, ItemBuildContext context); List> ingredientsInUse(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeFinder.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeFinder.java index e4f360164..d96375d34 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeFinder.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/RecipeFinder.java @@ -7,7 +7,7 @@ import java.util.List; public class RecipeFinder { private final StackedContents stackedContents = new StackedContents<>(); - public void addInput(OptimizedIDItem item) { + public void addInput(UniqueIdItem item) { if (!item.isEmpty()) { this.stackedContents.add(item.id(), 1); } 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 8d7d79e20..e45df9785 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 @@ -30,6 +30,7 @@ public class RecipeTypes { register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY); register(STONECUTTING, CustomStoneCuttingRecipe.FACTORY); register(SMITHING_TRANSFORM, CustomSmithingTransformRecipe.FACTORY); + register(SMITHING_TRIM, CustomSmithingTrimRecipe.FACTORY); } public static void register(Key key, RecipeFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/UniqueIdItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/UniqueIdItem.java new file mode 100644 index 000000000..3166c9d00 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/UniqueIdItem.java @@ -0,0 +1,38 @@ +package net.momirealms.craftengine.core.item.recipe; + +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.UniqueKey; +import org.jetbrains.annotations.NotNull; + +public class UniqueIdItem { + private final Item rawItem; + private final UniqueKey uniqueId; + + public UniqueIdItem(@NotNull UniqueKey uniqueId, @NotNull Item rawItem) { + this.uniqueId = uniqueId; + this.rawItem = rawItem; + } + + @NotNull + public UniqueKey id() { + return uniqueId; + } + + @NotNull + public Item item() { + return this.rawItem; + } + + public boolean is(UniqueKey id) { + return this.uniqueId == id; + } + + public boolean isEmpty() { + return this.uniqueId == UniqueKey.AIR; + } + + @Override + public String toString() { + return "UniqueIdItem[" + "uniqueId=" + uniqueId + ", item=" + rawItem.getItem() + ']'; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/CraftingInput.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/CraftingInput.java index 80a702da1..1db8029b6 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/CraftingInput.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/CraftingInput.java @@ -1,7 +1,7 @@ package net.momirealms.craftengine.core.item.recipe.input; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; import net.momirealms.craftengine.core.item.recipe.RecipeFinder; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; import java.util.ArrayList; import java.util.Collections; @@ -10,16 +10,16 @@ import java.util.List; public class CraftingInput implements RecipeInput { private final int width; private final int height; - private final List> items; + private final List> items; private final int ingredientCount; private final RecipeFinder finder = new RecipeFinder(); - private CraftingInput(int width, int height, List> items) { + private CraftingInput(int width, int height, List> items) { this.height = height; this.width = width; this.items = items; int i = 0; - for (OptimizedIDItem item : items) { + for (UniqueIdItem item : items) { if (!item.isEmpty()) { i++; this.finder.addInput(item); @@ -32,7 +32,7 @@ public class CraftingInput implements RecipeInput { return finder; } - public static CraftingInput of(int width, int height, List> stacks) { + public static CraftingInput of(int width, int height, List> stacks) { if (width <= 0 || height <= 0) { return new CraftingInput<>(0, 0, Collections.emptyList()); } @@ -43,7 +43,7 @@ public class CraftingInput implements RecipeInput { int maxRow = -1; for (int index = 0; index < width * height; index++) { - OptimizedIDItem item = stacks.get(index); + UniqueIdItem item = stacks.get(index); if (!item.isEmpty()) { int row = index / width; int col = index % width; @@ -65,7 +65,7 @@ public class CraftingInput implements RecipeInput { return new CraftingInput<>(width, height, stacks); } - List> trimmed = new ArrayList<>(newWidth * newHeight); + List> trimmed = new ArrayList<>(newWidth * newHeight); for (int row = minRow; row <= maxRow; row++) { for (int col = minCol; col <= maxCol; col++) { int originalIndex = col + row * width; @@ -92,11 +92,11 @@ public class CraftingInput implements RecipeInput { return items.size(); } - public OptimizedIDItem getItem(int x, int y) { + public UniqueIdItem getItem(int x, int y) { return this.items.get(x + y * width); } - public OptimizedIDItem getItem(int index) { + public UniqueIdItem getItem(int index) { return this.items.get(index); } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SingleItemInput.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SingleItemInput.java index c706c38d0..194e992c1 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SingleItemInput.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SingleItemInput.java @@ -1,6 +1,6 @@ package net.momirealms.craftengine.core.item.recipe.input; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; -public record SingleItemInput(OptimizedIDItem input) implements RecipeInput { +public record SingleItemInput(UniqueIdItem input) implements RecipeInput { } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java index 29764fcb5..e186b7e5c 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/input/SmithingInput.java @@ -1,33 +1,34 @@ package net.momirealms.craftengine.core.item.recipe.input; -import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem; +import net.momirealms.craftengine.core.item.recipe.UniqueIdItem; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class SmithingInput implements RecipeInput { - private final OptimizedIDItem base; - private final OptimizedIDItem template; - private final OptimizedIDItem addition; + private final UniqueIdItem base; + private final UniqueIdItem template; + private final UniqueIdItem addition; - public SmithingInput(@Nullable OptimizedIDItem base, - @Nullable OptimizedIDItem template, - @Nullable OptimizedIDItem addition) { + public SmithingInput(@NotNull UniqueIdItem base, + @Nullable UniqueIdItem template, + @Nullable UniqueIdItem addition) { this.base = base; this.template = template; this.addition = addition; } - @Nullable - public OptimizedIDItem base() { + @NotNull + public UniqueIdItem base() { return base; } @Nullable - public OptimizedIDItem template() { + public UniqueIdItem template() { return template; } @Nullable - public OptimizedIDItem addition() { + public UniqueIdItem addition() { return addition; } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java index 813a35e34..99d4e9aed 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaGroupedRecipe.java @@ -13,7 +13,6 @@ public abstract class VanillaGroupedRecipe implements VanillaRecipe { return group; } - @Override public RecipeResult result() { return result; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java index d020f5a69..a58cc6523 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipe.java @@ -5,6 +5,4 @@ import net.momirealms.craftengine.core.util.Key; public interface VanillaRecipe { Key type(); - - RecipeResult result(); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java index f75e42eea..343d9b06a 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaRecipeReader.java @@ -19,4 +19,6 @@ public interface VanillaRecipeReader { VanillaStoneCuttingRecipe readStoneCutting(JsonObject json); VanillaSmithingTransformRecipe readSmithingTransform(JsonObject json); + + VanillaSmithingTrimRecipe readSmithingTrim(JsonObject json); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java index 6ad75f38e..fef4ffbda 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTransformRecipe.java @@ -23,7 +23,6 @@ public class VanillaSmithingTransformRecipe implements VanillaRecipe { return RecipeTypes.SMITHING_TRANSFORM; } - @Override public RecipeResult result() { return result; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTrimRecipe.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTrimRecipe.java new file mode 100644 index 000000000..4b6bee14d --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/VanillaSmithingTrimRecipe.java @@ -0,0 +1,45 @@ +package net.momirealms.craftengine.core.item.recipe.vanilla; + +import net.momirealms.craftengine.core.item.recipe.RecipeTypes; +import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class VanillaSmithingTrimRecipe implements VanillaRecipe { + @Nullable // 1.21.5 + private final String pattern; + + private final List base; + private final List template; + private final List addition; + + public VanillaSmithingTrimRecipe(List base, List template, List addition, @Nullable String pattern) { + this.base = base; + this.template = template; + this.addition = addition; + this.pattern = pattern; + } + + @Override + public Key type() { + return RecipeTypes.SMITHING_TRIM; + } + + public List base() { + return base; + } + + public List template() { + return template; + } + + public List addition() { + return addition; + } + + @Nullable + public String pattern() { + return pattern; + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java index ff836a317..d45c8e5a2 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_20.java @@ -101,6 +101,16 @@ public class VanillaRecipeReader1_20 extends AbstractRecipeReader { ); } + @Override + public VanillaSmithingTrimRecipe readSmithingTrim(JsonObject json) { + return new VanillaSmithingTrimRecipe( + readSingleIngredient(json.get("base")), + readSingleIngredient(json.get("template")), + readSingleIngredient(json.get("addition")), + null + ); + } + protected List readSingleIngredient(JsonElement json) { List ingredients = new ArrayList<>(); if (json.isJsonObject()) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_21_5.java b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_21_5.java new file mode 100644 index 000000000..49634d90e --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/item/recipe/vanilla/reader/VanillaRecipeReader1_21_5.java @@ -0,0 +1,17 @@ +package net.momirealms.craftengine.core.item.recipe.vanilla.reader; + +import com.google.gson.JsonObject; +import net.momirealms.craftengine.core.item.recipe.vanilla.VanillaSmithingTrimRecipe; + +public class VanillaRecipeReader1_21_5 extends VanillaRecipeReader1_21_2 { + + @Override + public VanillaSmithingTrimRecipe readSmithingTrim(JsonObject json) { + return new VanillaSmithingTrimRecipe( + readSingleIngredient(json.get("base")), + readSingleIngredient(json.get("template")), + readSingleIngredient(json.get("addition")), + json.get("pattern").getAsString() + ); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/UniqueKey.java b/core/src/main/java/net/momirealms/craftengine/core/util/UniqueKey.java index 66b1a877e..1a4591535 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/UniqueKey.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/UniqueKey.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.util; +import net.momirealms.craftengine.core.item.ItemKeys; import org.jetbrains.annotations.Nullable; import java.util.HashMap; @@ -7,6 +8,8 @@ import java.util.Map; public final class UniqueKey { private static final Map CACHE = new HashMap<>(4096, 0.5f); + public static final UniqueKey AIR = UniqueKey.create(ItemKeys.AIR); + private final Key key; private UniqueKey(Key key) { @@ -23,6 +26,11 @@ public final class UniqueKey { } public Key key() { - return key; + return this.key; + } + + @Override + public String toString() { + return this.key.toString(); } } diff --git a/gradle.properties b/gradle.properties index 8b428d409..09e48e202 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.59.8 +project_version=0.0.59.9 config_version=41 lang_version=22 project_group=net.momirealms @@ -23,10 +23,10 @@ jar_relocator_version=1.7 adventure_bundle_version=4.23.0 cloud_core_version=2.0.0 cloud_services_version=2.0.0 -cloud_brigadier_version=2.0.0-beta.10 -cloud_bukkit_version=2.0.0-beta.10 -cloud_paper_version=2.0.0-beta.10 -cloud_minecraft_extras_version=2.0.0-beta.10 +cloud_brigadier_version=2.0.0-beta.11 +cloud_bukkit_version=2.0.0-beta.11 +cloud_paper_version=2.0.0-beta.11 +cloud_minecraft_extras_version=2.0.0-beta.11 boosted_yaml_version=1.3.7 bstats_version=3.1.0 caffeine_version=3.2.0 @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.18 -nms_helper_version=1.0.30 +nms_helper_version=1.0.32 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23