minecraft-src/net/minecraft/world/item/crafting/ShapelessRecipe.java
2025-07-04 03:15:13 +03:00

114 lines
3.9 KiB
Java

package net.minecraft.world.item.crafting;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.List;
import net.minecraft.core.HolderLookup.Provider;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.crafting.display.RecipeDisplay;
import net.minecraft.world.item.crafting.display.ShapelessCraftingRecipeDisplay;
import net.minecraft.world.item.crafting.display.SlotDisplay.ItemSlotDisplay;
import net.minecraft.world.item.crafting.display.SlotDisplay.ItemStackSlotDisplay;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
public class ShapelessRecipe implements CraftingRecipe {
final String group;
final CraftingBookCategory category;
final ItemStack result;
final List<Ingredient> ingredients;
@Nullable
private PlacementInfo placementInfo;
public ShapelessRecipe(String group, CraftingBookCategory category, ItemStack result, List<Ingredient> ingredients) {
this.group = group;
this.category = category;
this.result = result;
this.ingredients = ingredients;
}
@Override
public RecipeSerializer<ShapelessRecipe> getSerializer() {
return RecipeSerializer.SHAPELESS_RECIPE;
}
@Override
public String group() {
return this.group;
}
@Override
public CraftingBookCategory category() {
return this.category;
}
@Override
public PlacementInfo placementInfo() {
if (this.placementInfo == null) {
this.placementInfo = PlacementInfo.create(this.ingredients);
}
return this.placementInfo;
}
public boolean matches(CraftingInput craftingInput, Level level) {
if (craftingInput.ingredientCount() != this.ingredients.size()) {
return false;
} else {
return craftingInput.size() == 1 && this.ingredients.size() == 1
? ((Ingredient)this.ingredients.getFirst()).test(craftingInput.getItem(0))
: craftingInput.stackedContents().canCraft(this, null);
}
}
public ItemStack assemble(CraftingInput craftingInput, Provider provider) {
return this.result.copy();
}
@Override
public List<RecipeDisplay> display() {
return List.of(
new ShapelessCraftingRecipeDisplay(
this.ingredients.stream().map(Ingredient::display).toList(), new ItemStackSlotDisplay(this.result), new ItemSlotDisplay(Items.CRAFTING_TABLE)
)
);
}
public static class Serializer implements RecipeSerializer<ShapelessRecipe> {
private static final MapCodec<ShapelessRecipe> CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
Codec.STRING.optionalFieldOf("group", "").forGetter(shapelessRecipe -> shapelessRecipe.group),
CraftingBookCategory.CODEC.fieldOf("category").orElse(CraftingBookCategory.MISC).forGetter(shapelessRecipe -> shapelessRecipe.category),
ItemStack.STRICT_CODEC.fieldOf("result").forGetter(shapelessRecipe -> shapelessRecipe.result),
Ingredient.CODEC.listOf(1, 9).fieldOf("ingredients").forGetter(shapelessRecipe -> shapelessRecipe.ingredients)
)
.apply(instance, ShapelessRecipe::new)
);
public static final StreamCodec<RegistryFriendlyByteBuf, ShapelessRecipe> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.STRING_UTF8,
shapelessRecipe -> shapelessRecipe.group,
CraftingBookCategory.STREAM_CODEC,
shapelessRecipe -> shapelessRecipe.category,
ItemStack.STREAM_CODEC,
shapelessRecipe -> shapelessRecipe.result,
Ingredient.CONTENTS_STREAM_CODEC.apply(ByteBufCodecs.list()),
shapelessRecipe -> shapelessRecipe.ingredients,
ShapelessRecipe::new
);
@Override
public MapCodec<ShapelessRecipe> codec() {
return CODEC;
}
@Override
public StreamCodec<RegistryFriendlyByteBuf, ShapelessRecipe> streamCodec() {
return STREAM_CODEC;
}
}
}