Skip to content

Commit

Permalink
Added Recipe Logic for DiskAssemblerBlock
Browse files Browse the repository at this point in the history
  • Loading branch information
RoboXGamer committed Nov 6, 2024
1 parent 184076f commit 95bc63a
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
Expand Down Expand Up @@ -49,7 +51,12 @@ protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockSt
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return new DiskAssemblerBlockEntity(blockPos, blockState);
}


@Override
public @Nullable <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, @NotNull BlockState blockState, @NotNull BlockEntityType<T> blockEntityType) {
return level.isClientSide ? null : ((level1, pos, state, blockEntity) -> ((DiskAssemblerBlockEntity) blockEntity).tick());
}

@Override
protected InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player, BlockHitResult hitResult) {
if (player instanceof ServerPlayer serverPlayer) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,28 @@
package dev.wolfieboy09.qstorage.block.disk_assembler;

import dev.wolfieboy09.qstorage.QuantiumizedStorage;
import dev.wolfieboy09.qstorage.block.AbstractEnergyBlockEntity;
import dev.wolfieboy09.qstorage.registries.QSBlockEntities;
import dev.wolfieboy09.qstorage.registries.QSRecipes;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.network.chat.Component;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
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.RecipeManager;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.energy.EnergyStorage;
import net.neoforged.neoforge.items.ItemStackHandler;
import net.neoforged.neoforge.items.wrapper.RecipeWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

Expand All @@ -27,7 +34,9 @@ public class DiskAssemblerBlockEntity extends AbstractEnergyBlockEntity implemen
private int progress = 0;
private int crafting_ticks = 0;
private int energy_required = 0;

private DiskAssemblerRecipe recipe = null;
private boolean isValidRecipe = false;

public DiskAssemblerBlockEntity(BlockPos pos, BlockState blockState) {
super(QSBlockEntities.DISK_ASSEMBLER.get(), pos, blockState, getEnergyCapacity(), 1000, 0);
}
Expand All @@ -43,6 +52,95 @@ public DiskAssemblerBlockEntity(BlockPos pos, BlockState blockState) {
return new DiskAssemblerMenu(id, this.getBlockPos(), playerInv, player, this.energyData);
}

public void tick() {
if (this.level == null || getInputContainer().isEmpty()) return;

// Validate the recipe
if (!this.isValidRecipe) return;

// Check if output has space before crafting
ItemStack outputSlotStack = this.inventory.getStackInSlot(DiskAssemblerSlot.OUTPUT_SLOT);
ItemStack resultItem = this.recipe.getResultItem(this.level.registryAccess());

boolean outputHasSpace = outputSlotStack.isEmpty() ||
(outputSlotStack.getItem() == resultItem.getItem() &&
outputSlotStack.getCount() + resultItem.getCount() <= outputSlotStack.getMaxStackSize());

if (!outputHasSpace) return; // Exit if output slot lacks space

// Check energy and progress crafting if energy is sufficient
boolean energySufficient = this.energyStorage.getEnergyStored() >= this.recipe.energyCost();
int timeRequired = this.recipe.timeInTicks();

if (energySufficient) {
if (this.crafting_ticks < timeRequired) {
this.crafting_ticks++;
this.progress = getProgress();
QuantiumizedStorage.LOGGER.debug("Progress: {}", this.progress);
}

// If progress reaches 100%, complete the crafting
if (this.progress >= 100) {
// Consume energy and input items
this.energyStorage.removeEnergy(this.recipe.energyCost()); // Extract energy here upon successful crafting
consumeInputItems();

// Place result in output slot
if (outputSlotStack.isEmpty()) {
this.inventory.setStackInSlot(DiskAssemblerSlot.OUTPUT_SLOT, resultItem.copy());
} else {
outputSlotStack.grow(resultItem.getCount());
}

// Reset crafting progress
resetProgress();
}
}
}

private int getProgress() {
return (int) (this.crafting_ticks / (float) this.recipe.timeInTicks() * 100);
}

private void consumeInputItems() {
this.inventory.getStackInSlot(DiskAssemblerSlot.MAIN_SLOT_1).shrink(1);
this.inventory.getStackInSlot(DiskAssemblerSlot.MAIN_SLOT_2).shrink(1);
this.inventory.getStackInSlot(DiskAssemblerSlot.MAIN_SLOT_3).shrink(1);
this.inventory.getStackInSlot(DiskAssemblerSlot.EXTRA_SLOT_1).shrink(1);
this.inventory.getStackInSlot(DiskAssemblerSlot.EXTRA_SLOT_2).shrink(1);
this.inventory.getStackInSlot(DiskAssemblerSlot.EXTRA_SLOT_3).shrink(1);
this.inventory.getStackInSlot(DiskAssemblerSlot.EXTRA_SLOT_4).shrink(1);
}

protected void resetProgress() {
this.crafting_ticks = 0;
this.progress = 0;
}

private boolean checkRecipe(){
// Get the input items
if (this.level == null) return false;
var inputHandler = new ItemStackHandler(7);
for (int i = 0; i < 7; i++) {
inputHandler.setStackInSlot(i, this.inventory.getStackInSlot(i));
}
RecipeWrapper input = new RecipeWrapper(inputHandler);
RecipeManager recipes = this.level.getRecipeManager();
RecipeHolder<DiskAssemblerRecipe> recipeFound = recipes.getRecipeFor(
QSRecipes.DISK_ASSEMBLER_TYPE.get(),
input,
this.level
).orElseGet(()->null);
if (recipeFound == null) return false;
DiskAssemblerRecipe recipe = recipeFound.value();
boolean matches = recipe.matches(input, this.level);
if (!matches) return false;
ItemStack result = recipe.assemble(input, this.level.registryAccess());
if (result.isEmpty()) return false;
this.recipe = recipe;
return true;
}

public static class DiskAssemblerSlot {
public static final int MAIN_SLOT_1 = 0;
public static final int MAIN_SLOT_2 = 1;
Expand All @@ -59,15 +157,14 @@ public static class DiskAssemblerSlot {
protected void onContentsChanged(int slot) {
if (slot < 7) {
resetProgress();
setIsValidRecipe(checkRecipe());
}
setChanged();
}
};

protected void resetProgress() {
if (this.progress != 0) {
this.progress = 0;
}

private void setIsValidRecipe(boolean value){
this.isValidRecipe = value;
}

public ItemStackHandler getInventory() {
Expand Down Expand Up @@ -128,6 +225,24 @@ public SimpleContainer getOutputContainer() {
container.setItem(0, inventory.getStackInSlot(inventory.getSlots() - 1));
return container;
}

private void saveRecipeToNBT(CompoundTag modData, HolderLookup.Provider registries) {
try {
if (this.recipe instanceof DiskAssemblerRecipe t) {
modData.put("recipe", DiskAssemblerRecipe.CODEC.encodeStart(NbtOps.INSTANCE, t).getOrThrow());
}
} catch (Exception e) {
QuantiumizedStorage.LOGGER.error("Error saving recipe to NBT: {}", e.getMessage());
}
}

private void loadRecipeFromNBT(CompoundTag recipeTag) {
var recipe = Recipe.CODEC.parse(NbtOps.INSTANCE, recipeTag).getOrThrow();
if (recipe instanceof DiskAssemblerRecipe diskAssemblerRecipe) {
this.recipe = diskAssemblerRecipe;
}
}


@Override
public void saveExtra(CompoundTag tag, HolderLookup.Provider registries) {
Expand All @@ -136,6 +251,8 @@ public void saveExtra(CompoundTag tag, HolderLookup.Provider registries) {
tag.putInt("energy_required", this.energy_required);
tag.putInt("crafting_ticks", this.crafting_ticks);
tag.put("inventory", this.inventory.serializeNBT(registries));
tag.putBoolean("isValidRecipe", this.isValidRecipe);
saveRecipeToNBT(tag, registries);
}

@Override
Expand All @@ -145,6 +262,11 @@ protected void loadExtra(CompoundTag tag, HolderLookup.Provider registries) {
this.energy_required = tag.getInt("energy_required");
this.crafting_ticks = tag.getInt("crafting_ticks");
this.inventory.deserializeNBT(registries, tag.getCompound("inventory"));
this.isValidRecipe = tag.getBoolean("isValidRecipe");
// Load the recipe if it exists
if (tag.contains("recipe")) {
loadRecipeFromNBT(tag.getCompound("recipe"));
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
import org.jetbrains.annotations.NotNull;

import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

@ParametersAreNonnullByDefault
public record DiskAssemblerRecipe(
Expand All @@ -33,29 +31,26 @@ public record DiskAssemblerRecipe(
) implements Recipe<RecipeWrapper>, RecipeType<DiskAssemblerRecipe> {

@Override
public boolean matches(RecipeWrapper recipeWrapper, Level level) {
ItemStack[] mainItems = {recipeWrapper.getItem(0), recipeWrapper.getItem(1), recipeWrapper.getItem(2)};
List<Predicate<ItemStack>> toTest = Arrays.asList(diskPort, diskCasing, screws);

for (Predicate<ItemStack> test : toTest) {
if (Arrays.stream(mainItems).noneMatch(test)) {
return false;
}
}

for (int i = 3; i <= 6; i++) {
ItemStack extraItem = recipeWrapper.getItem(i);
if (extras.stream().noneMatch(extra -> extra.test(extraItem))) {
return false;
public boolean matches(RecipeWrapper input, Level level) {
boolean extrasMatch = !this.extras.isEmpty();
for (Ingredient extra : this.extras) {
if (!extra.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.EXTRA_SLOT_1))
&& !extra.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.EXTRA_SLOT_2))
&& !extra.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.EXTRA_SLOT_3))
&& !extra.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.EXTRA_SLOT_4))) {
extrasMatch = false;
}
}
return true;

return this.diskPort.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.MAIN_SLOT_1))
&& this.diskCasing.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.MAIN_SLOT_2))
&& this.screws.test(input.getItem(DiskAssemblerBlockEntity.DiskAssemblerSlot.MAIN_SLOT_3))
&& extrasMatch;
}


@Override
public @NotNull ItemStack assemble(RecipeWrapper recipeWrapper, HolderLookup.Provider provider) {
return this.result.copy();
return getResultItem(provider);
}

@Override
Expand Down

0 comments on commit 95bc63a

Please sign in to comment.