9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-23 17:09:19 +00:00

优化熔炉性能,保证线程安全

This commit is contained in:
XiaoMoMi
2025-06-07 19:49:47 +08:00
parent b0e1305427
commit 26edc960a2
16 changed files with 276 additions and 285 deletions

View File

@@ -160,7 +160,7 @@ public class BukkitBlockManager extends AbstractBlockManager {
for (Map.Entry<Integer, List<String>> 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);
}

View File

@@ -151,7 +151,7 @@ public class BukkitCustomBlock extends AbstractCustomBlock {
Object holder = BukkitCraftEngine.instance().blockManager().getMinecraftBlockHolder(state.customBlockState().registryId());
Set<Object> 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

View File

@@ -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<Object> holder = (Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(registry, FeatureUtils.createFeatureKey(treeFeature()));

View File

@@ -214,7 +214,7 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
.orElseGet(() -> ((WritableRegistry<Key>) 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<Object>) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.instance$Registries$ITEM, resourceLocation))).get();
Object mcHolder = ((Optional<Object>) CoreReflections.method$Registry$getHolder1.invoke(MBuiltInRegistries.ITEM, CoreReflections.method$ResourceKey$create.invoke(null, MRegistries.ITEM, resourceLocation))).get();
Set<Object> tags = (Set<Object>) CoreReflections.field$Holder$Reference$tags.get(mcHolder);
for (Object tag : tags) {
Key tagId = Key.of(CoreReflections.field$TagKey$location.get(tag).toString());

View File

@@ -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<ItemStack> {
// 将自定义配方转为“广义”配方,接受更加宽容的输入
// 部分过程借助bukkit完成部分直接通过nms方法注册
private static final Map<Key, BukkitRecipeConvertor<? extends Recipe<ItemStack>>> MIXED_RECIPE_CONVERTORS = new HashMap<>();
private static Object nmsRecipeManager;
private static final List<Object> injectedIngredients = new ArrayList<>();
private static final IdentityHashMap<Recipe<ItemStack>, Object> recipeToMcRecipeHolder = new IdentityHashMap<>();
private static final IdentityHashMap<Recipe<ItemStack>, 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<ItemStack> {
}
public Object nmsRecipeHolderByRecipe(Recipe<ItemStack> 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<ItemStack> {
@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<ItemStack> {
} catch (ReflectiveOperationException e) {
this.plugin.logger().warn("Failed to unregister recipes", e);
}
recipeToMcRecipeHolder.clear();
}
@Override
@@ -320,6 +322,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
@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<ItemStack> {
// clear cache
injectedIngredients.clear();
CE_RECIPE_2_NMS_HOLDER.clear();
// create mappings
for (Map.Entry<Key, Recipe<ItemStack>> entry : this.byId.entrySet()) {
Optional<Object> 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<ItemStack> {
return optionalItem.map(itemStackCustomItem -> MaterialUtils.getMaterial(itemStackCustomItem.material())).orElse(null);
}
private static List<Object> getIngredientLooks(List<Holder<Key>> holders) throws ReflectiveOperationException {
private static List<Object> getIngredientLooks(List<Holder<Key>> holders) {
List<Object> itemStacks = new ArrayList<>();
for (Holder<Key> holder : holders) {
ItemStack itemStack = BukkitItemManager.instance().getBuildableItem(holder.value()).get().buildItemStack(ItemBuildContext.EMPTY, 1);
@@ -710,8 +722,7 @@ public class BukkitRecipeManager extends AbstractRecipeManager<ItemStack> {
.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<ItemStack> {
try {
List<Ingredient<ItemStack>> 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<ItemStack> {
private static void injectCookingRecipe(Key id, CustomCookingRecipe<ItemStack> recipe) {
try {
Ingredient<ItemStack> 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<ItemStack> {
// 获取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<Object> 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<Object> optional = (Optional<Object>) 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<Object> optional = (Optional<Object>) CoreReflections.method$RecipeManager$byKey.invoke(nmsRecipeManager, resourceLocation);
if (optional.isEmpty()) {
throw new IllegalArgumentException("Recipe " + id + " not found");
}
return optional.get();
return optional;
}
}

View File

@@ -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<ItemStack> 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<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) 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<ItemStack> 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);
}
}

View File

@@ -8,6 +8,10 @@ public interface InjectedCacheCheck {
void recipeType(Object recipeType);
Key customRecipeType();
void customRecipeType(Key customRecipeType);
Object lastRecipe();
void lastRecipe(Object lastRecipe);

View File

@@ -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<Pair<Object, Object>> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(mcRecipeManager, type, args[0], args[1], lastRecipe);
if (optionalRecipe.isPresent()) {
Pair<Object, Object> pair = optionalRecipe.get();
Object resourceLocation = pair.getFirst();
Key recipeId = Key.of(resourceLocation.toString());
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
ItemStack itemStack;
List<Object> items;
if (type == MRecipeTypes.CAMPFIRE_COOKING) {
items = (List<Object>) CoreReflections.field$SimpleContainer$items.get(args[0]);
} else {
items = (List<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
if (type == MRecipeTypes.SMELTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.BLASTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.SMOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.CAMPFIRE_COOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Pair<Object, Object>> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.nmsRecipeManager(), injectedCacheCheck.recipeType(), args[0], args[1], lastRecipeResourceLocation);
if (optionalRecipe.isEmpty()) {
return Optional.empty();
}
Pair<Object, Object> 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Object> optionalRecipe = (Optional<Object>) 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<Object> items;
if (type == MRecipeTypes.CAMPFIRE_COOKING) {
items = (List<Object>) CoreReflections.field$SimpleContainer$items.get(args[0]);
} else {
items = (List<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
if (type == MRecipeTypes.SMELTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.BLASTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.SMOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.CAMPFIRE_COOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Object> optionalRecipe = (Optional<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Object> optionalRecipe = (Optional<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
if (type == MRecipeTypes.SMELTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.BLASTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.SMOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMOKING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.CAMPFIRE_COOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Object> optionalRecipe = (Optional<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Object> optionalRecipe = (Optional<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = injectedCacheCheck.lastCustomRecipe();
if (type == MRecipeTypes.SMELTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.SMELTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.BLASTING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) recipeManager.recipeByInput(RecipeTypes.BLASTING, input, lastCustomRecipe);
} else if (type == MRecipeTypes.SMOKING) {
ceRecipe = (CustomCookingRecipe<ItemStack>) 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<Object> optionalRecipe = (Optional<Object>) 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<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) {
return Optional.empty();
}
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCookingRecipe<ItemStack> ceRecipe = (CustomCookingRecipe<ItemStack>) 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));
}
}
}

View File

@@ -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);
}

View File

@@ -26,7 +26,7 @@ public class BukkitSoundManager extends AbstractSoundManager {
protected void registerSongs(Map<Key, JukeboxSong> 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<Key, JukeboxSong> entry : songs.entrySet()) {
Key id = entry.getKey();

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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);

View File

@@ -28,6 +28,7 @@ public abstract class AbstractRecipeManager<T> implements RecipeManager<T> {
protected final Set<Key> dataPackRecipes = new HashSet<>();
protected final Set<Key> customRecipes = new HashSet<>();
private final RecipeParser recipeParser;
protected boolean isReloading;
public AbstractRecipeManager() {
this.recipeReader = initVanillaRecipeReader();
@@ -72,37 +73,44 @@ public abstract class AbstractRecipeManager<T> implements RecipeManager<T> {
@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<Recipe<T>> recipeById(Key key) {
if (this.isReloading) return Optional.empty();
return Optional.ofNullable(this.byId.get(key));
}
@Override
public List<Recipe<T>> recipesByType(Key type) {
if (this.isReloading) return List.of();
return this.byType.getOrDefault(type, List.of());
}
@Override
public List<Recipe<T>> recipeByResult(Key result) {
if (this.isReloading) return List.of();
return this.byResult.getOrDefault(result, List.of());
}
@Override
public List<Recipe<T>> recipeByIngredient(Key ingredient) {
if (this.isReloading) return List.of();
return this.byIngredient.getOrDefault(ingredient, List.of());
}
@Nullable
@Override
public Recipe<T> recipeByInput(Key type, RecipeInput input) {
if (this.isReloading) return null;
List<Recipe<T>> recipes = this.byType.get(type);
if (recipes == null) return null;
for (Recipe<T> recipe : recipes) {
@@ -116,8 +124,9 @@ public abstract class AbstractRecipeManager<T> implements RecipeManager<T> {
@Nullable
@Override
public Recipe<T> recipeByInput(Key type, RecipeInput input, Key lastRecipe) {
if (this.isReloading) return null;
if (lastRecipe != null) {
Recipe<T> last = byId.get(lastRecipe);
Recipe<T> last = this.byId.get(lastRecipe);
if (last != null && last.matches(input)) {
return last;
}

View File

@@ -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