Skip to content

Commit

Permalink
feat: Add crafting table functionality to cutting boards #387
Browse files Browse the repository at this point in the history
  • Loading branch information
BlayTheNinth committed May 26, 2024
1 parent 708d1f5 commit 661dd7e
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,40 @@
package net.blay09.mods.cookingforblockheads.block;

import com.mojang.serialization.MapCodec;
import net.blay09.mods.balm.api.menu.BalmMenuProvider;
import net.blay09.mods.cookingforblockheads.block.entity.CuttingBoardBlockEntity;
import net.blay09.mods.cookingforblockheads.menu.CuttingBoardMenu;
import net.minecraft.core.BlockPos;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.CraftingMenu;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;

public class CuttingBoardBlock extends BaseKitchenBlock {

public static final MapCodec<CuttingBoardBlock> CODEC = simpleCodec(CuttingBoardBlock::new);
private static final Component CONTAINER_TITLE = Component.translatable("container.cookingforblockheads.cutting_board");

private static final VoxelShape SHAPE = Block.box(2, 0, 2, 14, 1.6, 14);

Expand Down Expand Up @@ -44,4 +62,40 @@ public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
protected MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}

@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult blockHitResult) {
if (level.isClientSide) {
return InteractionResult.SUCCESS;
} else {
player.openMenu(state.getMenuProvider(level, pos));
player.awardStat(Stats.INTERACT_WITH_CRAFTING_TABLE);
return InteractionResult.CONSUME;
}
}

@Override
protected MenuProvider getMenuProvider(BlockState state, Level level, BlockPos pos) {
return new BalmMenuProvider<BlockPos>() {
@Override
public Component getDisplayName() {
return CONTAINER_TITLE;
}

@Override
public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player player) {
return new CuttingBoardMenu(windowId, inventory, ContainerLevelAccess.create(level, pos));
}

@Override
public BlockPos getScreenOpeningData(ServerPlayer serverPlayer) {
return pos;
}

@Override
public StreamCodec<RegistryFriendlyByteBuf, BlockPos> getScreenStreamCodec() {
return BlockPos.STREAM_CODEC.cast();
}
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package net.blay09.mods.cookingforblockheads.menu;

import net.blay09.mods.cookingforblockheads.block.ModBlocks;
import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Container;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.player.StackedContents;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.item.crafting.RecipeHolder;
import net.minecraft.world.item.crafting.RecipeType;
import net.minecraft.world.level.Level;

public class CuttingBoardMenu extends RecipeBookMenu<CraftingContainer> {
private final CraftingContainer craftSlots = new TransientCraftingContainer(this, 3, 3);
private final ResultContainer resultSlots = new ResultContainer();
private final ContainerLevelAccess access;
private final Player player;

public CuttingBoardMenu(int windowId, Inventory inventory) {
this(windowId, inventory, ContainerLevelAccess.NULL);
}

public CuttingBoardMenu(int windowId, Inventory inventory, ContainerLevelAccess access) {
super(MenuType.CRAFTING, windowId);
this.access = access;
this.player = inventory.player;
addSlot(new ResultSlot(inventory.player, craftSlots, resultSlots, 0, 124, 35));

for (int x = 0; x < 3; x++) {
for (int y = 0; y < 3; y++) {
addSlot(new Slot(craftSlots, y + x * 3, 30 + y * 18, 17 + x * 18));
}
}

for (int x = 0; x < 3; x++) {
for (int y = 0; y < 9; y++) {
addSlot(new Slot(inventory, y + x * 9 + 9, 8 + y * 18, 84 + x * 18));
}
}

for (int i = 0; i < 9; i++) {
addSlot(new Slot(inventory, i, 8 + i * 18, 142));
}
}

protected static void slotChangedCraftingGrid(AbstractContainerMenu menu, Level level, Player player, CraftingContainer craftingContainer, ResultContainer resultContainer) {
if (!level.isClientSide) {
final var serverPlayer = (ServerPlayer) player;
var itemStack = ItemStack.EMPTY;
final var optionalRecipe = level.getServer().getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingContainer, level);
if (optionalRecipe.isPresent()) {
final var recipeHolder = optionalRecipe.get();
final var recipe = recipeHolder.value();
if (resultContainer.setRecipeUsed(level, serverPlayer, recipeHolder)) {
final var assembledStack = recipe.assemble(craftingContainer, level.registryAccess());
if (assembledStack.isItemEnabled(level.enabledFeatures())) {
itemStack = assembledStack;
}
}
}

resultContainer.setItem(0, itemStack);
menu.setRemoteSlot(0, itemStack);
serverPlayer.connection.send(new ClientboundContainerSetSlotPacket(menu.containerId, menu.incrementStateId(), 0, itemStack));
}
}

@Override
public void slotsChanged(Container container) {
access.execute((level, pos) -> slotChangedCraftingGrid(this, level, player, craftSlots, resultSlots));
}

@Override
public void fillCraftSlotsStackedContents(StackedContents stackedContents) {
craftSlots.fillStackedContents(stackedContents);
}

@Override
public void clearCraftingContent() {
craftSlots.clearContent();
resultSlots.clearContent();
}

@Override
public boolean recipeMatches(RecipeHolder<? extends Recipe<CraftingContainer>> recipe) {
return recipe.value().matches(craftSlots, player.level());
}

@Override
public void removed(Player player) {
super.removed(player);
access.execute((level, pos) -> clearContainer(player, craftSlots));
}

@Override
public boolean stillValid(Player player) {
return stillValid(access, player, ModBlocks.cuttingBoard);
}

@Override
public ItemStack quickMoveStack(Player player, int slotId) {
var itemStack = ItemStack.EMPTY;
final var slot = slots.get(slotId);
if (slot != null && slot.hasItem()) {
final var slotStack = slot.getItem();
itemStack = slotStack.copy();
if (slotId == 0) {
this.access.execute(($$2x, $$3x) -> slotStack.getItem().onCraftedBy(slotStack, $$2x, player));
if (!moveItemStackTo(slotStack, 10, 46, true)) {
return ItemStack.EMPTY;
}

slot.onQuickCraft(slotStack, itemStack);
} else if (slotId >= 10 && slotId < 46) {
if (!moveItemStackTo(slotStack, 1, 10, false)) {
if (slotId < 37) {
if (!moveItemStackTo(slotStack, 37, 46, false)) {
return ItemStack.EMPTY;
}
} else if (!moveItemStackTo(slotStack, 10, 37, false)) {
return ItemStack.EMPTY;
}
}
} else if (!moveItemStackTo(slotStack, 10, 46, false)) {
return ItemStack.EMPTY;
}

if (slotStack.isEmpty()) {
slot.setByPlayer(ItemStack.EMPTY);
} else {
slot.setChanged();
}

if (slotStack.getCount() == itemStack.getCount()) {
return ItemStack.EMPTY;
}

slot.onTake(player, slotStack);
if (slotId == 0) {
player.drop(slotStack, false);
}
}

return itemStack;
}

@Override
public boolean canTakeItemForPickAll(ItemStack itemStack, Slot slot) {
return slot.container != resultSlots && super.canTakeItemForPickAll(itemStack, slot);
}

@Override
public int getResultSlotIndex() {
return 0;
}

@Override
public int getGridWidth() {
return craftSlots.getWidth();
}

@Override
public int getGridHeight() {
return craftSlots.getHeight();
}

@Override
public int getSize() {
return 10;
}

@Override
public RecipeBookType getRecipeBookType() {
return RecipeBookType.CRAFTING;
}

@Override
public boolean shouldMoveToInventory(int slot) {
return slot != getResultSlotIndex();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;
import net.minecraft.util.Unit;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.inventory.ContainerLevelAccess;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
Expand All @@ -32,6 +34,7 @@ public class ModMenus {
public static DeferredObject<MenuType<KitchenMenu>> cookingTable;
public static DeferredObject<MenuType<KitchenMenu>> noFilterBook;
public static DeferredObject<MenuType<KitchenMenu>> craftingBook;
public static DeferredObject<MenuType<CuttingBoardMenu>> cuttingBoard;

public static void initialize(BalmMenus menus) {
counter = menus.registerMenu(id("counter"), new BalmMenuFactory<CounterMenu, BlockPos>() {
Expand Down Expand Up @@ -151,6 +154,18 @@ public StreamCodec<RegistryFriendlyByteBuf, ItemStack> getStreamCodec() {
return ItemStack.STREAM_CODEC.cast();
}
});

cuttingBoard = menus.registerMenu(id("cutting_board"), new BalmMenuFactory<CuttingBoardMenu, BlockPos>() {
@Override
public CuttingBoardMenu create(int windowId, Inventory inventory, BlockPos pos) {
return new CuttingBoardMenu(windowId, inventory, ContainerLevelAccess.create(inventory.player.level(), pos));
}

@Override
public StreamCodec<RegistryFriendlyByteBuf, BlockPos> getStreamCodec() {
return BlockPos.STREAM_CODEC.cast();
}
});
}

@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
"container.cookingforblockheads.cow_jar_compressed": "Compressed Cow in a Jar",
"container.cookingforblockheads.cow_jar": "Cow in a Jar",
"container.cookingforblockheads.cow_jar_custom": "%s in a Jar",
"container.cookingforblockheads.cutting_board": "Cutting Board",
"itemGroup.cookingforblockheads.cookingforblockheads": "Cooking for Blockheads",
"waila.cookingforblockheads.water_stored": "Water Stored: %d/%d",
"waila.cookingforblockheads.milk_stored": "Milk Stored: %d/%d",
Expand Down

0 comments on commit 661dd7e

Please sign in to comment.