9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-29 03:49:15 +00:00

register smithing recipes

This commit is contained in:
XiaoMoMi
2025-03-19 04:16:52 +08:00
parent 4653adc43c
commit 4090501191
5 changed files with 98 additions and 57 deletions

View File

@@ -56,18 +56,18 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
static {
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SMITHING_TRANSFORM, (key, recipe) -> {
CustomSmithingTransformRecipe<ItemStack> ceRecipe = (CustomSmithingTransformRecipe<ItemStack>) recipe;
SmithingTransformRecipe transformRecipe = new SmithingTransformRecipe(
key, ceRecipe.result(ItemBuildContext.EMPTY),
ingredientToBukkitRecipeChoice(ceRecipe.template()),
ingredientToBukkitRecipeChoice(ceRecipe.base()),
ingredientToBukkitRecipeChoice(ceRecipe.addition()),
false
);
ceRecipe.addition();
// bukkit api doesn't allow empty material choices, that's why we do this
try {
Object craftRecipe = Reflections.method$CraftSmithingTransformRecipe$fromBukkitRecipe.invoke(null, transformRecipe);
Reflections.method$CraftRecipe$addToCraftingManager.invoke(craftRecipe);
Object smithingRecipe = createMinecraftSmithingTransformRecipe(ceRecipe);
if (VersionHelper.isVersionNewerThan1_21_2()) {
smithingRecipe = Reflections.constructor$RecipeHolder.newInstance(Reflections.method$CraftRecipe$toMinecraft.invoke(null, key), smithingRecipe);
} else if (VersionHelper.isVersionNewerThan1_20_2()) {
smithingRecipe = Reflections.constructor$RecipeHolder.newInstance(Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, key.namespace(), key.value()), smithingRecipe);
}
Reflections.method$RecipeManager$addRecipe.invoke(minecraftRecipeManager(), smithingRecipe);
} catch (Exception e) {
CraftEngine.instance().logger().warn("Failed to convert smithing transform recipe", e);
CraftEngine.instance().logger().warn("Failed to convert transform recipe", e);
}
});
BUKKIT_RECIPE_FACTORIES.put(RecipeTypes.SHAPED, (key, recipe) -> {
@@ -761,9 +761,9 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
CustomSmithingTransformRecipe<ItemStack> ceRecipe = new CustomSmithingTransformRecipe<>(
id,
Ingredient.of(baseHolders),
Ingredient.of(templateHolders),
Ingredient.of(additionHolders),
baseHolders.isEmpty() ? null : Ingredient.of(baseHolders),
templateHolders.isEmpty() ? null : Ingredient.of(templateHolders),
additionHolders.isEmpty() ? null : Ingredient.of(additionHolders),
new CustomRecipeResult<>(new CloneableConstantItem(recipe.result().isCustom() ? Key.of("!internal:custom") : Key.of(recipe.result().id()), result), recipe.result().count())
);
@@ -838,15 +838,11 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
}
private static RecipeChoice ingredientToBukkitRecipeChoice(Ingredient<ItemStack> ingredient) {
if (ingredient == null) {
return EmptyRecipeChoice.INSTANCE;
} else {
Set<Material> materials = new HashSet<>();
for (Holder<Key> holder : ingredient.items()) {
materials.add(getMaterialById(holder.value()));
}
return new RecipeChoice.MaterialChoice(new ArrayList<>(materials));
Set<Material> materials = new HashSet<>();
for (Holder<Key> holder : ingredient.items()) {
materials.add(getMaterialById(holder.value()));
}
return new RecipeChoice.MaterialChoice(new ArrayList<>(materials));
}
private static Material getMaterialById(Key key) {
@@ -966,6 +962,53 @@ public class BukkitRecipeManager implements RecipeManager<ItemStack> {
}
}
// 1.20-1.21.2
private static Object toMinecraftIngredient(Ingredient<ItemStack> ingredient) throws ReflectiveOperationException {
if (ingredient == null) {
return Reflections.method$CraftRecipe$toIngredient.invoke(null, null, true);
} else {
RecipeChoice choice = ingredientToBukkitRecipeChoice(ingredient);
return Reflections.method$CraftRecipe$toIngredient.invoke(null, choice, true);
}
}
// 1.21.2+
private static Optional<Object> toOptionalMinecraftIngredient(Ingredient<ItemStack> ingredient) throws ReflectiveOperationException {
if (ingredient == null) {
return Optional.empty();
} else {
RecipeChoice choice = ingredientToBukkitRecipeChoice(ingredient);
Object mcIngredient = Reflections.method$CraftRecipe$toIngredient.invoke(null, choice, true);
return Optional.of(mcIngredient);
}
}
private static Object createMinecraftSmithingTransformRecipe(CustomSmithingTransformRecipe<ItemStack> ceRecipe) throws ReflectiveOperationException {
if (VersionHelper.isVersionNewerThan1_21_2()) {
return Reflections.constructor$SmithingTransformRecipe.newInstance(
toOptionalMinecraftIngredient(ceRecipe.template()),
toOptionalMinecraftIngredient(ceRecipe.base()),
toOptionalMinecraftIngredient(ceRecipe.addition()),
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
);
} else if (VersionHelper.isVersionNewerThan1_20_2()) {
return Reflections.constructor$SmithingTransformRecipe.newInstance(
toMinecraftIngredient(ceRecipe.template()),
toMinecraftIngredient(ceRecipe.base()),
toMinecraftIngredient(ceRecipe.addition()),
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
);
} else {
return Reflections.constructor$SmithingTransformRecipe.newInstance(
Reflections.method$ResourceLocation$fromNamespaceAndPath.invoke(null, ceRecipe.id().namespace(), ceRecipe.id().value()),
toMinecraftIngredient(ceRecipe.template()),
toMinecraftIngredient(ceRecipe.base()),
toMinecraftIngredient(ceRecipe.addition()),
Reflections.method$CraftItemStack$asNMSMirror.invoke(null, ceRecipe.result(ItemBuildContext.EMPTY))
);
}
}
public Object getRecipeHolderByRecipe(Recipe<ItemStack> recipe) {
return recipeToMcRecipeHolder.get(recipe);
}

View File

@@ -1,35 +0,0 @@
package net.momirealms.craftengine.bukkit.item.recipe;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.RecipeChoice;
import org.jetbrains.annotations.NotNull;
record EmptyRecipeChoice() implements RecipeChoice {
static final RecipeChoice INSTANCE = new EmptyRecipeChoice();
@Override
@NotNull
public ItemStack getItemStack() {
throw new UnsupportedOperationException("This is an empty RecipeChoice");
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
@NotNull
public RecipeChoice clone() {
return this;
}
@Override
public boolean test(final @NotNull ItemStack itemStack) {
return false;
}
@Override
@NotNull
public RecipeChoice validate(final boolean allowEmptyRecipes) {
if (allowEmptyRecipes) return this;
throw new IllegalArgumentException("empty RecipeChoice isn't allowed here");
}
}

View File

@@ -4267,6 +4267,12 @@ public class Reflections {
BukkitReflectionUtils.assembleMCClass("world.item.crafting.RecipeHolder")
);
// 1.20.2-1.21.1 resource location
// 1.21.2+ resource key
public static final Constructor<?> constructor$RecipeHolder = Optional.ofNullable(clazz$RecipeHolder)
.map(it -> ReflectionUtils.getConstructor(it, 0))
.orElse(null);
// 1.20.2+
public static final Field field$RecipeHolder$recipe = Optional.ofNullable(clazz$RecipeHolder)
.map(it -> ReflectionUtils.getDeclaredField(it, 1))
@@ -4945,4 +4951,30 @@ public class Reflections {
ReflectionUtils.getDeclaredField(
clazz$CraftInventoryAnvil, clazz$AnvilMenu, 0
);
public static final Class<?> clazz$SmithingTransformRecipe = requireNonNull(
ReflectionUtils.getClazz(
BukkitReflectionUtils.assembleMCClass("world.item.crafting.SmithingTransformRecipe")
)
);
public static final Constructor<?> constructor$SmithingTransformRecipe = requireNonNull(
VersionHelper.isVersionNewerThan1_21_2() ?
ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, Optional.class, Optional.class, Optional.class, clazz$ItemStack) :
VersionHelper.isVersionNewerThan1_20_2() ?
ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack) :
ReflectionUtils.getConstructor(clazz$SmithingTransformRecipe, clazz$ResourceLocation, clazz$Ingredient, clazz$Ingredient, clazz$Ingredient, clazz$ItemStack)
);
public static final Method method$RecipeManager$addRecipe = requireNonNull(
VersionHelper.isVersionNewerThan1_20_2() ?
ReflectionUtils.getMethod(clazz$RecipeManager, void.class, clazz$RecipeHolder) :
ReflectionUtils.getMethod(clazz$RecipeManager, void.class, clazz$Recipe)
);
public static final Method method$CraftRecipe$toIngredient = requireNonNull(
ReflectionUtils.getStaticMethod(
clazz$CraftRecipe, clazz$Ingredient, RecipeChoice.class, boolean.class
)
);
}