9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-28 03:19:14 +00:00

Stone Cutting is a Lie

This commit is contained in:
XiaoMoMi
2025-02-16 00:42:42 +08:00
parent 53ca5482ac
commit c18ee2b477
10 changed files with 128 additions and 30 deletions

View File

@@ -179,6 +179,26 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
CraftEngine.instance().logger().warn("Failed to convert campfire recipe", e);
}
});
BUKKIT_RECIPE_REGISTER.put(RecipeTypes.STONE_CUTTING, (key, recipe) -> {
CustomStoneCuttingRecipe<ItemStack> ceRecipe = (CustomStoneCuttingRecipe<ItemStack>) recipe;
List<ItemStack> itemStacks = new ArrayList<>();
for (Holder<Key> item : ceRecipe.ingredient().items()) {
itemStacks.add(BukkitItemManager.instance().buildItemStack(item.value(), null));
}
StonecuttingRecipe stonecuttingRecipe = new StonecuttingRecipe(
key, ceRecipe.getResult(null),
new RecipeChoice.ExactChoice(itemStacks)
);
if (ceRecipe.group() != null) {
stonecuttingRecipe.setGroup(Objects.requireNonNull(ceRecipe.group()));
}
try {
Object craftRecipe = Reflections.method$CraftStonecuttingRecipe$fromBukkitRecipe.invoke(null, stonecuttingRecipe);
Reflections.method$CraftRecipe$addToCraftingManager.invoke(craftRecipe);
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to convert stone cutting recipe", e);
}
});
}
private final BukkitCraftEngine plugin;

View File

@@ -12,7 +12,7 @@ import net.momirealms.craftengine.core.item.recipe.CustomCampfireRecipe;
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
import net.momirealms.craftengine.core.item.recipe.Recipe;
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
import net.momirealms.craftengine.core.item.recipe.input.CookingInput;
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
import net.momirealms.craftengine.core.item.recipe.input.CraftingInput;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
import net.momirealms.craftengine.core.registry.Holder;
@@ -64,7 +64,7 @@ public class RecipeEventListener implements Listener {
Optional<Holder.Reference<Key>> idHolder = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(wrappedItem.id());
if (idHolder.isEmpty()) return;
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), item));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), item));
Key recipeType;
if (furnaceInventory.getType() == InventoryType.FURNACE) {
recipeType = RecipeTypes.SMELTING;
@@ -344,7 +344,7 @@ public class RecipeEventListener implements Listener {
if (idHolder.isEmpty()) {
return;
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input);
if (ceRecipe == null) {
event.setCancelled(true);
@@ -374,7 +374,7 @@ public class RecipeEventListener implements Listener {
return;
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input);
if (ceRecipe == null) {
event.setTotalCookTime(Integer.MAX_VALUE);
@@ -406,7 +406,7 @@ public class RecipeEventListener implements Listener {
return;
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
CustomCampfireRecipe<ItemStack> ceRecipe = (CustomCampfireRecipe<ItemStack>) this.recipeManager.getRecipe(RecipeTypes.CAMPFIRE_COOKING, input);
if (ceRecipe == null) {
event.setCancelled(true);

View File

@@ -25,7 +25,7 @@ import net.momirealms.craftengine.core.block.StatePredicate;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
import net.momirealms.craftengine.core.item.recipe.input.CookingInput;
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
@@ -351,7 +351,7 @@ public class BukkitInjector {
return Optional.empty();
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
if (type == Reflections.instance$RecipeType$SMELTING) {
@@ -418,7 +418,7 @@ public class BukkitInjector {
return Optional.empty();
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
if (type == Reflections.instance$RecipeType$SMELTING) {
@@ -477,7 +477,7 @@ public class BukkitInjector {
return Optional.empty();
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
if (type == Reflections.instance$RecipeType$SMELTING) {
@@ -537,7 +537,7 @@ public class BukkitInjector {
return Optional.empty();
}
CookingInput<ItemStack> input = new CookingInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
SingleItemInput<ItemStack> input = new SingleItemInput<>(new OptimizedIDItem<>(idHolder.get(), itemStack));
net.momirealms.craftengine.core.item.recipe.CookingRecipe<ItemStack> ceRecipe;
Key lastCustomRecipe = (Key) field$InjectedCacheChecker$lastCustomRecipe.get(thisObj);
if (type == Reflections.instance$RecipeType$SMELTING) {

View File

@@ -5,7 +5,7 @@ import net.momirealms.craftengine.core.block.BlockKeys;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
import net.momirealms.craftengine.core.item.recipe.RecipeTypes;
import net.momirealms.craftengine.core.item.recipe.input.CookingInput;
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.ConfigManager;
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
@@ -79,14 +79,14 @@ public class InteractUtils {
register(BlockKeys.SOUL_CAMPFIRE, (player, item, blockState, result) -> {
if (!ConfigManager.enableRecipeSystem()) return false;
Optional<Holder.Reference<Key>> optional = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(item.id());
return optional.filter(keyReference -> BukkitRecipeManager.instance().getRecipe(RecipeTypes.CAMPFIRE_COOKING, new CookingInput<>(new OptimizedIDItem<>(
return optional.filter(keyReference -> BukkitRecipeManager.instance().getRecipe(RecipeTypes.CAMPFIRE_COOKING, new SingleItemInput<>(new OptimizedIDItem<>(
keyReference, item.getItem()
))) != null).isPresent();
});
register(BlockKeys.CAMPFIRE, (player, item, blockState, result) -> {
if (!ConfigManager.enableRecipeSystem()) return false;
Optional<Holder.Reference<Key>> optional = BuiltInRegistries.OPTIMIZED_ITEM_ID.get(item.id());
return optional.filter(keyReference -> BukkitRecipeManager.instance().getRecipe(RecipeTypes.CAMPFIRE_COOKING, new CookingInput<>(new OptimizedIDItem<>(
return optional.filter(keyReference -> BukkitRecipeManager.instance().getRecipe(RecipeTypes.CAMPFIRE_COOKING, new SingleItemInput<>(new OptimizedIDItem<>(
keyReference, item.getItem()
))) != null).isPresent();
});

View File

@@ -4341,6 +4341,18 @@ public class Reflections {
)
);
public static final Class<?> clazz$CraftStonecuttingRecipe = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleCBClass("inventory.CraftStonecuttingRecipe")
)
);
public static final Method method$CraftStonecuttingRecipe$fromBukkitRecipe = requireNonNull(
ReflectionUtils.getStaticMethod(
clazz$CraftStonecuttingRecipe, clazz$CraftStonecuttingRecipe, StonecuttingRecipe.class
)
);
public static final Field field$AbstractFurnaceBlockEntity$recipeType = requireNonNull(
ReflectionUtils.getDeclaredField(
clazz$AbstractFurnaceBlockEntity, clazz$RecipeType, 0

View File

@@ -1,7 +1,7 @@
package net.momirealms.craftengine.core.item.recipe;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.input.CookingInput;
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
import net.momirealms.craftengine.core.util.Key;
@@ -30,7 +30,7 @@ public abstract class CookingRecipe<T> extends AbstractRecipe<T> {
@SuppressWarnings("unchecked")
@Override
public boolean matches(RecipeInput input) {
return this.ingredient.test(((CookingInput<T>) input).input());
return this.ingredient.test(((SingleItemInput<T>) input).input());
}
@Override

View File

@@ -0,0 +1,73 @@
package net.momirealms.craftengine.core.item.recipe;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.item.recipe.input.RecipeInput;
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
import net.momirealms.craftengine.core.plugin.CraftEngine;
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.MiscUtils;
import org.jetbrains.annotations.NotNull;
import java.util.*;
public class CustomStoneCuttingRecipe<T> extends AbstractRecipe<T> {
public static final Factory<?> FACTORY = new Factory<>();
protected final Ingredient<T> ingredient;
protected final CustomRecipeResult<T> result;
protected CustomStoneCuttingRecipe(Key id, String group, Ingredient<T> ingredient, CustomRecipeResult<T> result) {
super(id, group);
this.ingredient = ingredient;
this.result = result;
}
@SuppressWarnings("unchecked")
@Override
public boolean matches(RecipeInput input) {
return this.ingredient.test(((SingleItemInput<T>) input).input());
}
@Override
public T getResult(Player player) {
return result.buildItemStack(player);
}
@Override
public @NotNull Key type() {
return RecipeTypes.STONE_CUTTING;
}
public Ingredient<T> ingredient() {
return ingredient;
}
public CustomRecipeResult<T> result() {
return result;
}
public static class Factory<A> implements RecipeFactory<A> {
@SuppressWarnings({"DuplicatedCode"})
@Override
public Recipe<A> create(Key id, Map<String, Object> arguments) {
String group = arguments.containsKey("group") ? arguments.get("group").toString() : null;
List<String> items = MiscUtils.getAsStringList(arguments.get("ingredient"));
Set<Holder<Key>> holders = new HashSet<>();
for (String item : items) {
if (item.charAt(0) == '#') {
holders.addAll(CraftEngine.instance().itemManager().tagToItems(Key.of(item.substring(1))));
} else {
holders.add(BuiltInRegistries.OPTIMIZED_ITEM_ID.get(Key.of(item)).orElseThrow(() -> new IllegalArgumentException("Invalid vanilla/custom item: " + item)));
}
}
return new CustomStoneCuttingRecipe<>(
id,
group,
Ingredient.of(holders),
parseResult(arguments)
);
}
}
}

View File

@@ -16,6 +16,7 @@ public class RecipeTypes {
public static final Key BLASTING = Key.of("minecraft:blasting");
public static final Key SMOKING = Key.of("minecraft:smoking");
public static final Key CAMPFIRE_COOKING = Key.of("minecraft:campfire_cooking");
public static final Key STONE_CUTTING = Key.of("minecraft:stone_cutting");
static {
register(SHAPED, CustomShapedRecipe.FACTORY);
@@ -24,6 +25,7 @@ public class RecipeTypes {
register(SMOKING, CustomSmokingRecipe.FACTORY);
register(BLASTING, CustomBlastingRecipe.FACTORY);
register(CAMPFIRE_COOKING, CustomCampfireRecipe.FACTORY);
register(STONE_CUTTING, CustomStoneCuttingRecipe.FACTORY);
}
public static <T> void register(Key key, RecipeFactory<T> factory) {

View File

@@ -1,15 +0,0 @@
package net.momirealms.craftengine.core.item.recipe.input;
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
public class CookingInput<T> implements RecipeInput {
private final OptimizedIDItem<T> input;
public CookingInput(OptimizedIDItem<T> input) {
this.input = input;
}
public OptimizedIDItem<T> input() {
return input;
}
}

View File

@@ -0,0 +1,6 @@
package net.momirealms.craftengine.core.item.recipe.input;
import net.momirealms.craftengine.core.item.recipe.OptimizedIDItem;
public record SingleItemInput<T>(OptimizedIDItem<T> input) implements RecipeInput {
}