From 26edc960a221d4394947bd1d15b1e2402947536c Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sat, 7 Jun 2025 19:49:47 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=86=94=E7=82=89=E6=80=A7?= =?UTF-8?q?=E8=83=BD=EF=BC=8C=E4=BF=9D=E8=AF=81=E7=BA=BF=E7=A8=8B=E5=AE=89?= =?UTF-8?q?=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/BukkitBlockManager.java | 4 +- .../bukkit/block/BukkitCustomBlock.java | 2 +- .../block/behavior/SaplingBlockBehavior.java | 2 +- .../bukkit/item/BukkitItemManager.java | 2 +- .../item/recipe/BukkitRecipeManager.java | 45 +- .../item/recipe/RecipeEventListener.java | 22 +- .../plugin/injector/InjectedCacheCheck.java | 4 + .../plugin/injector/RecipeInjector.java | 395 ++++++++---------- .../reflection/minecraft/MRegistries.java | 62 +-- .../bukkit/sound/BukkitSoundManager.java | 2 +- .../craftengine/bukkit/util/BlockTags.java | 2 +- .../craftengine/bukkit/util/FeatureUtils.java | 2 +- .../craftengine/bukkit/util/ItemTags.java | 2 +- .../bukkit/util/RegistryUtils.java | 2 +- .../item/recipe/AbstractRecipeManager.java | 11 +- gradle.properties | 2 +- 16 files changed, 276 insertions(+), 285 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java index 17e26e141..6e5c77ea3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitBlockManager.java @@ -160,7 +160,7 @@ public class BukkitBlockManager extends AbstractBlockManager { for (Map.Entry> entry : this.clientBoundTags.entrySet()) { list.add(new TagUtils.TagEntry(entry.getKey(), entry.getValue())); } - Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.instance$Registries$BLOCK, list)); + Object packet = TagUtils.createUpdateTagsPacket(Map.of(MRegistries.BLOCK, list)); for (Player player : Bukkit.getOnlinePlayers()) { this.plugin.networkManager().sendPacket(this.plugin.adapt(player), packet); } @@ -762,7 +762,7 @@ public class BukkitBlockManager extends AbstractBlockManager { private Object createBlockProperties(Key realBlockKey) throws Exception { Object blockProperties = CoreReflections.method$BlockBehaviour$Properties$of.invoke(null); Object realBlockResourceLocation = createResourceLocation(realBlockKey); - Object realBlockResourceKey = CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, realBlockResourceLocation); + Object realBlockResourceKey = CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.BLOCK, realBlockResourceLocation); if (CoreReflections.field$BlockBehaviour$Properties$id != null) { CoreReflections.field$BlockBehaviour$Properties$id.set(blockProperties, realBlockResourceKey); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java index dfac86a24..93469a576 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/BukkitCustomBlock.java @@ -151,7 +151,7 @@ public class BukkitCustomBlock extends AbstractCustomBlock { Object holder = BukkitCraftEngine.instance().blockManager().getMinecraftBlockHolder(state.customBlockState().registryId()); Set tags = new HashSet<>(); for (Key tag : settings.tags()) { - tags.add(CoreReflections.method$TagKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, KeyUtils.toResourceLocation(tag))); + tags.add(CoreReflections.method$TagKey$create.invoke(null, MRegistries.BLOCK, KeyUtils.toResourceLocation(tag))); } CoreReflections.field$Holder$Reference$tags.set(holder, tags); // set burning properties diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java index acee6a957..8569e6ca9 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SaplingBlockBehavior.java @@ -77,7 +77,7 @@ public class SaplingBlockBehavior extends BukkitBlockBehavior { } private void generateTree(Object world, Object blockPos, Object blockState, Object randomSource) throws Exception { - Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.instance$Registries$CONFIGURED_FEATURE); + Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.CONFIGURED_FEATURE); if (registry == null) return; @SuppressWarnings("unchecked") Optional holder = (Optional) CoreReflections.method$Registry$getHolder1.invoke(registry, FeatureUtils.createFeatureKey(treeFeature())); 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 632869c87..d909239f3 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 @@ -214,7 +214,7 @@ public class BukkitItemManager extends AbstractItemManager { .orElseGet(() -> ((WritableRegistry) BuiltInRegistries.OPTIMIZED_ITEM_ID) .register(new ResourceKey<>(BuiltInRegistries.OPTIMIZED_ITEM_ID.key().location(), id), id)); Object resourceLocation = KeyUtils.toResourceLocation(id.namespace(), id.value()); - Object mcHolder = ((Optional) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$ITEM, resourceLocation))).get(); + Object mcHolder = ((Optional) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.ITEM, resourceLocation))).get(); Set tags = (Set) CoreReflections.field$Holder$Reference$tags.get(mcHolder); for (Object tag : tags) { Key tagId = Key.of(CoreReflections.field$TagKey$location.get(tag).toString()); 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 05b6873eb..f37e0118c 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 @@ -10,6 +10,7 @@ import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; +import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries; import net.momirealms.craftengine.bukkit.util.KeyUtils; import net.momirealms.craftengine.bukkit.util.MaterialUtils; import net.momirealms.craftengine.bukkit.util.RecipeUtils; @@ -45,9 +46,9 @@ public class BukkitRecipeManager extends AbstractRecipeManager { // 将自定义配方转为“广义”配方,接受更加宽容的输入 // 部分过程借助bukkit完成,部分直接通过nms方法注册 private static final Map>> MIXED_RECIPE_CONVERTORS = new HashMap<>(); - private static Object nmsRecipeManager; private static final List injectedIngredients = new ArrayList<>(); - private static final IdentityHashMap, Object> recipeToMcRecipeHolder = new IdentityHashMap<>(); + private static final IdentityHashMap, Object> CE_RECIPE_2_NMS_HOLDER = new IdentityHashMap<>(); + private static Object nmsRecipeManager; private static void registerNMSSmithingRecipe(Object recipe) { try { @@ -265,7 +266,8 @@ public class BukkitRecipeManager extends AbstractRecipeManager { } public Object nmsRecipeHolderByRecipe(Recipe recipe) { - return recipeToMcRecipeHolder.get(recipe); + if (super.isReloading) return null; + return CE_RECIPE_2_NMS_HOLDER.get(recipe); } public static Object nmsRecipeManager() { @@ -287,6 +289,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { @Override public void load() { if (!Config.enableRecipeSystem()) return; + super.isReloading = true; if (VersionHelper.isOrAbove1_21_2()) { try { this.stolenFeatureFlagSet = CoreReflections.field$RecipeManager$featureflagset.get(nmsRecipeManager); @@ -308,7 +311,6 @@ public class BukkitRecipeManager extends AbstractRecipeManager { } catch (ReflectiveOperationException e) { this.plugin.logger().warn("Failed to unregister recipes", e); } - recipeToMcRecipeHolder.clear(); } @Override @@ -320,6 +322,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { @Override public void disable() { unload(); + CE_RECIPE_2_NMS_HOLDER.clear(); HandlerList.unregisterAll(this.recipeEventListener); if (this.crafterEventListener != null) { HandlerList.unregisterAll(this.crafterEventListener); @@ -473,6 +476,15 @@ public class BukkitRecipeManager extends AbstractRecipeManager { // clear cache injectedIngredients.clear(); + + CE_RECIPE_2_NMS_HOLDER.clear(); + // create mappings + for (Map.Entry> entry : this.byId.entrySet()) { + Optional nmsRecipe = getOptionalNMSRecipe(entry.getKey()); + nmsRecipe.ifPresent(o -> CE_RECIPE_2_NMS_HOLDER.put(entry.getValue(), o)); + } + + super.isReloading = false; } catch (Exception e) { this.plugin.logger().warn("Failed to run delayed recipe tasks", e); } @@ -691,7 +703,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { return optionalItem.map(itemStackCustomItem -> MaterialUtils.getMaterial(itemStackCustomItem.material())).orElse(null); } - private static List getIngredientLooks(List> holders) throws ReflectiveOperationException { + private static List getIngredientLooks(List> holders) { List itemStacks = new ArrayList<>(); for (Holder holder : holders) { ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1); @@ -710,8 +722,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { .map(Optional::get) .toList(); - Object shapedRecipe = getNMSRecipe(id); - recipeToMcRecipeHolder.put(recipe, shapedRecipe); + Object shapedRecipe = getOptionalNMSRecipe(id).get(); if (VersionHelper.isOrAbove1_20_2()) { shapedRecipe = CoreReflections.field$RecipeHolder$recipe.get(shapedRecipe); } @@ -731,8 +742,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { try { List> actualIngredients = recipe.ingredientsInUse(); - Object shapelessRecipe = getNMSRecipe(id); - recipeToMcRecipeHolder.put(recipe, shapelessRecipe); + Object shapelessRecipe = getOptionalNMSRecipe(id).get(); if (VersionHelper.isOrAbove1_20_2()) { shapelessRecipe = CoreReflections.field$RecipeHolder$recipe.get(shapelessRecipe); } @@ -751,8 +761,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { private static void injectCookingRecipe(Key id, CustomCookingRecipe recipe) { try { Ingredient actualIngredient = recipe.ingredient(); - Object smeltingRecipe = getNMSRecipe(id); - recipeToMcRecipeHolder.put(recipe, smeltingRecipe); + Object smeltingRecipe = getOptionalNMSRecipe(id).get(); if (VersionHelper.isOrAbove1_20_2()) { smeltingRecipe = CoreReflections.field$RecipeHolder$recipe.get(smeltingRecipe); } @@ -771,23 +780,17 @@ public class BukkitRecipeManager extends AbstractRecipeManager { // 获取nms配方,请注意1.20.1获取配方本身,而1.20.2+获取的是配方的holder // recipe on 1.20.1 and holder on 1.20.2+ - private static Object getNMSRecipe(Key id) throws ReflectiveOperationException { + private static Optional getOptionalNMSRecipe(Key id) throws ReflectiveOperationException { if (VersionHelper.isOrAbove1_21_2()) { - Object resourceKey = CraftBukkitReflections.method$CraftRecipe$toMinecraft.invoke(null, new NamespacedKey(id.namespace(), id.value())); + Object resourceKey = FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.RECIPE, KeyUtils.toResourceLocation(id)); @SuppressWarnings("unchecked") Optional optional = (Optional) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceKey); - if (optional.isEmpty()) { - throw new IllegalArgumentException("Recipe " + id + " not found"); - } - return optional.get(); + return optional; } else { Object resourceLocation = KeyUtils.toResourceLocation(id); @SuppressWarnings("unchecked") Optional optional = (Optional) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceLocation); - if (optional.isEmpty()) { - throw new IllegalArgumentException("Recipe " + id + " not found"); - } - return optional.get(); + return optional; } } 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 3e059ee13..91a6938b7 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 @@ -843,7 +843,7 @@ public class RecipeEventListener implements Listener { try { player = (Player) CraftBukkitReflections.method$InventoryView$getPlayer.invoke(event.getView()); } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to get inventory viewer", e); + this.plugin.logger().warn("Failed to get inventory viewer", e); return; } @@ -854,14 +854,18 @@ public class RecipeEventListener implements Listener { if (ceRecipe != null) { inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY))); serverPlayer.setLastUsedRecipe(ceRecipe.id()); - correctCraftingRecipeUsed(inventory, ceRecipe); + if (!ceRecipe.id().equals(recipeId)) { + correctCraftingRecipeUsed(inventory, ceRecipe); + } return; } ceRecipe = this.recipeManager.recipeByInput(RecipeTypes.SHAPED, input, lastRecipe); if (ceRecipe != null) { inventory.setResult(ceRecipe.result(new ItemBuildContext(serverPlayer, ContextHolder.EMPTY))); serverPlayer.setLastUsedRecipe(ceRecipe.id()); - correctCraftingRecipeUsed(inventory, ceRecipe); + if (!ceRecipe.id().equals(recipeId)) { + correctCraftingRecipeUsed(inventory, ceRecipe); + } return; } // clear result if not met @@ -869,9 +873,8 @@ public class RecipeEventListener implements Listener { } private void correctCraftingRecipeUsed(CraftingInventory inventory, Recipe recipe) { - Object holderOrRecipe = recipeManager.nmsRecipeHolderByRecipe(recipe); + Object holderOrRecipe = this.recipeManager.nmsRecipeHolderByRecipe(recipe); if (holderOrRecipe == null) { - // it's a vanilla recipe but not injected return; } try { @@ -922,20 +925,21 @@ public class RecipeEventListener implements Listener { CustomSmithingTransformRecipe transformRecipe = (CustomSmithingTransformRecipe) ceRecipe; ItemStack processed = transformRecipe.assemble(new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY), this.itemManager.wrap(base)); event.setResult(processed); - correctSmithingRecipeUsed(inventory, ceRecipe); + if (!ceRecipe.id().equals(recipeId)) { + correctSmithingRecipeUsed(inventory, ceRecipe); + } } private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe recipe) { - Object holderOrRecipe = recipeManager.nmsRecipeHolderByRecipe(recipe); + Object holderOrRecipe = this.recipeManager.nmsRecipeHolderByRecipe(recipe); if (holderOrRecipe == null) { - // it's a vanilla recipe but not injected return; } try { Object resultInventory = CraftBukkitReflections.field$CraftResultInventory$resultInventory.get(inventory); CoreReflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe); } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to correct used recipe", e); + this.plugin.logger().warn("Failed to correct used recipe", e); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/InjectedCacheCheck.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/InjectedCacheCheck.java index 728547596..f8fc33654 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/InjectedCacheCheck.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/InjectedCacheCheck.java @@ -8,6 +8,10 @@ public interface InjectedCacheCheck { void recipeType(Object recipeType); + Key customRecipeType(); + + void customRecipeType(Key customRecipeType); + Object lastRecipe(); void lastRecipe(Object lastRecipe); 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 820b9f556..a928ad74c 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 @@ -16,6 +16,8 @@ import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRecipeTypes; +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; @@ -28,7 +30,6 @@ import net.momirealms.craftengine.core.util.ReflectionUtils; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.inventory.ItemStack; -import java.util.List; import java.util.Optional; public class RecipeInjector { @@ -41,17 +42,23 @@ public class RecipeInjector { .name("net.momirealms.craftengine.bukkit.entity.InjectedCacheChecker") .implement(CoreReflections.clazz$RecipeManager$CachedCheck) .implement(InjectedCacheCheck.class) + .defineField("recipeType", Object.class, Visibility.PUBLIC) .method(ElementMatchers.named("recipeType")) .intercept(FieldAccessor.ofField("recipeType")) + + .defineField("customRecipeType", Key.class, Visibility.PUBLIC) + .method(ElementMatchers.named("customRecipeType")) + .intercept(FieldAccessor.ofField("customRecipeType")) + .defineField("lastRecipe", Object.class, Visibility.PUBLIC) .method(ElementMatchers.named("lastRecipe")) .intercept(FieldAccessor.ofField("lastRecipe")) - .method(ElementMatchers.named("setLastRecipe")) - .intercept(FieldAccessor.ofField("lastRecipe")) + .defineField("lastCustomRecipe", Key.class, Visibility.PUBLIC) .method(ElementMatchers.named("lastCustomRecipe")) .intercept(FieldAccessor.ofField("lastCustomRecipe")) + .method(ElementMatchers.named("getRecipeFor").or(ElementMatchers.named("a"))) .intercept(MethodDelegation.to( VersionHelper.isOrAbove1_21_2() ? @@ -73,269 +80,227 @@ public class RecipeInjector { if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected Object recipeType = FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$recipeType(entity); InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker); - injectedChecker.recipeType(recipeType); + if (recipeType == MRecipeTypes.SMELTING) { + injectedChecker.customRecipeType(RecipeTypes.SMELTING); + injectedChecker.recipeType(MRecipeTypes.SMELTING); + } else if (recipeType == MRecipeTypes.BLASTING) { + injectedChecker.customRecipeType(RecipeTypes.BLASTING); + injectedChecker.recipeType(MRecipeTypes.BLASTING); + } else if (recipeType == MRecipeTypes.SMOKING) { + injectedChecker.customRecipeType(RecipeTypes.SMOKING); + injectedChecker.recipeType(MRecipeTypes.SMOKING); + } else { + throw new IllegalStateException("RecipeType " + recipeType + " not supported"); + } CoreReflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker); } else if (!VersionHelper.isOrAbove1_21_2() && CoreReflections.clazz$CampfireBlockEntity.isInstance(entity)) { Object quickCheck = CoreReflections.field$CampfireBlockEntity$quickCheck.get(entity); if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker); + injectedChecker.customRecipeType(RecipeTypes.CAMPFIRE_COOKING); injectedChecker.recipeType(MRecipeTypes.CAMPFIRE_COOKING); CoreReflections.field$CampfireBlockEntity$quickCheck.set(entity, injectedChecker); } } + @SuppressWarnings("DuplicatedCode") public static class GetRecipeForMethodInterceptor1_20 { public static final GetRecipeForMethodInterceptor1_20 INSTANCE = new GetRecipeForMethodInterceptor1_20(); @SuppressWarnings("unchecked") @RuntimeType - public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception { - Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager(); + public Object intercept(@This Object thisObj, @AllArguments Object[] args) { InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj; - Object type = injectedCacheCheck.recipeType(); - Object lastRecipe = injectedCacheCheck.lastRecipe(); - Optional> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe); - if (optionalRecipe.isPresent()) { - Pair pair = optionalRecipe.get(); - Object resourceLocation = pair.getFirst(); - Key recipeId = Key.of(resourceLocation.toString()); - BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); - - ItemStack itemStack; - List items; - if (type == MRecipeTypes.CAMPFIRE_COOKING) { - items = (List) CoreReflections.field$SimpleContainer$items.get(args[0]); - } else { - items = (List) CoreReflections.field$AbstractFurnaceBlockEntity$items.get(args[0]); - } - itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(items.get(0)); - - // it's a recipe from other plugins - boolean isCustom = recipeManager.isCustomRecipe(recipeId); - if (!isCustom) { - injectedCacheCheck.lastRecipe(resourceLocation); - return Optional.of(pair.getSecond()); - } - - Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); - if (idHolder.isEmpty()) { - return Optional.empty(); - } - - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); - CustomCookingRecipe ceRecipe; - Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe(); - if (type == MRecipeTypes.SMELTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.BLASTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.SMOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.CAMPFIRE_COOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe); - } else { - return Optional.empty(); - } - if (ceRecipe == null) { - return Optional.empty(); - } - - // Cache recipes, it might be incorrect on reloading - injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); - // It doesn't matter at all - injectedCacheCheck.lastRecipe(resourceLocation); - return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(pair.getSecond())); - } else { + Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe(); + Optional> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation); + if (optionalRecipe.isEmpty()) { return Optional.empty(); } + + Pair resourceLocationAndRecipe = optionalRecipe.get(); + Object rawRecipeResourceLocation = resourceLocationAndRecipe.getFirst(); + Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString()); + BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); + + boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey); + if (!isCustom) { + injectedCacheCheck.lastRecipe(rawRecipeResourceLocation); + return Optional.of(resourceLocationAndRecipe.getSecond()); + } + + ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror( + injectedCacheCheck.recipeType() == MRecipeTypes.CAMPFIRE_COOKING ? + FastNMS.INSTANCE.field$SimpleContainer$items(args[0]).getFirst() : + FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$getItem(args[0], 0) + ); + + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + return Optional.empty(); + } + + SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); + if (ceRecipe == null) { + return Optional.empty(); + } + + injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); + if (!ceRecipe.id().equals(rawRecipeKey)) { + injectedCacheCheck.lastRecipe(KeyUtils.toResourceLocation(ceRecipe.id())); + } + return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(resourceLocationAndRecipe.getSecond()); } } + @SuppressWarnings("DuplicatedCode") public static class GetRecipeForMethodInterceptor1_20_5 { public static final GetRecipeForMethodInterceptor1_20_5 INSTANCE = new GetRecipeForMethodInterceptor1_20_5(); @SuppressWarnings("unchecked") @RuntimeType - public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception { - Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager(); + public Object intercept(@This Object thisObj, @AllArguments Object[] args) { InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj; - Object type = injectedCacheCheck.recipeType(); - Object lastRecipe = injectedCacheCheck.lastRecipe(); - Optional optionalRecipe = (Optional) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe); - if (optionalRecipe.isPresent()) { - Object holder = optionalRecipe.get(); - Object id = FastNMS.INSTANCE.field$RecipeHolder$id(holder); - Key recipeId = Key.of(id.toString()); - BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); - - ItemStack itemStack; - List items; - if (type == MRecipeTypes.CAMPFIRE_COOKING) { - items = (List) CoreReflections.field$SimpleContainer$items.get(args[0]); - } else { - items = (List) CoreReflections.field$AbstractFurnaceBlockEntity$items.get(args[0]); - } - itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(items.get(0)); - - // it's a recipe from other plugins - boolean isCustom = recipeManager.isCustomRecipe(recipeId); - if (!isCustom) { - injectedCacheCheck.lastRecipe(id); - return optionalRecipe; - } - - Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); - if (idHolder.isEmpty()) { - return Optional.empty(); - } - - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); - CustomCookingRecipe ceRecipe; - Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe(); - if (type == MRecipeTypes.SMELTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.BLASTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.SMOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.CAMPFIRE_COOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe); - } else { - return Optional.empty(); - } - if (ceRecipe == null) { - return Optional.empty(); - } - - // Cache recipes, it might be incorrect on reloading - injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); - // It doesn't matter at all - injectedCacheCheck.lastRecipe(id); - return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(holder)); - } else { + Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe(); + Optional optionalRecipe = (Optional) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation); + if (optionalRecipe.isEmpty()) { return Optional.empty(); } + + Object rawRecipeHolder = optionalRecipe.get(); + Object rawRecipeResourceLocation = FastNMS.INSTANCE.field$RecipeHolder$id(rawRecipeHolder); + Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString()); + + BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); + ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror( + injectedCacheCheck.recipeType() == MRecipeTypes.CAMPFIRE_COOKING ? + FastNMS.INSTANCE.field$SimpleContainer$items(args[0]).getFirst() : + FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$getItem(args[0], 0) + ); + + boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey); + if (!isCustom) { + injectedCacheCheck.lastRecipe(rawRecipeResourceLocation); + return optionalRecipe; + } + + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + return Optional.empty(); + } + + SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); + if (ceRecipe == null) { + return Optional.empty(); + } + + injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); + if (!ceRecipe.id().equals(rawRecipeKey)) { + injectedCacheCheck.lastRecipe(KeyUtils.toResourceLocation(ceRecipe.id())); + } + return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)); } } + @SuppressWarnings("DuplicatedCode") public static class GetRecipeForMethodInterceptor1_21 { public static final GetRecipeForMethodInterceptor1_21 INSTANCE = new GetRecipeForMethodInterceptor1_21(); @SuppressWarnings("unchecked") @RuntimeType - public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception { - Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager(); + public Object intercept(@This Object thisObj, @AllArguments Object[] args) { InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj; - Object type = injectedCacheCheck.recipeType(); - Object lastRecipe = injectedCacheCheck.lastRecipe(); - Optional optionalRecipe = (Optional) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe); - if (optionalRecipe.isPresent()) { - Object holder = optionalRecipe.get(); - Object id = FastNMS.INSTANCE.field$RecipeHolder$id(holder); - Key recipeId = Key.of(id.toString()); - BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); - ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.field$SingleRecipeInput$item.get(args[0])); - - // it's a recipe from other plugins - boolean isCustom = recipeManager.isCustomRecipe(recipeId); - if (!isCustom) { - injectedCacheCheck.lastRecipe(id); - return optionalRecipe; - } - - Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); - if (idHolder.isEmpty()) { - return Optional.empty(); - } - - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); - CustomCookingRecipe ceRecipe; - Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe(); - if (type == MRecipeTypes.SMELTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.BLASTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.SMOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.CAMPFIRE_COOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.CAMPFIRE_COOKING, input, lastCustomRecipe); - } else { - return Optional.empty(); - } - if (ceRecipe == null) { - return Optional.empty(); - } - - // Cache recipes, it might be incorrect on reloading - injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); - // It doesn't matter at all - injectedCacheCheck.lastRecipe(id); - return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(holder)); - } else { + Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe(); + Optional optionalRecipe = (Optional) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation); + if (optionalRecipe.isEmpty()) { return Optional.empty(); } + + Object rawRecipeHolder = optionalRecipe.get(); + Object rawRecipeResourceLocation = FastNMS.INSTANCE.field$RecipeHolder$id(rawRecipeHolder); + Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString()); + + BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); + boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey); + if (!isCustom) { + injectedCacheCheck.lastRecipe(rawRecipeResourceLocation); + return optionalRecipe; + } + + ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0])); + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + return Optional.empty(); + } + + SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); + if (ceRecipe == null) { + return Optional.empty(); + } + + injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); + if (!ceRecipe.id().equals(rawRecipeKey)) { + injectedCacheCheck.lastRecipe(KeyUtils.toResourceLocation(ceRecipe.id())); + } + return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)); } } + @SuppressWarnings("DuplicatedCode") public static class GetRecipeForMethodInterceptor1_21_2 { public static final GetRecipeForMethodInterceptor1_21_2 INSTANCE = new GetRecipeForMethodInterceptor1_21_2(); @SuppressWarnings("unchecked") @RuntimeType - public Object intercept(@This Object thisObj, @AllArguments Object[] args) throws Exception { - Object mcRecipeManager = BukkitRecipeManager.nmsRecipeManager(); + public Object intercept(@This Object thisObj, @AllArguments Object[] args) { InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj; - Object type = injectedCacheCheck.recipeType(); - Object lastRecipe = injectedCacheCheck.lastRecipe(); - Optional optionalRecipe = (Optional) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe); - if (optionalRecipe.isPresent()) { - Object holder = optionalRecipe.get(); - Object id = FastNMS.INSTANCE.field$RecipeHolder$id(holder); - Object resourceLocation = FastNMS.INSTANCE.field$ResourceKey$location(id); - Key recipeId = Key.of(resourceLocation.toString()); - BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); - ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.field$SingleRecipeInput$item.get(args[0])); - - // it's a recipe from other plugins - boolean isCustom = recipeManager.isCustomRecipe(recipeId); - if (!isCustom) { - injectedCacheCheck.lastRecipe(id); - return optionalRecipe; - } - - Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); - Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); - if (idHolder.isEmpty()) { - return Optional.empty(); - } - - SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); - CustomCookingRecipe ceRecipe; - Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe(); - if (type == MRecipeTypes.SMELTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.BLASTING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe); - } else if (type == MRecipeTypes.SMOKING) { - ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe); - } else { - return Optional.empty(); - } - if (ceRecipe == null) { - return Optional.empty(); - } - - // Cache recipes, it might be incorrect on reloading - injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); - // It doesn't matter at all - injectedCacheCheck.lastRecipe(id); - return Optional.of(Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)).orElse(holder)); - } else { + Object lastRecipeResourceKey = injectedCacheCheck.lastRecipe(); + Optional optionalRecipe = (Optional) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceKey); + if (optionalRecipe.isEmpty()) { return Optional.empty(); } + + // 获取配方的基础信息 + Object recipeHolder = optionalRecipe.get(); + Object rawRecipeResourceKey = FastNMS.INSTANCE.field$RecipeHolder$id(recipeHolder); + Object rawRecipeResourceLocation = FastNMS.INSTANCE.field$ResourceKey$location(rawRecipeResourceKey); + Key rawRecipeKey = Key.of(rawRecipeResourceLocation.toString()); + + BukkitRecipeManager recipeManager = BukkitRecipeManager.instance(); + // 来自其他插件注册的自定义配方 + boolean isCustom = recipeManager.isCustomRecipe(rawRecipeKey); + if (!isCustom) { + injectedCacheCheck.lastRecipe(rawRecipeResourceKey); + return optionalRecipe; + } + + // 获取唯一内存地址id + ItemStack itemStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(FastNMS.INSTANCE.field$SingleRecipeInput$item(args[0])); + Item wrappedItem = BukkitItemManager.instance().wrap(itemStack); + Optional> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id()); + if (idHolder.isEmpty()) { + return Optional.empty(); + } + + SingleItemInput input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack)); + CustomCookingRecipe ceRecipe = (CustomCookingRecipe) recipeManager.recipeByInput(injectedCacheCheck.customRecipeType(), input, injectedCacheCheck.lastCustomRecipe()); + // 这个ce配方并不存在,那么应该返回空 + if (ceRecipe == null) { + return Optional.empty(); + } + + // 记录上一次使用的配方(ce) + injectedCacheCheck.lastCustomRecipe(ceRecipe.id()); + // 更新上一次使用的配方(nms) + if (!ceRecipe.id().equals(rawRecipeKey)) { + injectedCacheCheck.lastRecipe(FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.RECIPE, KeyUtils.toResourceLocation(ceRecipe.id()))); + } + return Optional.ofNullable(recipeManager.nmsRecipeHolderByRecipe(ceRecipe)); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MRegistries.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MRegistries.java index 04a754e1b..244d26904 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MRegistries.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/minecraft/MRegistries.java @@ -10,21 +10,23 @@ import java.lang.reflect.Type; import static java.util.Objects.requireNonNull; public final class MRegistries { - public static final Object instance$Registries$BLOCK; - public static final Object instance$Registries$ITEM; - public static final Object instance$Registries$ATTRIBUTE; - public static final Object instance$Registries$BIOME; - public static final Object instance$Registries$MOB_EFFECT; - public static final Object instance$Registries$SOUND_EVENT; - public static final Object instance$Registries$PARTICLE_TYPE; - public static final Object instance$Registries$ENTITY_TYPE; - public static final Object instance$Registries$FLUID; - public static final Object instance$Registries$RECIPE_TYPE; - public static final Object instance$Registries$DIMENSION_TYPE; - public static final Object instance$Registries$CONFIGURED_FEATURE; - public static final Object instance$Registries$PLACED_FEATURE; + public static final Object BLOCK; + public static final Object ITEM; + public static final Object ATTRIBUTE; + public static final Object BIOME; + public static final Object MOB_EFFECT; + public static final Object SOUND_EVENT; + public static final Object PARTICLE_TYPE; + public static final Object ENTITY_TYPE; + public static final Object FLUID; + public static final Object RECIPE_TYPE; + public static final Object DIMENSION_TYPE; + public static final Object CONFIGURED_FEATURE; + public static final Object PLACED_FEATURE; @Nullable // 1.21+ - public static final Object instance$Registries$JUKEBOX_SONG; + public static final Object JUKEBOX_SONG; + @Nullable // 1.21+ + public static final Object RECIPE; static { Field[] fields = CoreReflections.clazz$Registries.getDeclaredFields(); @@ -43,6 +45,7 @@ public final class MRegistries { Object registries$ConfiguredFeature = null; Object registries$PlacedFeature = null; Object registries$JukeboxSong = null; + Object registries$Recipe = null; for (Field field : fields) { Type fieldType = field.getGenericType(); if (fieldType instanceof ParameterizedType paramType) { @@ -60,6 +63,8 @@ public final class MRegistries { registries$RecipeType = field.get(null); } else if (rawType == CoreReflections.clazz$ConfiguredFeature) { registries$ConfiguredFeature = field.get(null); + } else if (rawType == CoreReflections.clazz$Recipe) { + registries$Recipe = field.get(null); } } else { if (type == CoreReflections.clazz$Block) { @@ -88,20 +93,21 @@ public final class MRegistries { } } } - instance$Registries$BLOCK = requireNonNull(registries$Block); - instance$Registries$ITEM = requireNonNull(registries$Item); - instance$Registries$ATTRIBUTE = requireNonNull(registries$Attribute); - instance$Registries$BIOME = requireNonNull(registries$Biome); - instance$Registries$MOB_EFFECT = requireNonNull(registries$MobEffect); - instance$Registries$SOUND_EVENT = requireNonNull(registries$SoundEvent); - instance$Registries$DIMENSION_TYPE = requireNonNull(registries$DimensionType); - instance$Registries$PARTICLE_TYPE = requireNonNull(registries$ParticleType); - instance$Registries$ENTITY_TYPE = requireNonNull(registries$EntityType); - instance$Registries$FLUID = requireNonNull(registries$Fluid); - instance$Registries$RECIPE_TYPE = requireNonNull(registries$RecipeType); - instance$Registries$CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature); - instance$Registries$PLACED_FEATURE = requireNonNull(registries$PlacedFeature); - instance$Registries$JUKEBOX_SONG = registries$JukeboxSong; + BLOCK = requireNonNull(registries$Block); + ITEM = requireNonNull(registries$Item); + ATTRIBUTE = requireNonNull(registries$Attribute); + BIOME = requireNonNull(registries$Biome); + MOB_EFFECT = requireNonNull(registries$MobEffect); + SOUND_EVENT = requireNonNull(registries$SoundEvent); + DIMENSION_TYPE = requireNonNull(registries$DimensionType); + PARTICLE_TYPE = requireNonNull(registries$ParticleType); + ENTITY_TYPE = requireNonNull(registries$EntityType); + FLUID = requireNonNull(registries$Fluid); + RECIPE_TYPE = requireNonNull(registries$RecipeType); + CONFIGURED_FEATURE = requireNonNull(registries$ConfiguredFeature); + PLACED_FEATURE = requireNonNull(registries$PlacedFeature); + JUKEBOX_SONG = registries$JukeboxSong; + RECIPE = registries$Recipe; } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/sound/BukkitSoundManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/sound/BukkitSoundManager.java index 50dfb6b68..4500128e3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/sound/BukkitSoundManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/sound/BukkitSoundManager.java @@ -26,7 +26,7 @@ public class BukkitSoundManager extends AbstractSoundManager { protected void registerSongs(Map songs) { if (songs.isEmpty()) return; try { - Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.instance$Registries$JUKEBOX_SONG);; + Object registry = CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.JUKEBOX_SONG);; unfreezeRegistry(registry); for (Map.Entry entry : songs.entrySet()) { Key id = entry.getKey(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockTags.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockTags.java index 75728c940..a83a91c27 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockTags.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockTags.java @@ -16,7 +16,7 @@ public class BlockTags { Object value = CACHE.get(key); if (value == null) { try { - value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.instance$Registries$BLOCK, KeyUtils.toResourceLocation(key)); + value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.BLOCK, KeyUtils.toResourceLocation(key)); CACHE.put(key, value); return value; } catch (Exception e) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/FeatureUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/FeatureUtils.java index 800c203aa..e985bf7d6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/FeatureUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/FeatureUtils.java @@ -10,7 +10,7 @@ public class FeatureUtils { public static Object createFeatureKey(Key id) { try { - return CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$CONFIGURED_FEATURE, KeyUtils.toResourceLocation(id)); + return CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.CONFIGURED_FEATURE, KeyUtils.toResourceLocation(id)); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java index fc87dbc53..2e972673e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java @@ -19,7 +19,7 @@ public class ItemTags { Object value = CACHE.get(key); if (value == null) { try { - value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.instance$Registries$ITEM, KeyUtils.toResourceLocation(key)); + value = CoreReflections.method$TagKey$create.invoke(null, MRegistries.ITEM, KeyUtils.toResourceLocation(key)); CACHE.put(key, value); return value; } catch (Exception e) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RegistryUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RegistryUtils.java index d5754abde..f6e8bf219 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RegistryUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/RegistryUtils.java @@ -19,7 +19,7 @@ public class RegistryUtils { public static int currentBiomeRegistrySize() { try { - Object idMap = CoreReflections.method$Registry$asHolderIdMap.invoke(CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.instance$Registries$BIOME)); + Object idMap = CoreReflections.method$Registry$asHolderIdMap.invoke(CoreReflections.method$RegistryAccess$registryOrThrow.invoke(FastNMS.INSTANCE.registryAccess(), MRegistries.BIOME)); return (int) CoreReflections.method$IdMap$size.invoke(idMap); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); 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 f84e496ec..5b4a9d4ed 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 @@ -28,6 +28,7 @@ public abstract class AbstractRecipeManager implements RecipeManager { protected final Set dataPackRecipes = new HashSet<>(); protected final Set customRecipes = new HashSet<>(); private final RecipeParser recipeParser; + protected boolean isReloading; public AbstractRecipeManager() { this.recipeReader = initVanillaRecipeReader(); @@ -72,37 +73,44 @@ public abstract class AbstractRecipeManager implements RecipeManager { @Override public boolean isDataPackRecipe(Key key) { + if (this.isReloading) return false; return this.dataPackRecipes.contains(key); } @Override public boolean isCustomRecipe(Key key) { + if (this.isReloading) return false; return this.byId.containsKey(key); } @Override public Optional> recipeById(Key key) { + if (this.isReloading) return Optional.empty(); return Optional.ofNullable(this.byId.get(key)); } @Override public List> recipesByType(Key type) { + if (this.isReloading) return List.of(); return this.byType.getOrDefault(type, List.of()); } @Override public List> recipeByResult(Key result) { + if (this.isReloading) return List.of(); return this.byResult.getOrDefault(result, List.of()); } @Override public List> recipeByIngredient(Key ingredient) { + if (this.isReloading) return List.of(); return this.byIngredient.getOrDefault(ingredient, List.of()); } @Nullable @Override public Recipe recipeByInput(Key type, RecipeInput input) { + if (this.isReloading) return null; List> recipes = this.byType.get(type); if (recipes == null) return null; for (Recipe recipe : recipes) { @@ -116,8 +124,9 @@ public abstract class AbstractRecipeManager implements RecipeManager { @Nullable @Override public Recipe recipeByInput(Key type, RecipeInput input, Key lastRecipe) { + if (this.isReloading) return null; if (lastRecipe != null) { - Recipe last = byId.get(lastRecipe); + Recipe last = this.byId.get(lastRecipe); if (last != null && last.matches(input)) { return last; } diff --git a/gradle.properties b/gradle.properties index 33a71d065..e1b0975d8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -51,7 +51,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.4 anti_grief_version=0.17 -nms_helper_version=0.66.12 +nms_helper_version=0.66.15 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.31.23