mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-27 10:59:07 +00:00
配方重构
This commit is contained in:
@@ -21,12 +21,12 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
private final Object item;
|
||||
private final Object clientItem;
|
||||
|
||||
public BukkitCustomItem(UniqueKey id, Object item, Object clientItem, Key materialKey, Key clientBoundMaterialKey,
|
||||
public BukkitCustomItem(boolean isVanillaItem, UniqueKey id, Object item, Object clientItem, Key materialKey, Key clientBoundMaterialKey,
|
||||
List<ItemBehavior> behaviors,
|
||||
List<ItemDataModifier<ItemStack>> modifiers, List<ItemDataModifier<ItemStack>> clientBoundModifiers,
|
||||
ItemSettings settings,
|
||||
Map<EventTrigger, List<Function<PlayerOptionalContext>>> events) {
|
||||
super(id, materialKey, clientBoundMaterialKey, behaviors, modifiers, clientBoundModifiers, settings, events);
|
||||
super(isVanillaItem, id, materialKey, clientBoundMaterialKey, behaviors, modifiers, clientBoundModifiers, settings, events);
|
||||
this.item = item;
|
||||
this.clientItem = clientItem;
|
||||
}
|
||||
@@ -64,6 +64,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
}
|
||||
|
||||
public static class BuilderImpl implements Builder<ItemStack> {
|
||||
private boolean isVanillaItem;
|
||||
private UniqueKey id;
|
||||
private Key itemKey;
|
||||
private final Object item;
|
||||
@@ -80,6 +81,12 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
this.clientBoundItem = clientBoundItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ItemStack> isVanillaItem(boolean is) {
|
||||
this.isVanillaItem = is;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder<ItemStack> id(UniqueKey id) {
|
||||
this.id = id;
|
||||
@@ -150,7 +157,7 @@ public class BukkitCustomItem extends AbstractCustomItem<ItemStack> {
|
||||
public CustomItem<ItemStack> build() {
|
||||
this.modifiers.addAll(this.settings.modifiers());
|
||||
this.clientBoundModifiers.addAll(this.settings.clientBoundModifiers());
|
||||
return new BukkitCustomItem(this.id, this.item, this.clientBoundItem, this.itemKey, this.clientBoundItemKey, List.copyOf(this.behaviors),
|
||||
return new BukkitCustomItem(this.isVanillaItem, this.id, this.item, this.clientBoundItem, this.itemKey, this.clientBoundItemKey, List.copyOf(this.behaviors),
|
||||
List.copyOf(this.modifiers), List.copyOf(this.clientBoundModifiers), this.settings, this.events);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.*;
|
||||
import net.momirealms.craftengine.core.item.modifier.IdModifier;
|
||||
import net.momirealms.craftengine.core.item.recipe.DatapackRecipeResult;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.pack.AbstractPackManager;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
@@ -70,10 +70,9 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
this.bedrockItemHolder = FastNMS.INSTANCE.method$Registry$getHolderByResourceKey(MBuiltInRegistries.ITEM, FastNMS.INSTANCE.method$ResourceKey$create(MRegistries.ITEM, KeyUtils.toResourceLocation(Key.of("minecraft:bedrock")))).get();
|
||||
this.registerCustomTrimMaterial();
|
||||
this.loadLastRegisteredPatterns();
|
||||
|
||||
ItemStack emptyStack = FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(CoreReflections.instance$ItemStack$EMPTY);
|
||||
this.emptyItem = this.wrap(emptyStack);
|
||||
this.emptyUniqueItem = new UniqueIdItem<>(UniqueKey.AIR, this.emptyItem);
|
||||
this.emptyItem = this.factory.wrap(emptyStack);
|
||||
this.emptyUniqueItem = UniqueIdItem.of(this.emptyItem);
|
||||
this.decoratedHashOpsGenerator = VersionHelper.isOrAbove1_21_5() ? (Function<Object, Integer>) FastNMS.INSTANCE.createDecoratedHashOpsGenerator(MRegistryOps.HASHCODE) : null;
|
||||
}
|
||||
|
||||
@@ -158,13 +157,33 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> build(DatapackRecipeResult result) {
|
||||
if (result.components() == null) {
|
||||
ItemStack itemStack = createVanillaItemStack(Key.of(result.id()));
|
||||
return wrap(itemStack).count(result.count());
|
||||
} else {
|
||||
// 低版本无法应用nbt或组件,所以这里是1.20.5+
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("id", result.id());
|
||||
jsonObject.addProperty("count", result.count());
|
||||
jsonObject.add("components", result.components());
|
||||
Object nmsStack = CoreReflections.instance$ItemStack$CODEC.parse(MRegistryOps.JSON, jsonObject)
|
||||
.resultOrPartial((itemId) -> plugin.logger().severe("Tried to load invalid item: '" + itemId + "'")).orElse(null);
|
||||
if (nmsStack == null) {
|
||||
return this.emptyItem;
|
||||
}
|
||||
return wrap(FastNMS.INSTANCE.method$CraftItemStack$asCraftMirror(nmsStack));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<BuildableItem<ItemStack>> getVanillaItem(Key key) {
|
||||
ItemStack vanilla = createVanillaItemStack(key);
|
||||
if (vanilla == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new CloneableConstantItem(key, this.wrap(vanilla)));
|
||||
return Optional.of(CloneableConstantItem.of(this.wrap(vanilla)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -356,23 +375,10 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
|
||||
@Override
|
||||
public @NotNull Item<ItemStack> wrap(ItemStack itemStack) {
|
||||
if (itemStack == null) return this.emptyItem;
|
||||
if (itemStack == null || itemStack.isEmpty()) return this.emptyItem;
|
||||
return this.factory.wrap(itemStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key itemId(ItemStack itemStack) {
|
||||
Item<ItemStack> wrapped = wrap(itemStack);
|
||||
return wrapped.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key customItemId(ItemStack itemStack) {
|
||||
Item<ItemStack> wrapped = wrap(itemStack);
|
||||
if (!wrapped.hasTag(IdModifier.CRAFT_ENGINE_ID)) return null;
|
||||
return wrapped.id();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CustomItem.Builder<ItemStack> createPlatformItemBuilder(UniqueKey id, Key materialId, Key clientBoundMaterialId) {
|
||||
Object item = FastNMS.INSTANCE.method$Registry$getValue(MBuiltInRegistries.ITEM, KeyUtils.toResourceLocation(materialId));
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.item;
|
||||
|
||||
import net.momirealms.craftengine.core.item.BuildableItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class CloneableConstantItem implements BuildableItem<ItemStack> {
|
||||
private final Item<ItemStack> item;
|
||||
private final Key id;
|
||||
|
||||
public CloneableConstantItem(Key id, Item<ItemStack> item) {
|
||||
this.item = item;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Key id() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Item<ItemStack> buildItem(ItemBuildContext context, int count) {
|
||||
return this.item.copyWithCount(count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack buildItemStack(ItemBuildContext context, int count) {
|
||||
return this.item.copyWithCount(count).getItem();
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import net.momirealms.craftengine.bukkit.util.ItemTags;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.item.ExternalItemSource;
|
||||
import net.momirealms.craftengine.core.item.ItemFactory;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.ItemWrapper;
|
||||
import net.momirealms.craftengine.core.item.data.JukeboxPlayable;
|
||||
import net.momirealms.craftengine.core.item.setting.EquipmentData;
|
||||
@@ -66,6 +65,11 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEmpty(W item) {
|
||||
return FastNMS.INSTANCE.method$ItemStack$isEmpty(item.getLiteralObject());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
protected byte[] toByteArray(W item) {
|
||||
@@ -80,12 +84,15 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
@Override
|
||||
protected Key vanillaId(W item) {
|
||||
Object i = FastNMS.INSTANCE.method$ItemStack$getItem(item.getLiteralObject());
|
||||
if (i == null) return ItemKeys.AIR;
|
||||
if (i == null) return null;
|
||||
return KeyUtils.resourceLocationToKey(FastNMS.INSTANCE.method$Registry$getKey(MBuiltInRegistries.ITEM, i));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Key id(W item) {
|
||||
if (FastNMS.INSTANCE.method$ItemStack$isEmpty(item.getLiteralObject())) {
|
||||
return null;
|
||||
}
|
||||
return customId(item).orElse(vanillaId(item));
|
||||
}
|
||||
|
||||
@@ -96,6 +103,9 @@ public abstract class BukkitItemFactory<W extends ItemWrapper<ItemStack>> extend
|
||||
|
||||
@Override
|
||||
protected UniqueKey recipeIngredientID(W item) {
|
||||
if (FastNMS.INSTANCE.method$ItemStack$isEmpty(item.getLiteralObject())) {
|
||||
return null;
|
||||
}
|
||||
if (this.hasExternalRecipeSource) {
|
||||
for (ExternalItemSource<ItemStack> source : this.recipeIngredientSources) {
|
||||
String id = source.id(item.getItem());
|
||||
|
||||
@@ -31,11 +31,6 @@ public class ComponentItemFactory1_20_5 extends BukkitItemFactory<ComponentItemW
|
||||
super(plugin);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEmpty(ComponentItemWrapper item) {
|
||||
return item.getItem().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void customId(ComponentItemWrapper item, Key id) {
|
||||
FastNMS.INSTANCE.setCustomItemId(item.getLiteralObject(), id.toString());
|
||||
|
||||
@@ -67,11 +67,6 @@ public class UniversalItemFactory extends BukkitItemFactory<LegacyItemWrapper> {
|
||||
return item.remove(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEmpty(LegacyItemWrapper item) {
|
||||
return item.getItem().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<Key> customId(LegacyItemWrapper item) {
|
||||
Object id = item.getJavaTag(IdModifier.CRAFT_ENGINE_ID);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
||||
package net.momirealms.craftengine.bukkit.item.recipe;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.util.ItemStackUtils;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.ItemManager;
|
||||
import net.momirealms.craftengine.core.item.recipe.Recipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeType;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.block.Crafter;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.CrafterCraftEvent;
|
||||
import org.bukkit.inventory.CraftingRecipe;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CrafterEventListener implements Listener {
|
||||
private final ItemManager<ItemStack> itemManager;
|
||||
private final BukkitRecipeManager recipeManager;
|
||||
private final BukkitCraftEngine plugin;
|
||||
|
||||
public CrafterEventListener(BukkitCraftEngine plugin, BukkitRecipeManager recipeManager, ItemManager<ItemStack> itemManager) {
|
||||
this.itemManager = itemManager;
|
||||
this.recipeManager = recipeManager;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCrafting(CrafterCraftEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
CraftingRecipe recipe = event.getRecipe();
|
||||
if (!(event.getBlock().getState() instanceof Crafter crafter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory inventory = crafter.getInventory();
|
||||
ItemStack[] ingredients = inventory.getStorageContents();
|
||||
|
||||
List<UniqueIdItem<ItemStack>> uniqueIdItems = new ArrayList<>();
|
||||
for (ItemStack itemStack : ingredients) {
|
||||
if (ItemStackUtils.isEmpty(itemStack)) {
|
||||
uniqueIdItems.add(this.itemManager.uniqueEmptyItem());
|
||||
} else {
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
|
||||
uniqueIdItems.add(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
}
|
||||
}
|
||||
|
||||
CraftingInput<ItemStack> input;
|
||||
if (ingredients.length == 9) {
|
||||
input = CraftingInput.of(3, 3, uniqueIdItems);
|
||||
} else if (ingredients.length == 4) {
|
||||
input = CraftingInput.of(2, 2, uniqueIdItems);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeType.CRAFTING, input);
|
||||
if (ceRecipe != null) {
|
||||
event.setResult(ceRecipe.assemble(input, ItemBuildContext.EMPTY));
|
||||
return;
|
||||
}
|
||||
// clear result if not met
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,9 @@ import com.destroystokyo.paper.event.inventory.PrepareResultEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine;
|
||||
import net.momirealms.craftengine.bukkit.plugin.injector.RecipeInjector;
|
||||
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.MRecipeTypes;
|
||||
import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
|
||||
import net.momirealms.craftengine.bukkit.util.ComponentUtils;
|
||||
import net.momirealms.craftengine.bukkit.util.InventoryUtils;
|
||||
@@ -28,21 +25,14 @@ import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.context.ContextHolder;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Campfire;
|
||||
import org.bukkit.block.Furnace;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.*;
|
||||
import org.bukkit.event.inventory.*;
|
||||
import org.bukkit.event.inventory.ClickType;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.*;
|
||||
import org.bukkit.inventory.view.AnvilView;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -74,7 +64,7 @@ public class RecipeEventListener implements Listener {
|
||||
ItemStack item = event.getCurrentItem();
|
||||
if (ItemStackUtils.isEmpty(item)) return;
|
||||
if (ItemStackUtils.isEmpty(fuelStack)) {
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(item));
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(ItemStackUtils.getUniqueIdItem(item));
|
||||
RecipeType recipeType;
|
||||
if (furnaceInventory.getType() == InventoryType.FURNACE) {
|
||||
recipeType = RecipeType.SMELTING;
|
||||
@@ -258,166 +248,9 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onFurnaceInventoryOpen(InventoryOpenEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!(event.getInventory() instanceof FurnaceInventory furnaceInventory)) {
|
||||
return;
|
||||
}
|
||||
Furnace furnace = furnaceInventory.getHolder();
|
||||
try {
|
||||
Object blockEntity = CraftBukkitReflections.field$CraftBlockEntityState$tileEntity.get(furnace);
|
||||
RecipeInjector.injectCookingBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
|
||||
// for 1.20.1-1.21.1
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onBlockIgnite(BlockIgniteEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (VersionHelper.isOrAbove1_21_2()) return;
|
||||
Block block = event.getBlock();
|
||||
Material material = block.getType();
|
||||
if (material == Material.CAMPFIRE) {
|
||||
if (block.getState() instanceof Campfire campfire) {
|
||||
try {
|
||||
Object blockEntity = CraftBukkitReflections.field$CraftBlockEntityState$tileEntity.get(campfire);
|
||||
RecipeInjector.injectCookingBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||
public void onPlaceBlock(BlockPlaceEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
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 = CraftBukkitReflections.field$CraftBlockEntityState$tileEntity.get(furnace);
|
||||
RecipeInjector.injectCookingBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
} else if (!VersionHelper.isOrAbove1_21_2() && material == Material.CAMPFIRE) {
|
||||
if (block.getState() instanceof Campfire campfire) {
|
||||
try {
|
||||
Object blockEntity = CraftBukkitReflections.field$CraftBlockEntityState$tileEntity.get(campfire);
|
||||
RecipeInjector.injectCookingBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for 1.21.2+
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onPutItemOnCampfire(PlayerInteractEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
Block clicked = event.getClickedBlock();
|
||||
if (clicked == null) return;
|
||||
Material type = clicked.getType();
|
||||
if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return;
|
||||
if (clicked.getState() instanceof Campfire campfire) {
|
||||
try {
|
||||
Object blockEntity = CraftBukkitReflections.field$CraftBlockEntityState$tileEntity.get(campfire);
|
||||
RecipeInjector.injectCookingBlockEntity(blockEntity);
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to inject cooking block entity", e);
|
||||
}
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getItem();
|
||||
if (ItemStackUtils.isEmpty(itemStack)) return;
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Optional<Object> optionalMCRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(
|
||||
BukkitRecipeManager.minecraftRecipeManager(),
|
||||
MRecipeTypes.CAMPFIRE_COOKING,
|
||||
CoreReflections.constructor$SingleRecipeInput.newInstance(FastNMS.INSTANCE.method$CraftItemStack$asNMSCopy(itemStack)),
|
||||
FastNMS.INSTANCE.field$CraftWorld$ServerLevel(event.getPlayer().getWorld()),
|
||||
null
|
||||
);
|
||||
if (optionalMCRecipe.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(itemStack));
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.recipeByInput(RecipeType.CAMPFIRE_COOKING, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to handle interact campfire", e);
|
||||
}
|
||||
}
|
||||
|
||||
// for 1.21.2+
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onCampfireCook(CampfireStartEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
CampfireRecipe recipe = event.getRecipe();
|
||||
Key recipeId = new Key(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getSource();
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(itemStack));
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.recipeByInput(RecipeType.CAMPFIRE_COOKING, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setTotalCookTime(Integer.MAX_VALUE);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setTotalCookTime(ceRecipe.cookingTime());
|
||||
}
|
||||
|
||||
// for 1.21.2+
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onCampfireCook(BlockCookEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
if (!VersionHelper.isOrAbove1_21_2()) return;
|
||||
Material type = event.getBlock().getType();
|
||||
if (type != Material.CAMPFIRE && type != Material.SOUL_CAMPFIRE) return;
|
||||
CampfireRecipe recipe = (CampfireRecipe) event.getRecipe();
|
||||
if (recipe == null) return;
|
||||
|
||||
Key recipeId = new Key(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
if (!isCustom) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack itemStack = event.getSource();
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(getUniqueIdItem(itemStack));
|
||||
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.recipeByInput(RecipeType.CAMPFIRE_COOKING, input);
|
||||
if (ceRecipe == null) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setResult(ceRecipe.result(ItemBuildContext.EMPTY));
|
||||
}
|
||||
|
||||
// Paper only
|
||||
@EventHandler
|
||||
public void onPrepareResult(PrepareResultEvent event) {
|
||||
// if (!ConfigManager.enableRecipeSystem()) return;
|
||||
if (event.getInventory() instanceof CartographyInventory cartographyInventory) {
|
||||
if (ItemStackUtils.hasCustomItem(cartographyInventory.getStorageContents())) {
|
||||
event.setResult(new ItemStack(Material.AIR));
|
||||
@@ -745,98 +578,35 @@ public class RecipeEventListener implements Listener {
|
||||
return new Pair<>(first, second);
|
||||
}
|
||||
|
||||
// 不是完美的解决方案,仍然需要更多的探讨
|
||||
// TODO 生成类代理掉ResultSlot,并注入menu的slots对象,修改掉onTake方法
|
||||
// TODO 对于耐久度降低的配方,应该注册special recipe?
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onCraft(CraftItemEvent event) {
|
||||
org.bukkit.inventory.Recipe recipe = event.getRecipe();
|
||||
if (!(recipe instanceof ShapelessRecipe) && !(recipe instanceof ShapedRecipe)) return;
|
||||
HumanEntity humanEntity = event.getWhoClicked();
|
||||
if (!(humanEntity instanceof Player player)) return;
|
||||
CraftingInventory inventory = event.getInventory();
|
||||
ItemStack result = inventory.getResult();
|
||||
if (result == null) return;
|
||||
ItemStack[] usedItems = inventory.getMatrix();
|
||||
ItemStack[] replacements = new ItemStack[usedItems.length];
|
||||
boolean hasReplacement = false;
|
||||
for (int i = 0; i < usedItems.length; i++) {
|
||||
ItemStack usedItem = usedItems[i];
|
||||
if (ItemStackUtils.isEmpty(usedItem)) continue;
|
||||
if (usedItem.getAmount() != 1) continue;
|
||||
Item<ItemStack> wrapped = BukkitItemManager.instance().wrap(usedItem);
|
||||
if (ItemUtils.isEmpty(wrapped)) continue;
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = wrapped.getCustomItem();
|
||||
if (optionalCustomItem.isPresent()) {
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
Key remainingItem = customItem.settings().craftRemainder();
|
||||
if (remainingItem != null) {
|
||||
replacements[i] = BukkitItemManager.instance().buildItemStack(remainingItem, this.plugin.adapt(player));
|
||||
hasReplacement = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasReplacement) return;
|
||||
Runnable delayedTask = () -> {
|
||||
for (int i = 0; i < replacements.length; i++) {
|
||||
if (replacements[i] == null) continue;
|
||||
inventory.setItem(i + 1, replacements[i]);
|
||||
}
|
||||
};
|
||||
if (VersionHelper.isFolia()) {
|
||||
player.getScheduler().run(this.plugin.javaPlugin(), (t) -> delayedTask.run(), () -> {});
|
||||
} else {
|
||||
this.plugin.scheduler().sync().runDelayed(delayedTask);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onCraftingRecipe(PrepareItemCraftEvent event) {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
org.bukkit.inventory.Recipe recipe = event.getRecipe();
|
||||
|
||||
// we only handle shaped and shapeless recipes
|
||||
boolean shapeless = recipe instanceof ShapelessRecipe;
|
||||
boolean shaped = recipe instanceof ShapedRecipe;
|
||||
if (!shaped && !shapeless) return;
|
||||
|
||||
CraftingRecipe craftingRecipe = (CraftingRecipe) recipe;
|
||||
if (!(recipe instanceof CraftingRecipe craftingRecipe)) return;
|
||||
Key recipeId = Key.of(craftingRecipe.getKey().namespace(), craftingRecipe.getKey().value());
|
||||
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
Optional<Recipe<ItemStack>> optionalRecipe = this.recipeManager.recipeById(recipeId);
|
||||
// 也许是其他插件注册的配方,直接无视
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
CraftingInventory inventory = event.getInventory();
|
||||
if (!(optionalRecipe.get() instanceof CustomCraftingTableRecipe<ItemStack> craftingTableRecipe)) {
|
||||
inventory.setResult(null);
|
||||
return;
|
||||
}
|
||||
CraftingInput<ItemStack> input = getCraftingInput(inventory);
|
||||
if (input == null) return;
|
||||
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(player);
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeType.CRAFTING, input, recipeId);
|
||||
if (ceRecipe != null) {
|
||||
inventory.setResult(ceRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
serverPlayer.setLastUsedRecipe(ceRecipe.id());
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctCraftingRecipeUsed(inventory, ceRecipe);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// clear result if not met
|
||||
inventory.setResult(null);
|
||||
inventory.setResult(craftingTableRecipe.assemble(input, new ItemBuildContext(serverPlayer, ContextHolder.EMPTY)));
|
||||
}
|
||||
|
||||
private CraftingInput<ItemStack> getCraftingInput(CraftingInventory inventory) {
|
||||
ItemStack[] ingredients = inventory.getMatrix();
|
||||
|
||||
List<UniqueIdItem<ItemStack>> uniqueIdItems = new ArrayList<>();
|
||||
for (ItemStack itemStack : ingredients) {
|
||||
uniqueIdItems.add(getUniqueIdItem(itemStack));
|
||||
uniqueIdItems.add(ItemStackUtils.getUniqueIdItem(itemStack));
|
||||
}
|
||||
|
||||
CraftingInput<ItemStack> input;
|
||||
if (ingredients.length == 9) {
|
||||
input = CraftingInput.of(3, 3, uniqueIdItems);
|
||||
@@ -848,17 +618,6 @@ public class RecipeEventListener implements Listener {
|
||||
return input;
|
||||
}
|
||||
|
||||
private void correctCraftingRecipeUsed(CraftingInventory inventory, Recipe<ItemStack> recipe) {
|
||||
Object holderOrRecipe = this.recipeManager.nmsRecipeHolderByRecipe(recipe);
|
||||
if (holderOrRecipe == null) {
|
||||
return;
|
||||
}
|
||||
Object resultInventory = FastNMS.INSTANCE.method$CraftInventoryCrafting$getResultInventory(inventory);
|
||||
FastNMS.INSTANCE.method$ResultContainer$setRecipeUsed(resultInventory, holderOrRecipe);
|
||||
Object matrixInventory = FastNMS.INSTANCE.method$CraftInventoryCrafting$getMatrixInventory(inventory);
|
||||
FastNMS.INSTANCE.method$CraftingContainer$setCurrentRecipe(matrixInventory, holderOrRecipe);
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onSmithingTrim(PrepareSmithingEvent event) {
|
||||
SmithingInventory inventory = event.getInventory();
|
||||
@@ -880,31 +639,17 @@ public class RecipeEventListener implements Listener {
|
||||
}
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
Optional<Recipe<ItemStack>> optionalRecipe = this.recipeManager.recipeById(recipeId);
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SmithingInput<ItemStack> input = new SmithingInput<>(
|
||||
getUniqueIdItem(inventory.getInputEquipment()),
|
||||
getUniqueIdItem(inventory.getInputTemplate()),
|
||||
getUniqueIdItem(inventory.getInputMineral())
|
||||
);
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeType.SMITHING, input, recipeId);
|
||||
if (ceRecipe == null) {
|
||||
if (!(optionalRecipe.get() instanceof CustomSmithingTrimRecipe<ItemStack> smithingTrimRecipe)) {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
CustomSmithingTrimRecipe<ItemStack> trimRecipe = (CustomSmithingTrimRecipe<ItemStack>) ceRecipe;
|
||||
ItemStack result = trimRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
ItemStack result = smithingTrimRecipe.assemble(getSmithingInput(inventory), new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
event.setResult(result);
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
@@ -912,59 +657,25 @@ public class RecipeEventListener implements Listener {
|
||||
if (!Config.enableRecipeSystem()) return;
|
||||
SmithingInventory inventory = event.getInventory();
|
||||
if (!(inventory.getRecipe() instanceof SmithingTransformRecipe recipe)) return;
|
||||
|
||||
Key recipeId = Key.of(recipe.getKey().namespace(), recipe.getKey().value());
|
||||
boolean isCustom = this.recipeManager.isCustomRecipe(recipeId);
|
||||
// Maybe it's recipe from other plugins, then we ignore it
|
||||
if (!isCustom) {
|
||||
Optional<Recipe<ItemStack>> optionalRecipe = this.recipeManager.recipeById(recipeId);
|
||||
if (optionalRecipe.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack base = inventory.getInputEquipment();
|
||||
ItemStack template = inventory.getInputTemplate();
|
||||
ItemStack addition = inventory.getInputMineral();
|
||||
|
||||
SmithingInput<ItemStack> input = new SmithingInput<>(
|
||||
getUniqueIdItem(base),
|
||||
getUniqueIdItem(template),
|
||||
getUniqueIdItem(addition)
|
||||
);
|
||||
|
||||
Recipe<ItemStack> ceRecipe = this.recipeManager.recipeByInput(RecipeType.SMITHING, input, recipeId);
|
||||
if (ceRecipe == null) {
|
||||
if (!(optionalRecipe.get() instanceof CustomSmithingTransformRecipe<ItemStack> smithingTransformRecipe)) {
|
||||
event.setResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = InventoryUtils.getPlayerFromInventoryEvent(event);
|
||||
|
||||
CustomSmithingTransformRecipe<ItemStack> transformRecipe = (CustomSmithingTransformRecipe<ItemStack>) ceRecipe;
|
||||
ItemStack processed = transformRecipe.assemble(input, new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
ItemStack processed = smithingTransformRecipe.assemble(getSmithingInput(inventory), new ItemBuildContext(this.plugin.adapt(player), ContextHolder.EMPTY));
|
||||
event.setResult(processed);
|
||||
if (!ceRecipe.id().equals(recipeId)) {
|
||||
correctSmithingRecipeUsed(inventory, ceRecipe);
|
||||
}
|
||||
}
|
||||
|
||||
private void correctSmithingRecipeUsed(SmithingInventory inventory, Recipe<ItemStack> recipe) {
|
||||
Object holderOrRecipe = this.recipeManager.nmsRecipeHolderByRecipe(recipe);
|
||||
if (holderOrRecipe == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Object resultInventory = CraftBukkitReflections.field$CraftResultInventory$resultInventory.get(inventory);
|
||||
CoreReflections.field$ResultContainer$recipeUsed.set(resultInventory, holderOrRecipe);
|
||||
} catch (ReflectiveOperationException e) {
|
||||
this.plugin.logger().warn("Failed to correct used recipe", e);
|
||||
}
|
||||
}
|
||||
|
||||
private UniqueIdItem<ItemStack> getUniqueIdItem(@Nullable ItemStack itemStack) {
|
||||
if (ItemStackUtils.isEmpty(itemStack)) {
|
||||
return this.itemManager.uniqueEmptyItem();
|
||||
} else {
|
||||
Item<ItemStack> wrappedItem = this.itemManager.wrap(itemStack);
|
||||
return new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem);
|
||||
}
|
||||
private SmithingInput<ItemStack> getSmithingInput(SmithingInventory inventory) {
|
||||
return new SmithingInput<>(
|
||||
ItemStackUtils.getUniqueIdItem(inventory.getInputEquipment()),
|
||||
ItemStackUtils.getUniqueIdItem(inventory.getInputTemplate()),
|
||||
ItemStackUtils.getUniqueIdItem(inventory.getInputMineral())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,28 +60,12 @@ public class BukkitPackManager extends AbstractPackManager implements Listener {
|
||||
@Override
|
||||
public void unload() {
|
||||
super.unload();
|
||||
if (ReloadCommand.RELOAD_PACK_FLAG) {
|
||||
if (VersionHelper.isOrAbove1_20_2()) {
|
||||
this.resetServerSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disable() {
|
||||
super.disable();
|
||||
HandlerList.unregisterAll(this);
|
||||
this.resetServerSettings();
|
||||
}
|
||||
|
||||
public void resetServerSettings() {
|
||||
try {
|
||||
Object settings = CoreReflections.field$DedicatedServer$settings.get(CoreReflections.method$MinecraftServer$getServer.invoke(null));
|
||||
Object properties = CoreReflections.field$DedicatedServerSettings$properties.get(settings);
|
||||
CoreReflections.field$DedicatedServerProperties$serverResourcePackInfo.set(properties, Optional.empty());
|
||||
} catch (Exception e) {
|
||||
this.plugin.logger().warn("Failed to reset resource pack settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
|
||||
@@ -6,32 +6,22 @@ import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.bytebuddy.ByteBuddy;
|
||||
import net.bytebuddy.ClassFileVersion;
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.description.modifier.Visibility;
|
||||
import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy;
|
||||
import net.bytebuddy.implementation.FieldAccessor;
|
||||
import net.bytebuddy.implementation.MethodDelegation;
|
||||
import net.bytebuddy.implementation.bind.annotation.AllArguments;
|
||||
import net.bytebuddy.implementation.bind.annotation.RuntimeType;
|
||||
import net.bytebuddy.implementation.bind.annotation.This;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import net.bytebuddy.matcher.ElementMatchers;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.ComponentTypes;
|
||||
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.ItemTags;
|
||||
import net.momirealms.craftengine.bukkit.util.KeyUtils;
|
||||
import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.data.FireworkExplosion;
|
||||
import net.momirealms.craftengine.core.item.recipe.CustomCookingRecipe;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeType;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -46,43 +36,13 @@ import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class RecipeInjector {
|
||||
private static Class<?> clazz$InjectedCacheChecker;
|
||||
private static Class<?> clazz$InjectedArmorDyeRecipe;
|
||||
private static Class<?> clazz$InjectedRepairItemRecipe;
|
||||
private static Class<?> clazz$InjectedFireworkStarFadeRecipe;
|
||||
|
||||
public static void init() {
|
||||
ByteBuddy byteBuddy = new ByteBuddy(ClassFileVersion.JAVA_V17);
|
||||
clazz$InjectedCacheChecker = byteBuddy
|
||||
.subclass(Object.class, ConstructorStrategy.Default.IMITATE_SUPER_CLASS_OPENING)
|
||||
.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", RecipeType.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"))
|
||||
.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() ?
|
||||
GetRecipeForMethodInterceptor1_21_2.INSTANCE :
|
||||
(VersionHelper.isOrAbove1_21() ?
|
||||
GetRecipeForMethodInterceptor1_21.INSTANCE :
|
||||
VersionHelper.isOrAbove1_20_5() ?
|
||||
GetRecipeForMethodInterceptor1_20_5.INSTANCE :
|
||||
GetRecipeForMethodInterceptor1_20.INSTANCE)
|
||||
))
|
||||
.make()
|
||||
.load(RecipeInjector.class.getClassLoader())
|
||||
.getLoaded();
|
||||
|
||||
ElementMatcher.Junction<MethodDescription> matches = (VersionHelper.isOrAbove1_21() ?
|
||||
ElementMatchers.takesArguments(CoreReflections.clazz$CraftingInput, CoreReflections.clazz$Level) :
|
||||
ElementMatchers.takesArguments(CoreReflections.clazz$CraftingContainer, CoreReflections.clazz$Level)
|
||||
@@ -151,35 +111,6 @@ public class RecipeInjector {
|
||||
}
|
||||
}
|
||||
|
||||
public static void injectCookingBlockEntity(Object entity) throws ReflectiveOperationException {
|
||||
if (CoreReflections.clazz$AbstractFurnaceBlockEntity.isInstance(entity)) {
|
||||
Object quickCheck = CoreReflections.field$AbstractFurnaceBlockEntity$quickCheck.get(entity);
|
||||
if (clazz$InjectedCacheChecker.isInstance(quickCheck)) return; // already injected
|
||||
Object recipeType = FastNMS.INSTANCE.field$AbstractFurnaceBlockEntity$recipeType(entity);
|
||||
InjectedCacheCheck injectedChecker = (InjectedCacheCheck) ReflectionUtils.UNSAFE.allocateInstance(clazz$InjectedCacheChecker);
|
||||
if (recipeType == MRecipeTypes.SMELTING) {
|
||||
injectedChecker.customRecipeType(RecipeType.SMELTING);
|
||||
injectedChecker.recipeType(MRecipeTypes.SMELTING);
|
||||
} else if (recipeType == MRecipeTypes.BLASTING) {
|
||||
injectedChecker.customRecipeType(RecipeType.BLASTING);
|
||||
injectedChecker.recipeType(MRecipeTypes.BLASTING);
|
||||
} else if (recipeType == MRecipeTypes.SMOKING) {
|
||||
injectedChecker.customRecipeType(RecipeType.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(RecipeType.CAMPFIRE_COOKING);
|
||||
injectedChecker.recipeType(MRecipeTypes.CAMPFIRE_COOKING);
|
||||
CoreReflections.field$CampfireBlockEntity$quickCheck.set(entity, injectedChecker);
|
||||
}
|
||||
}
|
||||
|
||||
private static final Function<Object, Integer> INGREDIENT_SIZE_GETTER =
|
||||
VersionHelper.isOrAbove1_21() ?
|
||||
FastNMS.INSTANCE::method$CraftingInput$size :
|
||||
@@ -471,185 +402,4 @@ public class RecipeInjector {
|
||||
private static boolean isVanillaDyeItem(Item<ItemStack> item) {
|
||||
return CoreReflections.clazz$DyeItem.isInstance(FastNMS.INSTANCE.method$ItemStack$getItem(item.getLiteralObject()));
|
||||
}
|
||||
|
||||
@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) {
|
||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||
Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe();
|
||||
Optional<Pair<Object, Object>> optionalRecipe = FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.minecraftRecipeManager(), 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);
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
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_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) {
|
||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||
Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe();
|
||||
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.minecraftRecipeManager(), 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);
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
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) {
|
||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||
Object lastRecipeResourceLocation = injectedCacheCheck.lastRecipe();
|
||||
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.minecraftRecipeManager(), 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);
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
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) {
|
||||
InjectedCacheCheck injectedCacheCheck = (InjectedCacheCheck) thisObj;
|
||||
Object lastRecipeResourceKey = injectedCacheCheck.lastRecipe();
|
||||
Optional<Object> optionalRecipe = (Optional<Object>) FastNMS.INSTANCE.method$RecipeManager$getRecipeFor(BukkitRecipeManager.minecraftRecipeManager(), 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);
|
||||
SingleItemInput<ItemStack> input = new SingleItemInput<>(new UniqueIdItem<>(wrappedItem.recipeIngredientId(), wrappedItem));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ public class BukkitNetworkManager implements NetworkManager, Listener, PluginMes
|
||||
this.plugin.javaPlugin().getServer().getMessenger().registerOutgoingPluginChannel(this.plugin.javaPlugin(), MOD_CHANNEL);
|
||||
// Inject server channel
|
||||
try {
|
||||
Object server = CoreReflections.method$MinecraftServer$getServer.invoke(null);
|
||||
Object server = FastNMS.INSTANCE.method$MinecraftServer$getServer();
|
||||
Object serverConnection = CoreReflections.field$MinecraftServer$connection.get(server);
|
||||
@SuppressWarnings("unchecked")
|
||||
List<ChannelFuture> channels = (List<ChannelFuture>) CoreReflections.field$ServerConnectionListener$channels.get(serverConnection);
|
||||
|
||||
@@ -2849,10 +2849,6 @@ public final class CoreReflections {
|
||||
ReflectionUtils.getClazz(BukkitReflectionUtils.assembleMCClass("server.MinecraftServer"))
|
||||
);
|
||||
|
||||
public static final Method method$MinecraftServer$getServer = requireNonNull(
|
||||
ReflectionUtils.getMethod(clazz$MinecraftServer, new String[] { "getServer" })
|
||||
);
|
||||
|
||||
public static final Field field$MinecraftServer$registries = requireNonNull(
|
||||
ReflectionUtils.getDeclaredField(clazz$MinecraftServer, clazz$LayeredRegistryAccess, 0)
|
||||
);
|
||||
|
||||
@@ -93,8 +93,6 @@ public class BukkitServerPlayer extends Player {
|
||||
// for client visual sync
|
||||
private int resentSoundTick;
|
||||
private int resentSwingTick;
|
||||
// cache used recipe
|
||||
private Key lastUsedRecipe = null;
|
||||
// has fabric client mod or not
|
||||
private boolean hasClientMod = false;
|
||||
// cache if player can break blocks
|
||||
@@ -885,14 +883,6 @@ public class BukkitServerPlayer extends Player {
|
||||
return resentSwingTick == gameTicks();
|
||||
}
|
||||
|
||||
public Key lastUsedRecipe() {
|
||||
return lastUsedRecipe;
|
||||
}
|
||||
|
||||
public void setLastUsedRecipe(Key lastUsedRecipe) {
|
||||
this.lastUsedRecipe = lastUsedRecipe;
|
||||
}
|
||||
|
||||
public boolean clientModEnabled() {
|
||||
return this.hasClientMod;
|
||||
}
|
||||
|
||||
@@ -129,15 +129,11 @@ public class InteractUtils {
|
||||
});
|
||||
registerInteraction(BlockKeys.SOUL_CAMPFIRE, (player, item, blockState, result) -> {
|
||||
if (!Config.enableRecipeSystem()) return false;
|
||||
return BukkitRecipeManager.instance().recipeByInput(RecipeType.CAMPFIRE_COOKING, new SingleItemInput<>(new UniqueIdItem<>(
|
||||
item.recipeIngredientId(), item
|
||||
))) != null;
|
||||
return BukkitRecipeManager.instance().recipeByInput(RecipeType.CAMPFIRE_COOKING, new SingleItemInput<>(UniqueIdItem.of(item))) != null;
|
||||
});
|
||||
registerInteraction(BlockKeys.CAMPFIRE, (player, item, blockState, result) -> {
|
||||
if (!Config.enableRecipeSystem()) return false;
|
||||
return BukkitRecipeManager.instance().recipeByInput(RecipeType.CAMPFIRE_COOKING, new SingleItemInput<>(new UniqueIdItem<>(
|
||||
item.recipeIngredientId(), item
|
||||
))) != null;
|
||||
return BukkitRecipeManager.instance().recipeByInput(RecipeType.CAMPFIRE_COOKING, new SingleItemInput<>(UniqueIdItem.of(item))) != null;
|
||||
});
|
||||
registerInteraction(BlockKeys.CHISELED_BOOKSHELF, (player, item, blockState, result) -> {
|
||||
if (!(blockState instanceof ChiseledBookshelf chiseledBookshelf)) return false;
|
||||
|
||||
@@ -3,11 +3,14 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.bukkit.CraftBukkitReflections;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ItemStackUtils {
|
||||
public final class ItemStackUtils {
|
||||
|
||||
private ItemStackUtils() {}
|
||||
|
||||
@@ -43,4 +46,9 @@ public class ItemStackUtils {
|
||||
return FastNMS.INSTANCE.method$CraftItemStack$asCraftCopy(itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
public static UniqueIdItem<ItemStack> getUniqueIdItem(@Nullable ItemStack itemStack) {
|
||||
Item<ItemStack> wrappedItem = BukkitItemManager.instance().wrap(itemStack);
|
||||
return UniqueIdItem.of(wrappedItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,7 @@
|
||||
package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class RecipeUtils {
|
||||
|
||||
private RecipeUtils() {}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static List<Object> getIngredientsFromShapedRecipe(Object recipe) {
|
||||
List<Object> ingredients = new ArrayList<>();
|
||||
try {
|
||||
if (VersionHelper.isOrAbove1_20_3()) {
|
||||
Object pattern = CoreReflections.field$1_20_3$ShapedRecipe$pattern.get(recipe);
|
||||
if (VersionHelper.isOrAbove1_21_2()) {
|
||||
List<Optional<Object>> optionals = (List<Optional<Object>>) CoreReflections.field$ShapedRecipePattern$ingredients1_21_2.get(pattern);
|
||||
for (Optional<Object> optional : optionals) {
|
||||
optional.ifPresent(ingredients::add);
|
||||
}
|
||||
} else {
|
||||
List<Object> objectList = (List<Object>) CoreReflections.field$ShapedRecipePattern$ingredients1_20_3.get(pattern);
|
||||
for (Object object : objectList) {
|
||||
Object[] values = (Object[]) CoreReflections.field$Ingredient$values.get(object);
|
||||
// is empty or not
|
||||
if (values.length != 0) {
|
||||
ingredients.add(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<Object> objectList = (List<Object>) CoreReflections.field$1_20_1$ShapedRecipe$recipeItems.get(recipe);
|
||||
for (Object object : objectList) {
|
||||
Object[] values = (Object[]) CoreReflections.field$Ingredient$values.get(object);
|
||||
if (values.length != 0) {
|
||||
ingredients.add(object);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
CraftEngine.instance().logger().warn("Failed to get ingredients from shaped recipe", e);
|
||||
}
|
||||
return ingredients;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,13 +403,6 @@ public class BukkitWorldManager implements WorldManager, Listener {
|
||||
(injected) -> sections[finalI] = injected);
|
||||
}
|
||||
}
|
||||
if (Config.enableRecipeSystem()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<Object, Object> blockEntities = (Map<Object, Object>) FastNMS.INSTANCE.field$ChunkAccess$blockEntities(levelChunk);
|
||||
for (Object blockEntity : blockEntities.values()) {
|
||||
RecipeInjector.injectCookingBlockEntity(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