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 373081c54..0fcba6c05 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 @@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.item.recipe; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import io.papermc.paper.potion.PotionMix; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; @@ -144,11 +145,11 @@ public class BukkitRecipeManager extends AbstractRecipeManager { .map(Optional::get) .toList(); if (VersionHelper.isOrAbove1_21_2()) { - CoreReflections.field$ShapedRecipe$placementInfo.set(shapedRecipe, null); + CoreReflections.methodHandle$ShapedRecipe$placementInfoSetter.invokeExact(shapedRecipe, (Object) null); } List ingredients = getIngredientsFromShapedRecipe(shapedRecipe); modifyIngredients(ingredients, actualIngredients); - } catch (ReflectiveOperationException e) { + } catch (Throwable e) { CraftEngine.instance().logger().warn("Failed to inject shaped recipe", e); } } @@ -158,16 +159,16 @@ public class BukkitRecipeManager extends AbstractRecipeManager { List ingredients = new ArrayList<>(); try { if (VersionHelper.isOrAbove1_20_3()) { - Object pattern = CoreReflections.field$1_20_3$ShapedRecipe$pattern.get(recipe); + Object pattern = CoreReflections.methodHandle$1_20_3$ShapedRecipe$patternGetter.invokeExact(recipe); if (VersionHelper.isOrAbove1_21_2()) { - List> optionals = (List>) CoreReflections.field$ShapedRecipePattern$ingredients1_21_2.get(pattern); + List> optionals = (List>) CoreReflections.methodHandle$ShapedRecipePattern$ingredients1_21_2Getter.invokeExact(pattern); for (Optional optional : optionals) { optional.ifPresent(ingredients::add); } } else { - List objectList = (List) CoreReflections.field$ShapedRecipePattern$ingredients1_20_3.get(pattern); + List objectList = (List) CoreReflections.methodHandle$ShapedRecipePattern$ingredients1_20_3Getter.invokeExact(pattern); for (Object object : objectList) { - Object[] values = (Object[]) CoreReflections.field$Ingredient$values.get(object); + Object[] values = (Object[]) CoreReflections.methodHandle$Ingredient$valuesGetter.invokeExact(object); // is empty or not if (values.length != 0) { ingredients.add(object); @@ -175,15 +176,15 @@ public class BukkitRecipeManager extends AbstractRecipeManager { } } } else { - List objectList = (List) CoreReflections.field$1_20_1$ShapedRecipe$recipeItems.get(recipe); + List objectList = (List) CoreReflections.methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter.invokeExact(recipe); for (Object object : objectList) { - Object[] values = (Object[]) CoreReflections.field$Ingredient$values.get(object); + Object[] values = (Object[]) CoreReflections.methodHandle$Ingredient$valuesGetter.invokeExact(object); if (values.length != 0) { ingredients.add(object); } } } - } catch (ReflectiveOperationException e) { + } catch (Throwable e) { CraftEngine.instance().logger().warn("Failed to get ingredients from shaped recipe", e); } return ingredients; @@ -193,12 +194,12 @@ public class BukkitRecipeManager extends AbstractRecipeManager { try { List> actualIngredients = recipe.ingredientsInUse(); if (VersionHelper.isOrAbove1_21_2()) { - CoreReflections.field$ShapelessRecipe$placementInfo.set(shapelessRecipe, null); + CoreReflections.methodHandle$ShapelessRecipe$placementInfoSetter.invokeExact(shapelessRecipe, (Object) null); } @SuppressWarnings("unchecked") - List ingredients = (List) CoreReflections.field$ShapelessRecipe$ingredients.get(shapelessRecipe); + List ingredients = (List) CoreReflections.methodHandle$ShapelessRecipe$ingredientsGetter.invokeExact(shapelessRecipe); modifyIngredients(ingredients, actualIngredients); - } catch (ReflectiveOperationException e) { + } catch (Throwable e) { CraftEngine.instance().logger().warn("Failed to inject shapeless recipe", e); } } @@ -208,12 +209,12 @@ public class BukkitRecipeManager extends AbstractRecipeManager { Ingredient actualIngredient = recipe.ingredient(); Object ingredient; if (VersionHelper.isOrAbove1_21_2()) { - ingredient = CoreReflections.field$SingleItemRecipe$input.get(cookingRecipe); + ingredient = CoreReflections.methodHandle$SingleItemRecipe$inputGetter.invokeExact(cookingRecipe); } else { - ingredient = CoreReflections.field$AbstractCookingRecipe$input.get(cookingRecipe); + ingredient = CoreReflections.methodHandle$AbstractCookingRecipe$inputGetter.invokeExact(cookingRecipe); } modifyIngredients(List.of(ingredient), List.of(actualIngredient)); - } catch (ReflectiveOperationException e) { + } catch (Throwable e) { CraftEngine.instance().logger().warn("Failed to inject cooking recipe", e); } } @@ -235,7 +236,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { return itemStacks; } - private static void modifyIngredients(List fakeIngredients, List> actualIngredients) throws ReflectiveOperationException { + private static void modifyIngredients(List fakeIngredients, List> actualIngredients) throws Throwable { if (fakeIngredients.size() != actualIngredients.size()) { throw new IllegalArgumentException("Ingredient count mismatch"); } @@ -244,15 +245,15 @@ public class BukkitRecipeManager extends AbstractRecipeManager { Ingredient actualIngredient = actualIngredients.get(i); List items = getIngredientLooks(actualIngredient.items()); if (VersionHelper.isOrAbove1_21_4()) { - CoreReflections.field$Ingredient$itemStacks1_21_4.set(ingredient, new HashSet<>(items)); + CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (Set) new ObjectOpenHashSet<>(items)); } else if (VersionHelper.isOrAbove1_21_2()) { - CoreReflections.field$Ingredient$itemStacks1_21_2.set(ingredient, items); + CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (List) items); } else { Object itemStackArray = Array.newInstance(CoreReflections.clazz$ItemStack, items.size()); for (int j = 0; j < items.size(); j++) { Array.set(itemStackArray, j, items.get(j)); } - CoreReflections.field$Ingredient$itemStacks1_20_1.set(ingredient, itemStackArray); + CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (Object) itemStackArray); } MODIFIED_INGREDIENTS.add(ingredient); } @@ -308,9 +309,9 @@ public class BukkitRecipeManager extends AbstractRecipeManager { if (!Config.enableRecipeSystem()) return; if (VersionHelper.isOrAbove1_21_2()) { try { - this.stolenFeatureFlagSet = CoreReflections.field$RecipeManager$featureflagset.get(minecraftRecipeManager()); - CoreReflections.field$RecipeManager$featureflagset.set(minecraftRecipeManager(), null); - } catch (ReflectiveOperationException e) { + this.stolenFeatureFlagSet = CoreReflections.methodHandle$RecipeManager$featureflagsetGetter.invokeExact(minecraftRecipeManager()); + CoreReflections.methodHandle$RecipeManager$featureflagsetSetter.invokeExact(minecraftRecipeManager(), (Object) null); + } catch (Throwable e) { this.plugin.logger().warn("Failed to steal feature flag set", e); } } @@ -398,7 +399,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { this.replacedDatapackRecipes.clear(); try { this.lastDatapackRecipes = scanResources(); - } catch (ReflectiveOperationException e) { + } catch (Throwable e) { this.plugin.logger().warn("Failed to load datapack recipes", e); } } @@ -409,19 +410,19 @@ public class BukkitRecipeManager extends AbstractRecipeManager { } @SuppressWarnings("unchecked") - private Map> scanResources() throws ReflectiveOperationException { - Object fileToIdConverter = CoreReflections.method$FileToIdConverter$json.invoke(null, VersionHelper.isOrAbove1_21() ? "recipe" : "recipes"); + private Map> scanResources() throws Throwable { + Object fileToIdConverter = CoreReflections.methodHandle$FileToIdConverter$json.invokeExact((String) (VersionHelper.isOrAbove1_21() ? "recipe" : "recipes")); Object minecraftServer = FastNMS.INSTANCE.method$MinecraftServer$getServer(); - Object packRepository = CoreReflections.method$MinecraftServer$getPackRepository.invoke(minecraftServer); - List selected = (List) CoreReflections.field$PackRepository$selected.get(packRepository); + Object packRepository = CoreReflections.methodHandle$MinecraftServer$getPackRepository.invokeExact(minecraftServer); + List selected = (List) CoreReflections.methodHandle$PackRepository$selectedGetter.invokeExact(packRepository); List packResources = new ArrayList<>(); for (Object pack : selected) { - packResources.add(CoreReflections.method$Pack$open.invoke(pack)); + packResources.add(CoreReflections.methodHandle$Pack$open.invokeExact(pack)); } Map> recipes = new HashMap<>(); boolean hasDisabledAny = !Config.disabledVanillaRecipes().isEmpty(); - try (AutoCloseable resourceManager = (AutoCloseable) CoreReflections.constructor$MultiPackResourceManager.newInstance(CoreReflections.instance$PackType$SERVER_DATA, packResources)) { - Map scannedResources = (Map) CoreReflections.method$FileToIdConverter$listMatchingResources.invoke(fileToIdConverter, resourceManager); + try (AutoCloseable resourceManager = (AutoCloseable) CoreReflections.methodHandle$MultiPackResourceManagerConstructor.invokeExact(CoreReflections.instance$PackType$SERVER_DATA, packResources)) { + Map scannedResources = (Map) CoreReflections.methodHandle$FileToIdConverter$listMatchingResources.invokeExact(fileToIdConverter, resourceManager); for (Map.Entry entry : scannedResources.entrySet()) { Key id = extractKeyFromResourceLocation(entry.getKey().toString()); if (Config.disableAllVanillaRecipes()) { @@ -432,7 +433,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { this.recipesToUnregister.add(new Pair<>(id, false)); continue; } - Reader reader = (Reader) CoreReflections.method$Resource$openAsReader.invoke(entry.getValue()); + Reader reader = (Reader) CoreReflections.methodHandle$Resource$openAsReader.invokeExact(entry.getValue()); JsonObject jsonObject = JsonParser.parseReader(reader).getAsJsonObject(); Key serializerType = Key.of(jsonObject.get("type").getAsString()); RecipeSerializer> serializer = (RecipeSerializer>) BuiltInRegistries.RECIPE_SERIALIZER.getValue(serializerType); @@ -446,7 +447,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager { this.plugin.logger().warn("Failed to load data pack recipe " + id + ". Json: " + jsonObject, e); } } - } catch (Exception e) { + } catch (Throwable e) { this.plugin.logger().warn("Unknown error occurred when loading data pack recipes", e); } return recipes; @@ -480,32 +481,32 @@ public class BukkitRecipeManager extends AbstractRecipeManager { try { // give flags back on 1.21.2+ if (VersionHelper.isOrAbove1_21_2() && this.stolenFeatureFlagSet != null) { - CoreReflections.field$RecipeManager$featureflagset.set(minecraftRecipeManager(), this.stolenFeatureFlagSet); + CoreReflections.methodHandle$RecipeManager$featureflagsetSetter.invokeExact(minecraftRecipeManager(), (Object) this.stolenFeatureFlagSet); this.stolenFeatureFlagSet = null; } // refresh recipes if (VersionHelper.isOrAbove1_21_2()) { - CoreReflections.method$RecipeManager$finalizeRecipeLoading.invoke(minecraftRecipeManager()); + CoreReflections.methodHandle$RecipeManager$finalizeRecipeLoading.invokeExact(minecraftRecipeManager()); } // send to players - CoreReflections.method$DedicatedPlayerList$reloadRecipes.invoke(CraftBukkitReflections.field$CraftServer$playerList.get(Bukkit.getServer())); + CoreReflections.methodHandle$DedicatedPlayerList$reloadRecipes.invokeExact(CraftBukkitReflections.methodHandle$CraftServer$playerListGetter.invokeExact(Bukkit.getServer())); // now we need to remove the fake `exact` choices if (VersionHelper.isOrAbove1_21_4()) { for (Object ingredient : MODIFIED_INGREDIENTS) { - CoreReflections.field$Ingredient$itemStacks1_21_4.set(ingredient, null); + CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (Set) null); } } else if (VersionHelper.isOrAbove1_21_2()) { for (Object ingredient : MODIFIED_INGREDIENTS) { - CoreReflections.field$Ingredient$itemStacks1_21_2.set(ingredient, null); + CoreReflections.methodHandle$Ingredient$itemStacksSetter.invokeExact(ingredient, (List) null); } } // clear cache MODIFIED_INGREDIENTS.clear(); - } catch (Exception e) { + } catch (Throwable e) { this.plugin.logger().warn("Failed to run delayed recipe tasks", e); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java index a216443ec..7d09bd51f 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/reflection/bukkit/CraftBukkitReflections.java @@ -1,10 +1,12 @@ package net.momirealms.craftengine.bukkit.plugin.reflection.bukkit; +import net.momirealms.craftengine.bukkit.plugin.reflection.ReflectionInitException; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.BukkitReflectionUtils; import net.momirealms.craftengine.core.util.ReflectionUtils; import net.momirealms.craftengine.core.util.VersionHelper; import org.bukkit.NamespacedKey; +import org.bukkit.Server; import org.bukkit.block.BlockState; import org.bukkit.block.data.BlockData; import org.bukkit.entity.HumanEntity; @@ -12,6 +14,8 @@ import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.inventory.*; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -201,6 +205,17 @@ public final class CraftBukkitReflections { ReflectionUtils.getDeclaredField(clazz$CraftServer, CoreReflections.clazz$DedicatedPlayerList, 0) ); + public static final MethodHandle methodHandle$CraftServer$playerListGetter; + + static { + try { + methodHandle$CraftServer$playerListGetter = ReflectionUtils.unreflectGetter(field$CraftServer$playerList) + .asType(MethodType.methodType(Object.class, Server.class)); + } catch (Exception e) { + throw new ReflectionInitException("Failed to initialize methodHandle$CraftServer$playerList", e); + } + } + public static final Class clazz$CraftInventoryCrafting = requireNonNull( ReflectionUtils.getClazz(BukkitReflectionUtils.assembleCBClass("inventory.CraftInventoryCrafting")) ); 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 0d494798a..bff6a601b 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 @@ -14,6 +14,7 @@ import net.momirealms.craftengine.core.util.ReflectionUtils; import net.momirealms.craftengine.core.util.VersionHelper; import java.io.BufferedReader; +import java.io.Reader; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.lang.invoke.VarHandle; @@ -97,6 +98,17 @@ public final class CoreReflections { public static final Method method$FileToIdConverter$json = requireNonNull( ReflectionUtils.getStaticMethod(clazz$FileToIdConverter, clazz$FileToIdConverter, String.class) ); + + public static final MethodHandle methodHandle$FileToIdConverter$json; + + static { + try { + methodHandle$FileToIdConverter$json = ReflectionUtils.unreflectMethod(method$FileToIdConverter$json) + .asType(MethodType.methodType(Object.class, String.class)); + } catch (Throwable t) { + throw new ReflectionInitException("Failed to initialize methodHandle$FileToIdConverter$json", t); + } + } public static final Class clazz$RegistryOps = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( @@ -1900,17 +1912,42 @@ public final class CoreReflections { ) ); - // 1.20.1-1.21.1 - public static final Field field$Ingredient$itemStacks1_20_1 = - ReflectionUtils.getDeclaredField(clazz$Ingredient, clazz$ItemStack.arrayType(), 0); + public static final Field field$Ingredient$itemStacks = requireNonNull( + ReflectionUtils.getDeclaredField( + clazz$Ingredient, + VersionHelper.isOrAbove1_21_4() ? Set.class : VersionHelper.isOrAbove1_21_2() ? List.class : clazz$ItemStack.arrayType(), + VersionHelper.isOrAbove1_21_4() ? 0 : VersionHelper.isOrAbove1_21_2() ? 1 : 0 + ) + ); - // 1.21.2-1.21.3 - public static final Field field$Ingredient$itemStacks1_21_2 = - ReflectionUtils.getDeclaredField(clazz$Ingredient, List.class, 1); + public static final MethodHandle methodHandle$RecipeManager$finalizeRecipeLoading; + public static final MethodHandle methodHandle$RecipeManager$featureflagsetGetter; + public static final MethodHandle methodHandle$RecipeManager$featureflagsetSetter; + public static final MethodHandle methodHandle$Ingredient$itemStacksSetter; - // 1.21.4 paper - public static final Field field$Ingredient$itemStacks1_21_4 = - ReflectionUtils.getDeclaredField(clazz$Ingredient, Set.class, 0); + static { + try { + if (method$RecipeManager$finalizeRecipeLoading != null) { + methodHandle$RecipeManager$finalizeRecipeLoading = ReflectionUtils.unreflectMethod(method$RecipeManager$finalizeRecipeLoading) + .asType(MethodType.methodType(void.class, Object.class)); + } else { + methodHandle$RecipeManager$finalizeRecipeLoading = null; + } + if (field$RecipeManager$featureflagset != null) { + methodHandle$RecipeManager$featureflagsetGetter = ReflectionUtils.unreflectGetter(field$RecipeManager$featureflagset) + .asType(MethodType.methodType(Object.class, Object.class)); + methodHandle$RecipeManager$featureflagsetSetter = ReflectionUtils.unreflectSetter(field$RecipeManager$featureflagset) + .asType(MethodType.methodType(void.class, Object.class, Object.class)); + } else { + methodHandle$RecipeManager$featureflagsetGetter = null; + methodHandle$RecipeManager$featureflagsetSetter = null; + } + methodHandle$Ingredient$itemStacksSetter = ReflectionUtils.unreflectSetter(field$Ingredient$itemStacks) + .asType(MethodType.methodType(void.class, Object.class, VersionHelper.isOrAbove1_21_4() ? Set.class : VersionHelper.isOrAbove1_21_2() ? List.class : Object.class)); + } catch (Exception e) { + throw new ReflectionInitException("Failed to initialize CoreReflections", e); + } + } // Since 1.21.2, exact has been removed public static final Field field$Ingredient$exact = @@ -1928,7 +1965,7 @@ public final class CoreReflections { ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("world.item.crafting.ShapedRecipePattern")); // 1.20.1-1.20.2 - public static final Field field$1_20_1$ShapedRecipe$recipeItems= + public static final Field field$1_20_1$ShapedRecipe$recipeItems = ReflectionUtils.getDeclaredField(clazz$ShapedRecipe, clazz$NonNullList, 0); // 1.20.3+ @@ -1992,6 +2029,70 @@ public final class CoreReflections { Optional.ofNullable(ReflectionUtils.getDeclaredField(clazz$ShapelessRecipe, List.class, 0)) .orElse(ReflectionUtils.getDeclaredField(clazz$ShapelessRecipe, clazz$NonNullList, 0)); + public static final MethodHandle methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter; + public static final MethodHandle methodHandle$1_20_3$ShapedRecipe$patternGetter; + public static final MethodHandle methodHandle$ShapedRecipePattern$ingredients1_20_3Getter; + public static final MethodHandle methodHandle$ShapedRecipePattern$ingredients1_21_2Getter; + public static final MethodHandle methodHandle$Ingredient$valuesGetter; + public static final MethodHandle methodHandle$ShapelessRecipe$placementInfoSetter; + public static final MethodHandle methodHandle$ShapedRecipe$placementInfoSetter; + public static final MethodHandle methodHandle$ShapelessRecipe$ingredientsGetter; + + static { + try { + if (field$1_20_1$ShapedRecipe$recipeItems != null) { + methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter = ReflectionUtils.unreflectGetter(field$1_20_1$ShapedRecipe$recipeItems) + .asType(MethodType.methodType(List.class, Object.class)); + } else { + methodHandle$1_20_1$ShapedRecipe$recipeItemsGetter = null; + } + if (field$1_20_3$ShapedRecipe$pattern != null) { + methodHandle$1_20_3$ShapedRecipe$patternGetter = ReflectionUtils.unreflectGetter(field$1_20_3$ShapedRecipe$pattern) + .asType(MethodType.methodType(Object.class, Object.class)); + } else { + methodHandle$1_20_3$ShapedRecipe$patternGetter = null; + } + if (field$ShapedRecipePattern$ingredients1_20_3 != null) { + methodHandle$ShapedRecipePattern$ingredients1_20_3Getter = ReflectionUtils.unreflectGetter(field$ShapedRecipePattern$ingredients1_20_3) + .asType(MethodType.methodType(List.class, Object.class)); + } else { + methodHandle$ShapedRecipePattern$ingredients1_20_3Getter = null; + } + if (field$ShapedRecipePattern$ingredients1_21_2 != null) { + methodHandle$ShapedRecipePattern$ingredients1_21_2Getter = ReflectionUtils.unreflectGetter(field$ShapedRecipePattern$ingredients1_21_2) + .asType(MethodType.methodType(List.class, Object.class)); + } else { + methodHandle$ShapedRecipePattern$ingredients1_21_2Getter = null; + } + if (field$Ingredient$values != null) { + methodHandle$Ingredient$valuesGetter = ReflectionUtils.unreflectGetter(field$Ingredient$values) + .asType(MethodType.methodType(Object[].class, Object.class)); + } else { + methodHandle$Ingredient$valuesGetter = null; + } + if (field$ShapelessRecipe$placementInfo != null) { + methodHandle$ShapelessRecipe$placementInfoSetter = ReflectionUtils.unreflectSetter(field$ShapelessRecipe$placementInfo) + .asType(MethodType.methodType(void.class, Object.class, Object.class)); + } else { + methodHandle$ShapelessRecipe$placementInfoSetter = null; + } + if (field$ShapedRecipe$placementInfo != null) { + methodHandle$ShapedRecipe$placementInfoSetter = ReflectionUtils.unreflectSetter(field$ShapedRecipe$placementInfo) + .asType(MethodType.methodType(void.class, Object.class, Object.class)); + } else { + methodHandle$ShapedRecipe$placementInfoSetter = null; + } + if (field$ShapelessRecipe$ingredients != null) { + methodHandle$ShapelessRecipe$ingredientsGetter = ReflectionUtils.unreflectGetter(field$ShapelessRecipe$ingredients) + .asType(MethodType.methodType(List.class, Object.class)); + } else { + methodHandle$ShapelessRecipe$ingredientsGetter = null; + } + } catch (Exception e) { + throw new ReflectionInitException("Failed to initialize CoreReflections", e); + } + } + // require ResourceLocation for 1.20.1-1.21.1 // require ResourceKey for 1.21.2+ public static final Method method$RecipeManager$byKey; @@ -2093,6 +2194,28 @@ public final class CoreReflections { .map(it -> ReflectionUtils.getDeclaredField(it, clazz$Ingredient, 0)) .orElse(null); + public static final MethodHandle methodHandle$AbstractCookingRecipe$inputGetter; + public static final MethodHandle methodHandle$SingleItemRecipe$inputGetter; + + static { + try { + if (field$AbstractCookingRecipe$input != null) { + methodHandle$AbstractCookingRecipe$inputGetter = ReflectionUtils.unreflectGetter(field$AbstractCookingRecipe$input) + .asType(MethodType.methodType(Object.class, Object.class)); + } else { + methodHandle$AbstractCookingRecipe$inputGetter = null; + } + if (field$SingleItemRecipe$input != null) { + methodHandle$SingleItemRecipe$inputGetter = ReflectionUtils.unreflectGetter(field$SingleItemRecipe$input) + .asType(MethodType.methodType(Object.class, Object.class)); + } else { + methodHandle$SingleItemRecipe$inputGetter = null; + } + } catch (Exception e) { + throw new ReflectionInitException("Failed to initialize methodHandle$SingleItemRecipe$inputGetter", e); + } + } + public static final Field field$AbstractFurnaceBlockEntity$quickCheck = requireNonNull( ReflectionUtils.getDeclaredField(clazz$AbstractFurnaceBlockEntity, clazz$RecipeManager$CachedCheck, 0) ); @@ -3019,6 +3142,17 @@ public final class CoreReflections { ReflectionUtils.getMethod(clazz$Resource, BufferedReader.class) ); + public static final MethodHandle methodHandle$Resource$openAsReader; + + static { + try { + methodHandle$Resource$openAsReader = ReflectionUtils.unreflectMethod(method$Resource$openAsReader) + .asType(MethodType.methodType(Reader.class, Object.class)); + } catch (Exception e) { + throw new ReflectionInitException("Failed to init methodHandle$Resource$openAsReader", e); + } + } + public static final Class clazz$MultiPackResourceManager = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( "server.packs.resources.ResourceManager", @@ -3063,6 +3197,20 @@ public final class CoreReflections { ReflectionUtils.getInstanceDeclaredField(clazz$PackRepository, List.class, 0) ); + public static final MethodHandle methodHandle$MinecraftServer$getPackRepository; + public static final MethodHandle methodHandle$PackRepository$selectedGetter; + + static { + try { + methodHandle$MinecraftServer$getPackRepository = ReflectionUtils.unreflectMethod(method$MinecraftServer$getPackRepository) + .asType(MethodType.methodType(Object.class, Object.class)); + methodHandle$PackRepository$selectedGetter = ReflectionUtils.unreflectGetter(field$PackRepository$selected) + .asType(MethodType.methodType(List.class, Object.class)); + } catch (Exception e) { + throw new ReflectionInitException("Failed to initialize reflection for methodHandle$MinecraftServer$getPackRepository", e); + } + } + public static final Class clazz$Pack = requireNonNull( BukkitReflectionUtils.findReobfOrMojmapClass( "server.packs.repository.ResourcePackLoader", @@ -3109,6 +3257,23 @@ public final class CoreReflections { ReflectionUtils.getMethod(clazz$DedicatedPlayerList, new String[] {"reloadRecipeData", "reloadRecipes"}) ); + public static final MethodHandle methodHandle$DedicatedPlayerList$reloadRecipes; + public static final MethodHandle methodHandle$Pack$open; + public static final MethodHandle methodHandle$MultiPackResourceManagerConstructor; + + static { + try { + methodHandle$DedicatedPlayerList$reloadRecipes = ReflectionUtils.unreflectMethod(method$DedicatedPlayerList$reloadRecipes) + .asType(MethodType.methodType(void.class, Object.class)); + methodHandle$Pack$open = ReflectionUtils.unreflectMethod(method$Pack$open) + .asType(MethodType.methodType(Object.class, Object.class)); + methodHandle$MultiPackResourceManagerConstructor = ReflectionUtils.unreflectConstructor(constructor$MultiPackResourceManager) + .asType(MethodType.methodType(AutoCloseable.class, Object.class, List.class)); + } catch (Exception e) { + throw new ReflectionInitException("Failed to init methodHandle$DedicatedPlayerList$reloadRecipes", e); + } + } + public static final Method method$ServerChunkCache$getGenerator = requireNonNull( ReflectionUtils.getMethod(clazz$ServerChunkCache, clazz$ChunkGenerator) ); @@ -3315,6 +3480,17 @@ public final class CoreReflections { ReflectionUtils.getMethod(clazz$FileToIdConverter, Map.class, new String[]{"listMatchingResources", "a"}, clazz$ResourceManager) ); + public static final MethodHandle methodHandle$FileToIdConverter$listMatchingResources; + + static { + try { + methodHandle$FileToIdConverter$listMatchingResources = ReflectionUtils.unreflectMethod(method$FileToIdConverter$listMatchingResources) + .asType(MethodType.methodType(Map.class, Object.class, AutoCloseable.class)); + } catch (Exception e) { + throw new ReflectionInitException("Failed to initialize methodHandle$FileToIdConverter$listMatchingResources", e); + } + } + public static final Method method$RegistryOps$create = requireNonNull( ReflectionUtils.getStaticMethod(clazz$RegistryOps, clazz$RegistryOps, DynamicOps.class, clazz$HolderLookup$Provider) );