mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-06 15:52:03 +00:00
Inject Cooking Recipes
This commit is contained in:
@@ -51,6 +51,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
private static Object minecraftRecipeManager;
|
||||
private static final List<Object> injectedIngredients = new ArrayList<>();
|
||||
private static final IdentityHashMap<Recipe<ItemStack>, Object> recipeToMcRecipeHolder = new IdentityHashMap<>();
|
||||
private static BukkitRecipeManager instance;
|
||||
|
||||
static {
|
||||
BUKKIT_RECIPE_REGISTER.put(RecipeTypes.SHAPED, (key, recipe) -> {
|
||||
@@ -185,6 +186,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
private final CrafterEventListener crafterEventListener;
|
||||
private final PaperRecipeEventListener paperRecipeEventListener;
|
||||
private final Map<Key, List<Recipe<ItemStack>>> recipes;
|
||||
private final Map<Key, Recipe<ItemStack>> byId;
|
||||
private final VanillaRecipeReader recipeReader;
|
||||
private final List<NamespacedKey> injectedDataPackRecipes;
|
||||
private final List<NamespacedKey> registeredCustomRecipes;
|
||||
@@ -197,8 +199,10 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
private Object stolenFeatureFlagSet;
|
||||
|
||||
public BukkitRecipeManager(BukkitCraftEngine plugin) {
|
||||
instance = this;
|
||||
this.plugin = plugin;
|
||||
this.recipes = new HashMap<>();
|
||||
this.byId = new HashMap<>();
|
||||
this.injectedDataPackRecipes = new ArrayList<>();
|
||||
this.registeredCustomRecipes = new ArrayList<>();
|
||||
this.dataPackRecipes = new HashSet<>();
|
||||
@@ -238,6 +242,11 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
return this.customRecipes.contains(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Recipe<ItemStack>> getRecipeById(Key key) {
|
||||
return Optional.ofNullable(this.byId.get(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
if (!ConfigManager.enableRecipeSystem()) return;
|
||||
@@ -268,6 +277,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
HandlerList.unregisterAll(this.paperRecipeEventListener);
|
||||
}
|
||||
this.recipes.clear();
|
||||
this.byId.clear();
|
||||
this.dataPackRecipes.clear();
|
||||
this.customRecipes.clear();
|
||||
|
||||
@@ -325,6 +335,7 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
return this.recipes.getOrDefault(type, List.of());
|
||||
}
|
||||
|
||||
// example: stone button
|
||||
public void addVanillaInternalRecipe(Key id, Recipe<ItemStack> recipe) {
|
||||
this.customRecipes.add(id);
|
||||
this.recipes.computeIfAbsent(recipe.type(), k -> new ArrayList<>()).add(recipe);
|
||||
@@ -343,6 +354,25 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Recipe<ItemStack> getRecipe(Key type, RecipeInput input, Key lastRecipe) {
|
||||
List<Recipe<ItemStack>> recipes = this.recipes.get(type);
|
||||
if (recipes == null) return null;
|
||||
if (lastRecipe != null) {
|
||||
Recipe<ItemStack> last = byId.get(lastRecipe);
|
||||
if (last != null && last.matches(input)) {
|
||||
return last;
|
||||
}
|
||||
for (Recipe<ItemStack> recipe : recipes) {
|
||||
if (recipe.matches(input)) {
|
||||
return recipe;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> delayedLoad() {
|
||||
if (!ConfigManager.enableRecipeSystem()) return CompletableFuture.completedFuture(null);
|
||||
@@ -807,4 +837,12 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
|
||||
public Object getRecipeHolderByRecipe(Recipe<ItemStack> recipe) {
|
||||
return recipeToMcRecipeHolder.get(recipe);
|
||||
}
|
||||
|
||||
public static Object minecraftRecipeManager() {
|
||||
return minecraftRecipeManager;
|
||||
}
|
||||
|
||||
public static BukkitRecipeManager instance() {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,25 +42,17 @@ public class CrafterEventListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory inventory = crafter.getInventory();
|
||||
ItemStack[] ingredients = inventory.getStorageContents();
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
|
||||
// if the recipe is a vanilla one, custom items should never be ingredients
|
||||
if (this.recipeManager.isDataPackRecipe(recipeId) && !isCustom) {
|
||||
if (ItemUtils.hasCustomItem(ingredients)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory inventory = crafter.getInventory();
|
||||
ItemStack[] ingredients = inventory.getStorageContents();
|
||||
|
||||
List<OptimizedIDItem<ItemStack>> optimizedIDItems = new ArrayList<>();
|
||||
for (ItemStack itemStack : ingredients) {
|
||||
if (ItemUtils.isEmpty(itemStack)) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemManager;
|
||||
import net.momirealms.craftengine.core.item.recipe.CookingInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
@@ -15,15 +15,17 @@ import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.*;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Furnace;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.event.world.EntitiesLoadEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.inventory.PrepareItemCraftEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -42,6 +44,36 @@ public class RecipeEventListener implements Listener {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onFurnaceInventoryOpen(InventoryOpenEvent event) {
|
||||
if (!(event.getInventory() instanceof FurnaceInventory furnaceInventory)) {
|
||||
return;
|
||||
}
|
||||
Furnace furnace = furnaceInventory.getHolder();
|
||||
try {
|
||||
Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(furnace);
|
||||
BukkitInjector.injectFurnaceBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onPlaceBlock(BlockPlaceEvent event) {
|
||||
Block block = event.getBlock();
|
||||
Material material = block.getType();
|
||||
if (material == Material.FURNACE || material == Material.BLAST_FURNACE || material == Material.SMOKER) {
|
||||
if (block.getState() instanceof Furnace furnace) {
|
||||
try {
|
||||
Object blockEntity = Reflections.field$CraftBlockEntityState$tileEntity.get(furnace);
|
||||
BukkitInjector.injectFurnaceBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onClickCartographyTable(InventoryClickEvent event) {
|
||||
if (VersionHelper.isPaper()) return;
|
||||
@@ -55,13 +87,6 @@ public class RecipeEventListener implements Listener {
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onChunkLoad(ChunkLoadEvent event) {
|
||||
for (BlockState state : event.getChunk().getTileEntities()) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSpecialRecipe(PrepareItemCraftEvent event) {
|
||||
org.bukkit.inventory.Recipe recipe = event.getRecipe();
|
||||
@@ -89,24 +114,15 @@ public class RecipeEventListener implements Listener {
|
||||
CraftingRecipe craftingRecipe = (CraftingRecipe) recipe;
|
||||
Key recipeId = Key.of(craftingRecipe.getKey().namespace(), craftingRecipe.getKey().value());
|
||||
|
||||
CraftingInventory inventory = event.getInventory();
|
||||
ItemStack[] ingredients = inventory.getMatrix();
|
||||
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
|
||||
// if the recipe is a vanilla one but not injected, custom items should never be ingredients
|
||||
if (this.recipeManager.isDataPackRecipe(recipeId) && !isCustom) {
|
||||
if (ItemUtils.hasCustomItem(ingredients)) {
|
||||
inventory.setResult(null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
CraftingInventory inventory = event.getInventory();
|
||||
ItemStack[] ingredients = inventory.getMatrix();
|
||||
|
||||
List<OptimizedIDItem<ItemStack>> optimizedIDItems = new ArrayList<>();
|
||||
for (ItemStack itemStack : ingredients) {
|
||||
if (ItemUtils.isEmpty(itemStack)) {
|
||||
@@ -142,6 +158,8 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
// though it might be inaccurate after reloading
|
||||
// but it's worthy to cache
|
||||
Recipe<ItemStack> lastRecipe = serverPlayer.lastUsedRecipe();
|
||||
if (lastRecipe != null && (lastRecipe.type() == RecipeTypes.SHAPELESS || lastRecipe.type() == RecipeTypes.SHAPED )) {
|
||||
if (lastRecipe.matches(input)) {
|
||||
@@ -170,7 +188,10 @@ public class RecipeEventListener implements Listener {
|
||||
|
||||
private void correctCraftingRecipeUsed(CraftingInventory inventory, Recipe<ItemStack> recipe) {
|
||||
Object holderOrRecipe = recipeManager.getRecipeHolderByRecipe(recipe);
|
||||
if (holderOrRecipe == null) return;
|
||||
if (holderOrRecipe == null) {
|
||||
// it's a vanilla recipe but not injected
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object resultInventory = Reflections.field$CraftInventoryCrafting$resultInventory.get(inventory);
|
||||
Reflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe);
|
||||
@@ -178,110 +199,4 @@ public class RecipeEventListener implements Listener {
|
||||
plugin.logger().warn("Failed to correct used recipe", e);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO find a lighter way
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onFurnaceBurn(FurnaceBurnEvent event) {
|
||||
if (!(event.getBlock().getState() instanceof Furnace furnace)) {
|
||||
return;
|
||||
}
|
||||
FurnaceInventory inventory = furnace.getInventory();
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onFurnaceStartSmelt(FurnaceStartSmeltEvent event) {
|
||||
CookingRecipe<?> recipe = event.getRecipe();
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
ItemStack sourceItem = event.getSource();
|
||||
|
||||
if (this.recipeManager.isDataPackRecipe(recipeId) && !isCustom) {
|
||||
if (ItemUtils.isCustomItem(sourceItem)) {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(sourceItem);
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), event.getSource()));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
if (recipe instanceof FurnaceRecipe) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) this.recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
} else if (recipe instanceof SmokingRecipe) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) this.recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
} else if (recipe instanceof BlastingRecipe) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) this.recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
} else {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setTotalCookTime(ceRecipe.cookingTime());
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onFurnaceSmelt(FurnaceSmeltEvent event) {
|
||||
CookingRecipe<?> recipe = event.getRecipe();
|
||||
if (recipe == null) return;
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
|
||||
if (this.recipeManager.isDataPackRecipe(recipeId) && !isCustom) {
|
||||
if (ItemUtils.isCustomItem(event.getSource())) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(event.getSource());
|
||||
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
|
||||
if (idHolder.isEmpty()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), event.getSource()));
|
||||
if (recipe instanceof FurnaceRecipe furnaceRecipe) {
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
if (ceRecipe != null) {
|
||||
event.setResult(ceRecipe.getResult(null));
|
||||
return;
|
||||
}
|
||||
} else if (recipe instanceof SmokingRecipe smokingRecipe) {
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
if (ceRecipe != null) {
|
||||
event.setResult(ceRecipe.getResult(null));
|
||||
return;
|
||||
}
|
||||
} else if (recipe instanceof BlastingRecipe blastingRecipe) {
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
if (ceRecipe != null) {
|
||||
event.setResult(ceRecipe.getResult(null));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.momirealms.craftengine.bukkit.plugin.injector;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.ClassFileVersion;
|
||||
import net.bytebuddy.description.modifier.Visibility;
|
||||
@@ -12,6 +13,8 @@ import net.bytebuddy.implementation.bind.annotation.*;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockManager;
|
||||
import net.momirealms.craftengine.bukkit.block.BukkitBlockShape;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.NoteBlockChainUpdateUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
@@ -19,8 +22,14 @@ import net.momirealms.craftengine.core.block.BlockKeys;
|
||||
import net.momirealms.craftengine.core.block.EmptyBlock;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.block.StatePredicate;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.recipe.CookingInput;
|
||||
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Holder;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import net.momirealms.craftengine.core.util.SectionPosUtils;
|
||||
@@ -30,6 +39,7 @@ import net.momirealms.craftengine.core.world.SectionPos;
|
||||
import net.momirealms.craftengine.core.world.chunk.CESection;
|
||||
import net.momirealms.craftengine.shared.ObjectHolder;
|
||||
import net.momirealms.craftengine.shared.block.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
@@ -38,7 +48,9 @@ import java.lang.invoke.MethodType;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -64,8 +76,33 @@ public class BukkitInjector {
|
||||
private static Field field$CraftEngineBlock$shape;
|
||||
private static Field field$CraftEngineBlock$isNoteBlock;
|
||||
|
||||
private static Class<?> clazz$InjectedCacheChecker;
|
||||
private static Field field$InjectedCacheChecker$recipeType;
|
||||
private static Field field$InjectedCacheChecker$lastRecipe;
|
||||
|
||||
public static void init() {
|
||||
try {
|
||||
clazz$InjectedCacheChecker = byteBuddy
|
||||
.subclass(Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
.implement(Reflections.clazz$RecipeManager$CachedCheck)
|
||||
.defineField("recipeType", Reflections.clazz$RecipeType, Visibility.PUBLIC)
|
||||
.defineField("lastRecipe", Object.class, Visibility.PUBLIC)
|
||||
.method(ElementMatchers.named("getRecipeFor").or(ElementMatchers.named("a")))
|
||||
.intercept(MethodDelegation.to(
|
||||
VersionHelper.isVersionNewerThan1_21_2() ?
|
||||
GetRecipeForMethodInterceptor1_21_2.INSTANCE :
|
||||
(VersionHelper.isVersionNewerThan1_21() ?
|
||||
GetRecipeForMethodInterceptor1_21.INSTANCE :
|
||||
VersionHelper.isVersionNewerThan1_20_5() ?
|
||||
GetRecipeForMethodInterceptor1_20_5.INSTANCE :
|
||||
GetRecipeForMethodInterceptor1_20.INSTANCE)
|
||||
))
|
||||
.make()
|
||||
.load(BukkitInjector.class.getClassLoader())
|
||||
.getLoaded();
|
||||
field$InjectedCacheChecker$recipeType = clazz$InjectedCacheChecker.getDeclaredField("recipeType");
|
||||
field$InjectedCacheChecker$lastRecipe = clazz$InjectedCacheChecker.getDeclaredField("lastRecipe");
|
||||
|
||||
// Paletted Container
|
||||
clazz$InjectedPalettedContainer = byteBuddy
|
||||
.subclass(Reflections.clazz$PalettedContainer)
|
||||
@@ -215,6 +252,16 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectFurnaceBlockEntity(Object entity) throws ReflectiveOperationException {
|
||||
if (!Reflections.clazz$AbstractFurnaceBlockEntity.isInstance(entity)) return;
|
||||
Object quickCheck = Reflections.field$AbstractFurnaceBlockEntity$quickCheck.get(entity);
|
||||
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
||||
Object recipeType = Reflections.field$AbstractFurnaceBlockEntity$recipeType.get(entity);
|
||||
Object injectedChecker = Reflections.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
||||
field$InjectedCacheChecker$recipeType.set(injectedChecker, recipeType);
|
||||
Reflections.field$AbstractFurnaceBlockEntity$quickCheck.set(entity, injectedChecker);
|
||||
}
|
||||
|
||||
public static Object getOptimizedItemDisplayFactory() {
|
||||
return instance$OptimizedItemDisplayFactory;
|
||||
}
|
||||
@@ -256,6 +303,229 @@ public class BukkitInjector {
|
||||
}
|
||||
}
|
||||
|
||||
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.minecraftRecipeManager();
|
||||
Object type = field$InjectedCacheChecker$recipeType.get(thisObj);
|
||||
Object lastRecipe = field$InjectedCacheChecker$lastRecipe.get(thisObj);
|
||||
Optional<Pair<Object, Object>> optionalRecipe = (Optional<Pair<Object, Object>>) Reflections.method$RecipeManager$getRecipeFor0.invoke(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();
|
||||
List<Object> items = (List<Object>) Reflections.field$AbstractFurnaceBlockEntity$items.get(args[0]);
|
||||
ItemStack itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, items.get(0));
|
||||
|
||||
// it's a recipe from other plugins
|
||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, resourceLocation);
|
||||
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();
|
||||
}
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, resourceLocation);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(pair.getSecond()));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.minecraftRecipeManager();
|
||||
Object type = field$InjectedCacheChecker$recipeType.get(thisObj);
|
||||
Object lastRecipe = field$InjectedCacheChecker$lastRecipe.get(thisObj);
|
||||
Optional<Object> optionalRecipe = (Optional<Object>) Reflections.method$RecipeManager$getRecipeFor0.invoke(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
||||
if (optionalRecipe.isPresent()) {
|
||||
Object holder = optionalRecipe.get();
|
||||
Object id = Reflections.field$RecipeHolder$id.get(holder);
|
||||
Key recipeId = Key.of(id.toString());
|
||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||
List<Object> items = (List<Object>) Reflections.field$AbstractFurnaceBlockEntity$items.get(args[0]);
|
||||
ItemStack itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, items.get(0));
|
||||
|
||||
// it's a recipe from other plugins
|
||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, 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();
|
||||
}
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, id);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.minecraftRecipeManager();
|
||||
Object type = field$InjectedCacheChecker$recipeType.get(thisObj);
|
||||
Object lastRecipe = field$InjectedCacheChecker$lastRecipe.get(thisObj);
|
||||
Optional<Object> optionalRecipe = (Optional<Object>) Reflections.method$RecipeManager$getRecipeFor0.invoke(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
||||
if (optionalRecipe.isPresent()) {
|
||||
Object holder = optionalRecipe.get();
|
||||
Object id = Reflections.field$RecipeHolder$id.get(holder);
|
||||
Key recipeId = Key.of(id.toString());
|
||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||
ItemStack itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, Reflections.field$SingleRecipeInput$item.get(args[0]));
|
||||
|
||||
// it's a recipe from other plugins
|
||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, 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();
|
||||
}
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, id);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.minecraftRecipeManager();
|
||||
Object type = field$InjectedCacheChecker$recipeType.get(thisObj);
|
||||
Object lastRecipe = field$InjectedCacheChecker$lastRecipe.get(thisObj);
|
||||
Optional<Object> optionalRecipe = (Optional<Object>) Reflections.method$RecipeManager$getRecipeFor1.invoke(mcRecipeManager, type, args[0], args[1], lastRecipe);
|
||||
if (optionalRecipe.isPresent()) {
|
||||
Object holder = optionalRecipe.get();
|
||||
Object id = Reflections.field$RecipeHolder$id.get(holder);
|
||||
Object resourceLocation = Reflections.field$ResourceKey$location.get(id);
|
||||
Key recipeId = Key.of(resourceLocation.toString());
|
||||
BukkitRecipeManager recipeManager = BukkitRecipeManager.instance();
|
||||
ItemStack itemStack = (ItemStack) Reflections.method$CraftItemStack$asCraftMirror.invoke(null, Reflections.field$SingleRecipeInput$item.get(args[0]));
|
||||
|
||||
// it's a recipe from other plugins
|
||||
boolean isCustom = recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, 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();
|
||||
}
|
||||
|
||||
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
|
||||
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
|
||||
if (type == Reflections.instance$RecipeType$SMELTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMELTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$BLASTING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.BLASTING, input);
|
||||
} else if (type == Reflections.instance$RecipeType$SMOKING) {
|
||||
ceRecipe = (net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack>) recipeManager.getRecipe(RecipeTypes.SMOKING, input);
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
if (ceRecipe == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
// It doesn't matter at all
|
||||
field$InjectedCacheChecker$lastRecipe.set(thisObj, id);
|
||||
return Optional.of(Optional.ofNullable(recipeManager.getRecipeHolderByRecipe(ceRecipe)).orElse(holder));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class PalettedContainerMethodInterceptor {
|
||||
public static final PalettedContainerMethodInterceptor INSTANCE = new PalettedContainerMethodInterceptor();
|
||||
|
||||
|
||||
@@ -1711,6 +1711,41 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$BlockEntity = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.entity.BlockEntity"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.entity.TileEntity")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$AbstractFurnaceBlockEntity = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.entity.AbstractFurnaceBlockEntity"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.level.block.entity.TileEntityFurnace")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$ChunkAccess$blockEntities;
|
||||
|
||||
static {
|
||||
Field targetField = null;
|
||||
for (Field field : clazz$ChunkAccess.getDeclaredFields()) {
|
||||
if (Map.class.isAssignableFrom(field.getType())) {
|
||||
Type genericType = field.getGenericType();
|
||||
if (genericType instanceof ParameterizedType parameterizedType) {
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
if (actualTypeArguments.length == 2 &&
|
||||
actualTypeArguments[0].equals(clazz$BlockPos) &&
|
||||
actualTypeArguments[1].equals(clazz$BlockEntity)) {
|
||||
field.setAccessible(true);
|
||||
targetField = field;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
field$ChunkAccess$blockEntities = targetField;
|
||||
}
|
||||
|
||||
public static final Method method$LevelChunkSection$setBlockState = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$LevelChunkSection, clazz$BlockState, int.class, int.class, int.class, clazz$BlockState, boolean.class
|
||||
@@ -1816,6 +1851,13 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$RecipeType = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeType"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.Recipes")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Object instance$BuiltInRegistries$BLOCK;
|
||||
public static final Object instance$BuiltInRegistries$ITEM;
|
||||
public static final Object instance$BuiltInRegistries$ATTRIBUTE;
|
||||
@@ -1825,6 +1867,7 @@ public class Reflections {
|
||||
public static final Object instance$BuiltInRegistries$PARTICLE_TYPE;
|
||||
public static final Object instance$BuiltInRegistries$ENTITY_TYPE;
|
||||
public static final Object instance$BuiltInRegistries$FLUID;
|
||||
public static final Object instance$BuiltInRegistries$RECIPE_TYPE;
|
||||
public static final Object instance$InternalRegistries$DIMENSION_TYPE;
|
||||
|
||||
public static final Object instance$Registries$BLOCK;
|
||||
@@ -1835,8 +1878,9 @@ public class Reflections {
|
||||
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$DIMENSION_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$registryAccess;
|
||||
|
||||
@@ -1853,6 +1897,7 @@ public class Reflections {
|
||||
Object registries$EntityType = null;
|
||||
Object registries$Item = null;
|
||||
Object registries$Fluid = null;
|
||||
Object registries$RecipeType = null;
|
||||
for (Field field : fields) {
|
||||
Type fieldType = field.getGenericType();
|
||||
if (fieldType instanceof ParameterizedType paramType) {
|
||||
@@ -1866,6 +1911,8 @@ public class Reflections {
|
||||
registries$ParticleType = field.get(null);
|
||||
} else if (rawType == clazz$EntityType) {
|
||||
registries$EntityType = field.get(null);
|
||||
} else if (rawType == clazz$RecipeType) {
|
||||
registries$RecipeType = field.get(null);
|
||||
}
|
||||
} else {
|
||||
if (type == clazz$Block) {
|
||||
@@ -1900,6 +1947,7 @@ public class Reflections {
|
||||
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);
|
||||
Object server = method$MinecraftServer$getServer.invoke(null);
|
||||
Object registries = field$MinecraftServer$registries.get(server);
|
||||
instance$registryAccess = field$LayeredRegistryAccess$composite.get(registries);
|
||||
@@ -1913,6 +1961,7 @@ public class Reflections {
|
||||
instance$BuiltInRegistries$PARTICLE_TYPE = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$ParticleType);
|
||||
instance$BuiltInRegistries$ENTITY_TYPE = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$EntityType);
|
||||
instance$BuiltInRegistries$FLUID = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$Fluid);
|
||||
instance$BuiltInRegistries$RECIPE_TYPE = method$RegistryAccess$registryOrThrow.invoke(instance$registryAccess, registries$RecipeType);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -3359,6 +3408,28 @@ public class Reflections {
|
||||
}
|
||||
}
|
||||
|
||||
public static final Object instance$RecipeType$CRAFTING;
|
||||
public static final Object instance$RecipeType$SMELTING;
|
||||
public static final Object instance$RecipeType$BLASTING;
|
||||
public static final Object instance$RecipeType$SMOKING;
|
||||
public static final Object instance$RecipeType$CAMPFIRE_COOKING;
|
||||
public static final Object instance$RecipeType$STONECUTTING;
|
||||
public static final Object instance$RecipeType$SMITHING;
|
||||
|
||||
static {
|
||||
try {
|
||||
instance$RecipeType$CRAFTING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "crafting"));
|
||||
instance$RecipeType$SMELTING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "smelting"));
|
||||
instance$RecipeType$BLASTING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "blasting"));
|
||||
instance$RecipeType$SMOKING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "smoking"));
|
||||
instance$RecipeType$CAMPFIRE_COOKING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "campfire_cooking"));
|
||||
instance$RecipeType$STONECUTTING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "stonecutting"));
|
||||
instance$RecipeType$SMITHING = Reflections.method$Registry$get.invoke(Reflections.instance$BuiltInRegistries$RECIPE_TYPE, method$ResourceLocation$fromNamespaceAndPath.invoke(null, "minecraft", "smithing"));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static final Method method$BlockState$getShape = requireNonNull(
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$BlockStateBase, clazz$VoxelShape, new String[]{"getShape", "a"}, clazz$BlockGetter, clazz$BlockPos, clazz$CollisionContext
|
||||
@@ -3841,6 +3912,13 @@ public class Reflections {
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$RecipeManager$CachedCheck = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeManager$CachedCheck"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.CraftingManager$a")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Method method$RecipeManager$finalizeRecipeLoading =
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$RecipeManager, new String[]{"finalizeRecipeLoading"}
|
||||
@@ -4034,6 +4112,10 @@ public class Reflections {
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, 1))
|
||||
.orElse(null);
|
||||
|
||||
public static final Field field$RecipeHolder$id = Optional.ofNullable(clazz$RecipeHolder)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Class<?> clazz$ShapelessRecipe = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.ShapelessRecipe"),
|
||||
@@ -4175,7 +4257,8 @@ public class Reflections {
|
||||
// for 1.20.1-1.21.1
|
||||
public static final Class<?> clazz$AbstractCookingRecipe = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.AbstractCookingRecipe")
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.AbstractCookingRecipe"),
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeCooking")
|
||||
)
|
||||
);
|
||||
|
||||
@@ -4244,4 +4327,60 @@ public class Reflections {
|
||||
clazz$CraftCampfireRecipe, clazz$CraftCampfireRecipe, CampfireRecipe.class
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$AbstractFurnaceBlockEntity$recipeType = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$AbstractFurnaceBlockEntity, clazz$RecipeType, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$AbstractFurnaceBlockEntity$quickCheck = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$AbstractFurnaceBlockEntity, clazz$RecipeManager$CachedCheck, 0
|
||||
)
|
||||
);
|
||||
|
||||
// 1.21+
|
||||
public static final Class<?> clazz$RecipeInput = ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeInput")
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$SingleRecipeInput = ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleMCClass("world.item.crafting.SingleRecipeInput")
|
||||
);
|
||||
|
||||
// 1.20.1-1.21.1
|
||||
public static final Method method$RecipeManager$getRecipeFor0 =
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$RecipeManager, Optional.class, clazz$RecipeType, clazz$Container, clazz$Level, clazz$ResourceLocation
|
||||
);
|
||||
|
||||
// 1.21.2+
|
||||
public static final Method method$RecipeManager$getRecipeFor1 =
|
||||
ReflectionUtils.getMethod(
|
||||
clazz$RecipeManager, Optional.class, clazz$RecipeType, clazz$RecipeInput, clazz$Level, clazz$ResourceKey
|
||||
);
|
||||
|
||||
// 1.21+
|
||||
public static final Field field$SingleRecipeInput$item = Optional.ofNullable(clazz$SingleRecipeInput)
|
||||
.map(it -> ReflectionUtils.getDeclaredField(it, clazz$ItemStack, 0))
|
||||
.orElse(null);
|
||||
|
||||
public static final Field field$AbstractFurnaceBlockEntity$items = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$AbstractFurnaceBlockEntity, clazz$NonNullList, 0
|
||||
)
|
||||
);
|
||||
|
||||
public static final Class<?> clazz$CraftBlockEntityState = requireNonNull(
|
||||
ReflectionUtils.getClazz(
|
||||
BukkitReflectionUtils.assembleCBClass("block.CraftBlockEntityState")
|
||||
)
|
||||
);
|
||||
|
||||
public static final Field field$CraftBlockEntityState$tileEntity = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(
|
||||
clazz$CraftBlockEntityState, 0
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.BukkitInjector;
|
||||
import net.momirealms.craftengine.bukkit.util.Reflections;
|
||||
import net.momirealms.craftengine.core.block.ImmutableBlockState;
|
||||
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
|
||||
import net.momirealms.craftengine.core.plugin.scheduler.SchedulerTask;
|
||||
import net.momirealms.craftengine.core.world.CEWorld;
|
||||
import net.momirealms.craftengine.core.world.ChunkPos;
|
||||
@@ -268,6 +269,13 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
}
|
||||
BukkitInjector.injectLevelChunkSection(section, ceSection, ceWorld, new SectionPos(pos.x, ceChunk.sectionY(i), pos.z));
|
||||
}
|
||||
if (ConfigManager.enableRecipeSystem()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Object, Object> blockEntities = (Map<Object, Object>) Reflections.field$ChunkAccess$blockEntities.get(levelChunk);
|
||||
for (Object blockEntity : blockEntities.values()) {
|
||||
BukkitInjector.injectFurnaceBlockEntity(blockEntity);
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to restore chunk at " + chunk.getX() + " " + chunk.getZ(), e);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user