Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cutting Board Recipe Patch #974

Open
wants to merge 1 commit into
base: 1.21
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package vectorwing.farmersdelight.common.block.entity;

import java.util.List;
import java.util.Optional;

import javax.annotation.Nullable;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
Expand All @@ -15,7 +20,7 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeManager;
import net.minecraft.world.item.crafting.SingleRecipeInput;
import net.minecraft.world.item.crafting.RecipeManager.CachedCheck;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.block.Block;
Expand All @@ -31,6 +36,7 @@
import vectorwing.farmersdelight.FarmersDelight;
import vectorwing.farmersdelight.common.block.CuttingBoardBlock;
import vectorwing.farmersdelight.common.crafting.CuttingBoardRecipe;
import vectorwing.farmersdelight.common.crafting.CuttingBoardRecipeWrapper;
import vectorwing.farmersdelight.common.registry.ModAdvancements;
import vectorwing.farmersdelight.common.registry.ModBlockEntityTypes;
import vectorwing.farmersdelight.common.registry.ModRecipeTypes;
Expand All @@ -39,16 +45,11 @@
import vectorwing.farmersdelight.common.utility.ItemUtils;
import vectorwing.farmersdelight.common.utility.TextUtils;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;

@EventBusSubscriber(modid = FarmersDelight.MODID, bus = EventBusSubscriber.Bus.MOD)
public class CuttingBoardBlockEntity extends SyncedBlockEntity
{
public class CuttingBoardBlockEntity extends SyncedBlockEntity {
private final ItemStackHandler inventory;
private ResourceLocation lastRecipeID;
private final RecipeManager.CachedCheck<SingleRecipeInput, CuttingBoardRecipe> quickCheck;
private final CachedCheck<CuttingBoardRecipeWrapper, CuttingBoardRecipe> quickCheck;

private boolean isItemCarvingBoard;

Expand All @@ -61,11 +62,8 @@ public CuttingBoardBlockEntity(BlockPos pos, BlockState state) {

@SubscribeEvent
public static void registerCapabilities(RegisterCapabilitiesEvent event) {
event.registerBlockEntity(
Capabilities.ItemHandler.BLOCK,
ModBlockEntityTypes.CUTTING_BOARD.get(),
(be, context) -> be.getInventory()
);
event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntityTypes.CUTTING_BOARD.get(),
(be, context) -> be.getInventory());
}

@Override
Expand All @@ -83,19 +81,23 @@ public void saveAdditional(CompoundTag compound, HolderLookup.Provider registrie
}

public boolean processStoredItemUsingTool(ItemStack toolStack, @Nullable Player player) {
if (level == null) return false;
if (level == null)
return false;

if (isItemCarvingBoard) return false;
if (isItemCarvingBoard)
return false;

Optional<RecipeHolder<CuttingBoardRecipe>> matchingRecipe = getMatchingRecipe(toolStack, player);

matchingRecipe.ifPresent(recipe -> {
List<ItemStack> results = recipe.value().rollResults(level.random, EnchantmentHelper.getTagEnchantmentLevel(level.holder(Enchantments.FORTUNE).get(), toolStack));
List<ItemStack> results = recipe.value().rollResults(level.random,
EnchantmentHelper.getTagEnchantmentLevel(level.holder(Enchantments.FORTUNE).get(), toolStack));
for (ItemStack resultStack : results) {
Direction direction = getBlockState().getValue(CuttingBoardBlock.FACING).getCounterClockWise();
ItemUtils.spawnItemEntity(level, resultStack.copy(),
worldPosition.getX() + 0.5 + (direction.getStepX() * 0.2), worldPosition.getY() + 0.2, worldPosition.getZ() + 0.5 + (direction.getStepZ() * 0.2),
direction.getStepX() * 0.2F, 0.0F, direction.getStepZ() * 0.2F);
worldPosition.getX() + 0.5 + (direction.getStepX() * 0.2), worldPosition.getY() + 0.2,
worldPosition.getZ() + 0.5 + (direction.getStepZ() * 0.2), direction.getStepX() * 0.2F, 0.0F,
direction.getStepZ() * 0.2F);
}
if (!level.isClientSide) {
toolStack.hurtAndBreak(1, (ServerLevel) level, player, (item) -> {
Expand All @@ -113,9 +115,11 @@ public boolean processStoredItemUsingTool(ItemStack toolStack, @Nullable Player
}

private Optional<RecipeHolder<CuttingBoardRecipe>> getMatchingRecipe(ItemStack toolStack, @Nullable Player player) {
if (level == null) return Optional.empty();
if (level == null)
return Optional.empty();

Optional<RecipeHolder<CuttingBoardRecipe>> recipe = quickCheck.getRecipeFor(new SingleRecipeInput(getStoredItem()), level);
Optional<RecipeHolder<CuttingBoardRecipe>> recipe = quickCheck
.getRecipeFor(new CuttingBoardRecipeWrapper(getStoredItem(), toolStack), level);
if (recipe.isPresent()) {
if (recipe.get().value().getTool().test(toolStack)) {
return recipe;
Expand Down Expand Up @@ -147,7 +151,8 @@ public void playProcessingSound(@Nullable SoundEvent sound, ItemStack tool, Item

public void playSound(SoundEvent sound, float volume, float pitch) {
if (level != null)
level.playSound(null, worldPosition.getX() + 0.5F, worldPosition.getY() + 0.5F, worldPosition.getZ() + 0.5F, sound, SoundSource.BLOCKS, volume, pitch);
level.playSound(null, worldPosition.getX() + 0.5F, worldPosition.getY() + 0.5F, worldPosition.getZ() + 0.5F,
sound, SoundSource.BLOCKS, volume, pitch);
}

public boolean addItem(ItemStack itemStack) {
Expand Down Expand Up @@ -200,8 +205,7 @@ public void setRemoved() {
}

private ItemStackHandler createHandler() {
return new ItemStackHandler()
{
return new ItemStackHandler() {
@Override
public int getSlotLimit(int slot) {
return 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package vectorwing.farmersdelight.common.crafting;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;

import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.NonNullList;
Expand All @@ -15,20 +22,16 @@
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.*;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;
import vectorwing.farmersdelight.common.crafting.ingredient.ChanceResult;
import vectorwing.farmersdelight.common.registry.ModRecipeSerializers;
import vectorwing.farmersdelight.common.registry.ModRecipeTypes;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public class CuttingBoardRecipe implements Recipe<SingleRecipeInput>
{
public class CuttingBoardRecipe implements Recipe<CuttingBoardRecipeWrapper> {
public static final int MAX_RESULTS = 4;

private final String group;
Expand All @@ -37,7 +40,8 @@ public class CuttingBoardRecipe implements Recipe<SingleRecipeInput>
private final NonNullList<ChanceResult> results;
private final Optional<SoundEvent> soundEvent;

public CuttingBoardRecipe(String group, Ingredient input, Ingredient tool, NonNullList<ChanceResult> results, Optional<SoundEvent> soundEvent) {
public CuttingBoardRecipe(String group, Ingredient input, Ingredient tool, NonNullList<ChanceResult> results,
Optional<SoundEvent> soundEvent) {
this.group = group;
this.input = input;
this.tool = tool;
Expand All @@ -46,12 +50,12 @@ public CuttingBoardRecipe(String group, Ingredient input, Ingredient tool, NonNu
}

@Override
public boolean matches(SingleRecipeInput input, Level level) {
return this.input.test(input.item());
public boolean matches(CuttingBoardRecipeWrapper input, Level level) {
return this.input.test(input.item()) && this.tool.test(input.tool());
}

@Override
public ItemStack assemble(SingleRecipeInput inv, HolderLookup.Provider provider) {
public ItemStack assemble(CuttingBoardRecipeWrapper inv, HolderLookup.Provider provider) {
return this.results.getFirst().stack().copy();
}

Expand Down Expand Up @@ -82,9 +86,7 @@ public ItemStack getResultItem(HolderLookup.Provider provider) {
}

public List<ItemStack> getResults() {
return getRollableResults().stream()
.map(ChanceResult::stack)
.collect(Collectors.toList());
return getRollableResults().stream().map(ChanceResult::stack).collect(Collectors.toList());
}

public NonNullList<ChanceResult> getRollableResults() {
Expand Down Expand Up @@ -127,15 +129,21 @@ public RecipeType<?> getType() {

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;

CuttingBoardRecipe that = (CuttingBoardRecipe) o;

if (!getGroup().equals(that.getGroup())) return false;
if (!input.equals(that.input)) return false;
if (!getTool().equals(that.getTool())) return false;
if (!getResults().equals(that.getResults())) return false;
if (!getGroup().equals(that.getGroup()))
return false;
if (!input.equals(that.input))
return false;
if (!getTool().equals(that.getTool()))
return false;
if (!getResults().equals(that.getResults()))
return false;
return Objects.equals(soundEvent, that.soundEvent);
}

Expand All @@ -149,38 +157,41 @@ public int hashCode() {
return result;
}

public static class Serializer implements RecipeSerializer<CuttingBoardRecipe>
{
private static final MapCodec<CuttingBoardRecipe> CODEC = RecordCodecBuilder.mapCodec(inst -> inst.group(
Codec.STRING.optionalFieldOf("group", "").forGetter(CuttingBoardRecipe::getGroup),
Ingredient.LIST_CODEC_NONEMPTY.fieldOf("ingredients").flatXmap(ingredients -> {
if (ingredients.isEmpty()) {
return DataResult.error(() -> "No ingredients for cutting recipe");
}
if (ingredients.size() > 1) {
return DataResult.error(() -> "Too many ingredients for cutting recipe! Please define only one ingredient");
}
NonNullList<Ingredient> nonNullList = NonNullList.create();
nonNullList.add(ingredients.get(0));
return DataResult.success(ingredients.get(0));
}, ingredient -> {
NonNullList<Ingredient> nonNullList = NonNullList.create();
nonNullList.add(ingredient);
return DataResult.success(nonNullList);
}).forGetter(cuttingBoardRecipe -> cuttingBoardRecipe.input),
Ingredient.CODEC.fieldOf("tool").forGetter(CuttingBoardRecipe::getTool),
Codec.list(ChanceResult.CODEC).fieldOf("result").flatXmap(chanceResults -> {
if (chanceResults.size() > 4) {
return DataResult.error(() -> "Too many results for cutting recipe! The maximum quantity of unique results is " + MAX_RESULTS);
}
NonNullList<ChanceResult> nonNullList = NonNullList.create();
nonNullList.addAll(chanceResults);
return DataResult.success(nonNullList);
}, DataResult::success).forGetter(CuttingBoardRecipe::getRollableResults),
SoundEvent.DIRECT_CODEC.optionalFieldOf("sound").forGetter(CuttingBoardRecipe::getSoundEvent)
).apply(inst, CuttingBoardRecipe::new));

public static final StreamCodec<RegistryFriendlyByteBuf, CuttingBoardRecipe> STREAM_CODEC = StreamCodec.of(CuttingBoardRecipe.Serializer::toNetwork, CuttingBoardRecipe.Serializer::fromNetwork);
public static class Serializer implements RecipeSerializer<CuttingBoardRecipe> {
private static final MapCodec<CuttingBoardRecipe> CODEC = RecordCodecBuilder.mapCodec(
inst -> inst.group(Codec.STRING.optionalFieldOf("group", "").forGetter(CuttingBoardRecipe::getGroup),
Ingredient.LIST_CODEC_NONEMPTY.fieldOf("ingredients").flatXmap(ingredients -> {
if (ingredients.isEmpty()) {
return DataResult.error(() -> "No ingredients for cutting recipe");
}
if (ingredients.size() > 1) {
return DataResult.error(
() -> "Too many ingredients for cutting recipe! Please define only one ingredient");
}
NonNullList<Ingredient> nonNullList = NonNullList.create();
nonNullList.add(ingredients.get(0));
return DataResult.success(ingredients.get(0));
}, ingredient -> {
NonNullList<Ingredient> nonNullList = NonNullList.create();
nonNullList.add(ingredient);
return DataResult.success(nonNullList);
}).forGetter(cuttingBoardRecipe -> cuttingBoardRecipe.input),
Ingredient.CODEC.fieldOf("tool").forGetter(CuttingBoardRecipe::getTool),
Codec.list(ChanceResult.CODEC).fieldOf("result").flatXmap(chanceResults -> {
if (chanceResults.size() > 4) {
return DataResult.error(
() -> "Too many results for cutting recipe! The maximum quantity of unique results is "
+ MAX_RESULTS);
}
NonNullList<ChanceResult> nonNullList = NonNullList.create();
nonNullList.addAll(chanceResults);
return DataResult.success(nonNullList);
}, DataResult::success).forGetter(CuttingBoardRecipe::getRollableResults),
SoundEvent.DIRECT_CODEC.optionalFieldOf("sound").forGetter(CuttingBoardRecipe::getSoundEvent))
.apply(inst, CuttingBoardRecipe::new));

public static final StreamCodec<RegistryFriendlyByteBuf, CuttingBoardRecipe> STREAM_CODEC = StreamCodec
.of(CuttingBoardRecipe.Serializer::toNetwork, CuttingBoardRecipe.Serializer::fromNetwork);

public Serializer() {
}
Expand All @@ -205,7 +216,8 @@ public static CuttingBoardRecipe fromNetwork(RegistryFriendlyByteBuf buffer) {
resultsIn.replaceAll(ignored -> ChanceResult.read(buffer));
Optional<SoundEvent> soundEventIn = Optional.empty();
if (buffer.readBoolean()) {
Optional<Holder.Reference<SoundEvent>> holder = BuiltInRegistries.SOUND_EVENT.getHolder(buffer.readResourceKey(Registries.SOUND_EVENT));
Optional<Holder.Reference<SoundEvent>> holder = BuiltInRegistries.SOUND_EVENT
.getHolder(buffer.readResourceKey(Registries.SOUND_EVENT));
if (holder.isPresent() && holder.get().isBound()) {
soundEventIn = Optional.of(holder.get().value());
}
Expand All @@ -223,7 +235,8 @@ public static void toNetwork(RegistryFriendlyByteBuf buffer, CuttingBoardRecipe
result.write(buffer);
}
if (recipe.getSoundEvent().isPresent()) {
Optional<ResourceKey<SoundEvent>> resourceKey = BuiltInRegistries.SOUND_EVENT.getResourceKey(recipe.getSoundEvent().get());
Optional<ResourceKey<SoundEvent>> resourceKey = BuiltInRegistries.SOUND_EVENT
.getResourceKey(recipe.getSoundEvent().get());
resourceKey.ifPresentOrElse(rk -> {
buffer.writeBoolean(true);
buffer.writeResourceKey(rk);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package vectorwing.farmersdelight.common.crafting;

import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeInput;

public record CuttingBoardRecipeWrapper(ItemStack item, ItemStack tool) implements RecipeInput {
@Override
public ItemStack getItem(int p_345528_) {
if (p_345528_ != 0) {
throw new IllegalArgumentException("No item for index " + p_345528_);
} else {
return this.item;
}
}

@Override
public int size() {
return 2;
}
}