From 747d96f02dd88183c454f826c3edf6ac996d1ca2 Mon Sep 17 00:00:00 2001 From: Elenterius Date: Sat, 5 Oct 2024 16:03:10 +0200 Subject: [PATCH] refactor: refactor inventory handling of block entities and menus --- .../biomancy/api/nutrients/Nutrients.java | 2 + .../biomancy/block/base/MachineBlock.java | 2 +- .../block/base/MachineBlockEntity.java | 23 +- .../base/SimpleContainerBlockEntity.java | 7 +- .../block/bioforge/BioForgeBlock.java | 2 +- .../block/bioforge/BioForgeBlockEntity.java | 45 ++-- .../biomancy/block/biolab/BioLabBlock.java | 2 +- .../block/biolab/BioLabBlockEntity.java | 80 +++--- .../block/biolab/BioLabStateData.java | 3 +- .../block/decomposer/DecomposerBlock.java | 2 +- .../decomposer/DecomposerBlockEntity.java | 73 +++--- .../block/decomposer/DecomposerStateData.java | 3 +- .../block/digester/DigesterBlock.java | 2 +- .../block/digester/DigesterBlockEntity.java | 109 +++----- .../block/digester/DigesterStateData.java | 3 +- .../fleshkinchest/FleshkinChestBlock.java | 8 +- .../FleshkinChestBlockEntity.java | 42 +-- .../block/mawhopper/MawHopperBlockEntity.java | 8 +- .../ModularLarynxBlockEntity.java | 2 +- .../ownable/OwnableContainerBlockEntity.java | 4 +- .../block/storagesac/StorageSacBlock.java | 2 +- .../storagesac/StorageSacBlockEntity.java | 33 +-- .../block/tongue/TongueBlockEntity.java | 6 +- .../biomancy/client/gui/DecomposerScreen.java | 2 +- .../StorageSacTooltipClientComponent.java | 4 +- .../crafting/recipe/DigestingRecipe.java | 3 +- .../recipe/DynamicProcessingRecipe.java | 3 +- .../crafting/recipe/ProcessingRecipe.java | 8 +- .../recipe/StaticProcessingRecipe.java | 2 +- .../FuelConsumingRecipeCraftingStateData.java | 3 +- .../state/RecipeCraftingStateData.java | 4 +- .../integration/jei/BiomancyJeiPlugin.java | 2 +- .../biomancy/inventory/BaseInventory.java | 240 ------------------ .../inventory/BehavioralInventory.java | 79 ------ .../inventory/BehavioralItemHandler.java | 147 +++++++++++ .../FixedSizeItemStackHandler.java | 4 +- .../inventory/InjectorItemInventory.java | 83 ++---- .../biomancy/inventory/InventoryHandler.java | 102 ++++++++ .../biomancy/inventory/InventoryHandlers.java | 164 ++++++++++++ .../biomancy/inventory/ItemHandlerUtil.java | 127 +++++++++ ...emHandler.java => ItemHandlerWrapper.java} | 29 ++- .../inventory/ItemStackInventory.java | 42 ++- .../LargeSingleItemStackHandler.java | 2 +- .../inventory/SerializableItemHandler.java | 9 + .../biomancy/inventory/SimpleInventory.java | 46 ---- .../SingleItemStackHandler.java | 5 +- .../itemhandler/HandlerBehaviors.java | 93 ------- .../itemhandler/ItemHandlerDelegator.java | 120 --------- .../inventory/itemhandler/package-info.java | 7 - .../biomancy/item/StorageSacBlockItem.java | 16 +- .../biomancy/item/injector/InjectorItem.java | 8 +- .../biomancy/menu/BioForgeMenu.java | 81 +++--- .../elenterius/biomancy/menu/BioLabMenu.java | 73 +++--- .../biomancy/menu/DecomposerMenu.java | 79 +++--- .../biomancy/menu/DigesterMenu.java | 59 ++--- .../biomancy/menu/FleshkinChestMenu.java | 49 ++-- .../biomancy/menu/{slot => }/ISlotZone.java | 2 +- .../biomancy/menu/PlayerContainerMenu.java | 1 - .../biomancy/menu/StorageSacMenu.java | 36 +-- .../biomancy/menu/slot/FuelSlot.java | 19 -- .../biomancy/menu/slot/NonNestingSlot.java | 20 -- .../biomancy/menu/slot/OutputSlot.java | 18 -- .../biomancy/menu/slot/package-info.java | 7 - .../tooltip/StorageSacTooltipComponent.java | 8 +- .../biomancy/util/ItemStackFilter.java | 79 ++++++ .../biomancy/util/ItemStackFilterList.java | 92 +++++++ .../util/PlayerInteractionPredicate.java | 7 + 67 files changed, 1223 insertions(+), 1224 deletions(-) delete mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/BaseInventory.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/BehavioralInventory.java create mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/BehavioralItemHandler.java rename src/main/java/com/github/elenterius/biomancy/inventory/{itemhandler => }/FixedSizeItemStackHandler.java (95%) create mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandler.java create mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandlers.java create mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerUtil.java rename src/main/java/com/github/elenterius/biomancy/inventory/{itemhandler/EnhancedItemHandler.java => ItemHandlerWrapper.java} (88%) rename src/main/java/com/github/elenterius/biomancy/inventory/{itemhandler => }/LargeSingleItemStackHandler.java (97%) create mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/SerializableItemHandler.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/SimpleInventory.java rename src/main/java/com/github/elenterius/biomancy/inventory/{itemhandler => }/SingleItemStackHandler.java (95%) delete mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/HandlerBehaviors.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/ItemHandlerDelegator.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/package-info.java rename src/main/java/com/github/elenterius/biomancy/menu/{slot => }/ISlotZone.java (68%) delete mode 100644 src/main/java/com/github/elenterius/biomancy/menu/slot/FuelSlot.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/menu/slot/NonNestingSlot.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/menu/slot/OutputSlot.java delete mode 100644 src/main/java/com/github/elenterius/biomancy/menu/slot/package-info.java create mode 100644 src/main/java/com/github/elenterius/biomancy/util/ItemStackFilter.java create mode 100644 src/main/java/com/github/elenterius/biomancy/util/ItemStackFilterList.java create mode 100644 src/main/java/com/github/elenterius/biomancy/util/PlayerInteractionPredicate.java diff --git a/src/main/java/com/github/elenterius/biomancy/api/nutrients/Nutrients.java b/src/main/java/com/github/elenterius/biomancy/api/nutrients/Nutrients.java index bbe83d004..d82b883a5 100644 --- a/src/main/java/com/github/elenterius/biomancy/api/nutrients/Nutrients.java +++ b/src/main/java/com/github/elenterius/biomancy/api/nutrients/Nutrients.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.ApiStatus; import java.util.function.IntUnaryOperator; +import java.util.function.Predicate; @ApiStatus.Experimental public final class Nutrients { @@ -19,6 +20,7 @@ public final class Nutrients { private static final Object2IntMap REPAIR_VALUES = new Object2IntArrayMap<>(); public static final IntUnaryOperator RAW_MEAT_NUTRITION_MODIFIER = nutrition -> nutrition > 0 ? Mth.ceil(3.75d * Math.exp(0.215d * nutrition)) : 0; + public static final Predicate FUEL_PREDICATE = Nutrients::isValidFuel; static { registerFuel(ModItems.NUTRIENT_PASTE.get(), 3); diff --git a/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlock.java b/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlock.java index 5302e24e3..288e11a28 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlock.java @@ -58,7 +58,7 @@ public void onRemove(BlockState state, Level level, BlockPos pos, BlockState new updateNeighbors(level, pos); } BlockEntity blockEntity = level.getBlockEntity(pos); - if (blockEntity instanceof MachineBlockEntity machine) { + if (blockEntity instanceof MachineBlockEntity machine) { machine.dropAllInvContents(level, pos); } if (Boolean.TRUE.equals(state.getValue(CRAFTING))) { diff --git a/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlockEntity.java index 47b6cf796..e49852bb1 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/base/MachineBlockEntity.java @@ -5,10 +5,11 @@ import com.github.elenterius.biomancy.crafting.state.CraftingState; import com.github.elenterius.biomancy.crafting.state.RecipeCraftingStateData; import com.github.elenterius.biomancy.init.ModBlockProperties; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.util.PlayerInteractionPredicate; import com.github.elenterius.biomancy.util.fuel.IFuelHandler; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.Container; import net.minecraft.world.Nameable; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; @@ -21,7 +22,7 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -public abstract class MachineBlockEntity, C extends Container, S extends RecipeCraftingStateData> extends BlockEntity implements Nameable { +public abstract class MachineBlockEntity> extends BlockEntity implements Nameable, PlayerInteractionPredicate { protected final int tickOffset = BiomancyMod.GLOBAL_RANDOM.nextInt(20); protected int ticks = tickOffset; @@ -30,27 +31,33 @@ protected MachineBlockEntity(BlockEntityType type, BlockPos pos, BlockState s super(type, pos, state); } - public static , C extends Container, S extends RecipeCraftingStateData> void serverTick(Level level, BlockPos pos, BlockState state, MachineBlockEntity entity) { + public static > void serverTick(Level level, BlockPos pos, BlockState state, MachineBlockEntity entity) { entity.serverTick((ServerLevel) level); } - public boolean canPlayerOpenInv(Player player) { + @Override + public boolean canPlayerInteract(Player player) { + if (isRemoved()) return false; if (level == null || level.getBlockEntity(worldPosition) != this) return false; return player.distanceToSqr(Vec3.atCenterOf(worldPosition)) < 8d * 8d; } + protected void onInventoryChanged() { + if (level != null && !level.isClientSide) setChanged(); + } + public int getTicks() { return ticks - tickOffset; } protected abstract S getStateData(); - protected abstract C getInputInventory(); + protected abstract InventoryHandler getInputInventory(); protected abstract IFuelHandler getFuelHandler(); public int getFuelCost(R recipeToCraft) { - return getFuelHandler().getFuelCost(recipeToCraft.getCraftingCostNutrients(getInputInventory())); + return getFuelHandler().getFuelCost(recipeToCraft.getCraftingCostNutrients(getInputInventory().getRecipeWrapper())); } public abstract ItemStack getStackInFuelSlot(); @@ -111,7 +118,7 @@ protected void serverTick(final ServerLevel level) { if (hasEnoughFuel(craftingGoal)) { //make sure there is enough fuel to craft the recipe state.setCraftingState(CraftingState.IN_PROGRESS); state.clear(); //safeguard, shouldn't be needed - state.setCraftingGoalRecipe(craftingGoal, getInputInventory()); // this also sets the time required for crafting + state.setCraftingGoalRecipe(craftingGoal, getInputInventory().getRecipeWrapper()); // this also sets the time required for crafting } } else if (!state.isCraftingCanceled()) { // something is being crafted, check that the crafting goals match R prevCraftingGoal = state.getCraftingGoalRecipe(level).orElse(null); @@ -163,7 +170,7 @@ else if (state.getCraftingState() == CraftingState.NONE) { private ItemStack getItemToCraft(ServerLevel level, R craftingGoal) { if (craftingGoal.isSpecial()) { - return craftingGoal.assemble(getInputInventory(), level.registryAccess()); + return craftingGoal.assemble(getInputInventory().getRecipeWrapper(), level.registryAccess()); } return craftingGoal.getResultItem(level.registryAccess()); } diff --git a/src/main/java/com/github/elenterius/biomancy/block/base/SimpleContainerBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/base/SimpleContainerBlockEntity.java index 06255ea53..6ecc10bc0 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/base/SimpleContainerBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/base/SimpleContainerBlockEntity.java @@ -1,5 +1,6 @@ package com.github.elenterius.biomancy.block.base; +import com.github.elenterius.biomancy.util.PlayerInteractionPredicate; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; @@ -14,7 +15,7 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; -public abstract class SimpleContainerBlockEntity extends BlockEntity implements MenuProvider, Nameable { +public abstract class SimpleContainerBlockEntity extends BlockEntity implements MenuProvider, PlayerInteractionPredicate, Nameable { protected Component name; @@ -22,7 +23,9 @@ protected SimpleContainerBlockEntity(BlockEntityType type, BlockPos pos, Bloc super(type, pos, state); } - public boolean canPlayerOpenContainer(Player player) { + @Override + public boolean canPlayerInteract(Player player) { + if (isRemoved()) return false; if (level == null || level.getBlockEntity(worldPosition) != this) return false; return player.distanceToSqr(Vec3.atCenterOf(worldPosition)) < 8d * 8d; } diff --git a/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlock.java b/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlock.java index 1a535a811..e2a274c2d 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlock.java @@ -90,7 +90,7 @@ public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (level.getBlockEntity(pos) instanceof BioForgeBlockEntity bioForge && bioForge.canPlayerOpenInv(player)) { + if (level.getBlockEntity(pos) instanceof BioForgeBlockEntity bioForge && bioForge.canPlayerInteract(player)) { if (!level.isClientSide) { NetworkHooks.openScreen((ServerPlayer) player, bioForge, buffer -> buffer.writeBlockPos(pos)); SoundUtil.broadcastBlockSound((ServerLevel) level, pos, ModSoundEvents.UI_BIO_FORGE_OPEN); diff --git a/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlockEntity.java index 8ea13e4d1..c254e25b0 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/bioforge/BioForgeBlockEntity.java @@ -3,10 +3,12 @@ import com.github.elenterius.biomancy.BiomancyMod; import com.github.elenterius.biomancy.init.ModBlockEntities; import com.github.elenterius.biomancy.init.ModCapabilities; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.HandlerBehaviors; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.inventory.InventoryHandlers; +import com.github.elenterius.biomancy.inventory.ItemHandlerUtil; import com.github.elenterius.biomancy.menu.BioForgeMenu; import com.github.elenterius.biomancy.styles.TextComponentUtil; +import com.github.elenterius.biomancy.util.PlayerInteractionPredicate; import com.github.elenterius.biomancy.util.fuel.FluidFuelConsumerHandler; import com.github.elenterius.biomancy.util.fuel.FuelHandler; import com.github.elenterius.biomancy.util.fuel.IFuelHandler; @@ -16,13 +18,11 @@ import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.util.Mth; -import net.minecraft.world.Containers; import net.minecraft.world.MenuProvider; import net.minecraft.world.Nameable; 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.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -45,15 +45,17 @@ import javax.annotation.Nonnull; import java.util.Objects; -public class BioForgeBlockEntity extends BlockEntity implements MenuProvider, Nameable, GeoBlockEntity { +public class BioForgeBlockEntity extends BlockEntity implements MenuProvider, PlayerInteractionPredicate, Nameable, GeoBlockEntity { public static final int FUEL_SLOTS = 1; public static final int MAX_FUEL = 1_000; static final int OPENERS_CHANGE_EVENT = 1; + protected final int tickOffset = BiomancyMod.GLOBAL_RANDOM.nextInt(20); + private final BioForgeStateData stateData; private final FuelHandler fuelHandler; - private final BehavioralInventory fuelInventory; + private final InventoryHandler fuelInventory; private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { @@ -82,7 +84,9 @@ protected boolean isOwnContainer(Player player) { return false; } }; + private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); + protected int ticks = tickOffset; private boolean playWorkingAnimation = false; private int nearbyTimer = -10; @@ -91,9 +95,7 @@ protected boolean isOwnContainer(Player player) { public BioForgeBlockEntity(BlockPos worldPosition, BlockState blockState) { super(ModBlockEntities.BIO_FORGE.get(), worldPosition, blockState); - fuelInventory = BehavioralInventory.createServerContents(FUEL_SLOTS, HandlerBehaviors::filterFuel, this::canPlayerOpenInv, this::setChanged); - fuelInventory.setOpenInventoryConsumer(this::startOpen); - fuelInventory.setCloseInventoryConsumer(this::stopOpen); + fuelInventory = InventoryHandlers.filterFuel(FUEL_SLOTS, this::onInventoryChanged); fuelHandler = FuelHandler.createNutrientFuelHandler(MAX_FUEL, this::setChanged); stateData = new BioForgeStateData(fuelHandler); @@ -117,17 +119,22 @@ public boolean triggerEvent(int id, int type) { return super.triggerEvent(id, type); } - public boolean canPlayerOpenInv(Player player) { + @Override + public boolean canPlayerInteract(Player player) { if (level == null || level.getBlockEntity(worldPosition) != this) return false; return player.distanceToSqr(Vec3.atCenterOf(worldPosition)) < 8d * 8d; } - private void startOpen(Player player) { + protected void onInventoryChanged() { + if (level != null && !level.isClientSide) setChanged(); + } + + public void startOpen(Player player) { if (remove || player.isSpectator()) return; openersCounter.incrementOpeners(player, Objects.requireNonNull(getLevel()), getBlockPos(), getBlockState()); } - private void stopOpen(Player player) { + public void stopOpen(Player player) { if (remove || player.isSpectator()) return; openersCounter.decrementOpeners(player, Objects.requireNonNull(getLevel()), getBlockPos(), getBlockState()); } @@ -140,7 +147,11 @@ public void recheckOpen() { @Nullable @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return BioForgeMenu.createServerMenu(containerId, playerInventory, fuelInventory, stateData, ContainerLevelAccess.create(level, getBlockPos())); + return BioForgeMenu.createServerMenu(containerId, playerInventory, this); + } + + public InventoryHandler getFuelInventory() { + return fuelInventory; } public BioForgeStateData getStateData() { @@ -176,11 +187,11 @@ public int getMaxFuelAmount() { } public ItemStack getStackInFuelSlot() { - return fuelInventory.getItem(0); + return fuelInventory.getStackInSlot(0); } public void setStackInFuelSlot(ItemStack stack) { - fuelInventory.setItem(0, stack); + fuelInventory.setStackInSlot(0, stack); } @Override @@ -198,7 +209,7 @@ public void load(CompoundTag tag) { } public void dropAllInvContents(Level level, BlockPos pos) { - Containers.dropContents(level, pos, fuelInventory); + ItemHandlerUtil.dropContents(level, pos, fuelInventory); } @Nonnull @@ -207,7 +218,7 @@ public LazyOptional getCapability(Capability cap, @Nullable Direction if (remove) return super.getCapability(cap, side); if (cap == ModCapabilities.ITEM_HANDLER && side != null && side.getAxis().isHorizontal()) { - return fuelInventory.getOptionalItemHandler().cast(); + return fuelInventory.getLazyOptional().cast(); } if (cap == ModCapabilities.FLUID_HANDLER) { diff --git a/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlock.java b/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlock.java index cb85d4acc..c0ca39bd6 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlock.java @@ -78,7 +78,7 @@ public BlockEntityTicker getTicker(Level level, Block @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (level.getBlockEntity(pos) instanceof BioLabBlockEntity bioLab && bioLab.canPlayerOpenInv(player)) { + if (level.getBlockEntity(pos) instanceof BioLabBlockEntity bioLab && bioLab.canPlayerInteract(player)) { if (!level.isClientSide) { NetworkHooks.openScreen((ServerPlayer) player, bioLab, buffer -> buffer.writeBlockPos(pos)); SoundUtil.broadcastBlockSound((ServerLevel) level, pos, ModSoundEvents.UI_BIO_LAB_OPEN); diff --git a/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlockEntity.java index 4ab5b8292..6d2a28d51 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabBlockEntity.java @@ -10,12 +10,14 @@ import com.github.elenterius.biomancy.init.ModCapabilities; import com.github.elenterius.biomancy.init.ModRecipes; import com.github.elenterius.biomancy.init.ModSoundEvents; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.inventory.SimpleInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.HandlerBehaviors; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.inventory.InventoryHandlers; +import com.github.elenterius.biomancy.inventory.ItemHandlerUtil; import com.github.elenterius.biomancy.menu.BioLabMenu; import com.github.elenterius.biomancy.styles.TextComponentUtil; import com.github.elenterius.biomancy.util.ILoopingSoundHelper; +import com.github.elenterius.biomancy.util.ItemStackFilter; +import com.github.elenterius.biomancy.util.ItemStackFilterList; import com.github.elenterius.biomancy.util.SoundUtil; import com.github.elenterius.biomancy.util.fuel.FluidFuelConsumerHandler; import com.github.elenterius.biomancy.util.fuel.FuelHandler; @@ -25,8 +27,6 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.Container; -import net.minecraft.world.Containers; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -54,7 +54,7 @@ import java.util.List; -public class BioLabBlockEntity extends MachineBlockEntity implements MenuProvider, GeoBlockEntity { +public class BioLabBlockEntity extends MachineBlockEntity implements MenuProvider, GeoBlockEntity { public static final int FUEL_SLOTS = 1; public static final int INPUT_SLOTS = BioLabRecipe.MAX_INGREDIENTS + BioLabRecipe.MAX_REACTANT; @@ -69,9 +69,12 @@ public class BioLabBlockEntity extends MachineBlockEntity fuelInventory; - private final SimpleInventory inputInventory; - private final BehavioralInventory outputInventory; + private final InventoryHandler fuelInventory; + + private final InventoryHandler inputInventory; + private final ItemStackFilterList inputSlotsFilter; + + private final InventoryHandler outputInventory; private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private ILoopingSoundHelper loopingSoundHelper = ILoopingSoundHelper.NULL; @@ -82,9 +85,12 @@ public class BioLabBlockEntity extends MachineBlockEntity createCombinedInventory() { return LazyOptional.of(() -> new CombinedInvWrapper( - fuelInventory.getItemHandlerWithBehavior(), - new RangedWrapper(inputInventory.getItemHandler(), inputInventory.getContainerSize() - 1, inputInventory.getContainerSize()) + fuelInventory, + new RangedWrapper(inputInventory, inputInventory.getSlots() - 1, inputInventory.getSlots()) )); } @@ -120,19 +126,27 @@ public Component getName() { @Nullable @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return BioLabMenu.createServerMenu(containerId, playerInventory, fuelInventory, inputInventory, outputInventory, stateData); + return BioLabMenu.createServerMenu(containerId, playerInventory, this); } @Override - protected BioLabStateData getStateData() { + public BioLabStateData getStateData() { return stateData; } @Override - protected Container getInputInventory() { + public InventoryHandler getInputInventory() { return inputInventory; } + public InventoryHandler getFuelInventory() { + return fuelInventory; + } + + public InventoryHandler getOutputInventory() { + return outputInventory; + } + @Override protected IFuelHandler getFuelHandler() { return fuelHandler; @@ -140,28 +154,28 @@ protected IFuelHandler getFuelHandler() { @Override public ItemStack getStackInFuelSlot() { - return fuelInventory.getItem(0); + return fuelInventory.getStackInSlot(0); } @Override public void setStackInFuelSlot(ItemStack stack) { - fuelInventory.setItem(0, stack); + fuelInventory.setStackInSlot(0, stack); } @Override protected boolean doesRecipeResultFitIntoOutputInv(BioLabRecipe craftingGoal, ItemStack stackToCraft) { - return outputInventory.getItem(0).isEmpty() || outputInventory.doesItemStackFit(0, stackToCraft); + return ItemHandlerUtil.doesItemFit(outputInventory.getRaw(), 0, stackToCraft); } @Nullable @Override protected BioLabRecipe resolveRecipeFromInput(Level level) { - return RECIPE_TYPE.get().getRecipeFromContainer(level, inputInventory).orElse(null); + return RECIPE_TYPE.get().getRecipeFromContainer(level, inputInventory.getRecipeWrapper()).orElse(null); } @Override protected boolean doesRecipeMatchInput(BioLabRecipe recipeToTest, Level level) { - return recipeToTest.matches(inputInventory, level); + return recipeToTest.matches(inputInventory.getRecipeWrapper(), level); } @Override @@ -171,6 +185,7 @@ protected void saveAdditional(CompoundTag tag) { tag.put("Fuel", fuelHandler.serializeNBT()); tag.put("FuelSlots", fuelInventory.serializeNBT()); tag.put("InputSlots", inputInventory.serializeNBT()); + tag.put("InputSlotsFilter", inputSlotsFilter.serializeNBT()); tag.put("OutputSlots", outputInventory.serializeNBT()); } @@ -181,14 +196,15 @@ public void load(CompoundTag tag) { fuelHandler.deserializeNBT(tag.getCompound("Fuel")); fuelInventory.deserializeNBT(tag.getCompound("FuelSlots")); inputInventory.deserializeNBT(tag.getCompound("InputSlots")); + inputSlotsFilter.deserializeNBT(tag.getCompound("InputSlotsFilter")); outputInventory.deserializeNBT(tag.getCompound("OutputSlots")); } @Override public void dropAllInvContents(Level level, BlockPos pos) { - Containers.dropContents(level, pos, fuelInventory); - Containers.dropContents(level, pos, inputInventory); - Containers.dropContents(level, pos, outputInventory); + ItemHandlerUtil.dropContents(level, pos, fuelInventory); + ItemHandlerUtil.dropContents(level, pos, inputInventory); + ItemHandlerUtil.dropContents(level, pos, outputInventory); } @Override @@ -196,8 +212,8 @@ public void dropAllInvContents(Level level, BlockPos pos) { if (remove) return super.getCapability(cap, side); if (cap == ModCapabilities.ITEM_HANDLER) { - if (side == null || side == Direction.DOWN) return outputInventory.getOptionalItemHandler().cast(); - if (side == Direction.UP) return inputInventory.getOptionalItemHandler().cast(); + if (side == null || side == Direction.DOWN) return outputInventory.getLazyOptional().cast(); + if (side == Direction.UP) return inputInventory.getLazyOptional().cast(); return optionalCombinedInventory.cast(); } @@ -243,18 +259,18 @@ protected boolean craftRecipe(BioLabRecipe recipeToCraft, Level level) { } //consume reactant - final int lastIndex = inputInventory.getContainerSize() - 1; - inputInventory.removeItem(lastIndex, 1); + final int lastIndex = inputInventory.getSlots() - 1; + inputInventory.extractItem(lastIndex, 1, false); //consume ingredients for (int idx = 0; idx < lastIndex; idx++) { - final ItemStack foundStack = inputInventory.getItem(idx); //do not modify this stack + final ItemStack foundStack = inputInventory.getStackInSlot(idx); //do not modify this stack if (!foundStack.isEmpty()) { for (int i = 0; i < ingredients.size(); i++) { int remainingCost = ingredientCost[i]; if (remainingCost > 0 && ingredients.get(i).testItem(foundStack)) { int amount = Math.min(remainingCost, foundStack.getCount()); - inputInventory.removeItem(idx, amount); + inputInventory.extractItem(idx, amount, false); ingredientCost[i] -= amount; break; } @@ -263,7 +279,7 @@ protected boolean craftRecipe(BioLabRecipe recipeToCraft, Level level) { } //output result - outputInventory.insertItemStack(0, result); + outputInventory.getRaw().insertItem(0, result, false); SoundUtil.broadcastBlockSound((ServerLevel) level, getBlockPos(), ModSoundEvents.BIO_LAB_CRAFTING_COMPLETED); diff --git a/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabStateData.java b/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabStateData.java index 330282405..0833a1e6f 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabStateData.java +++ b/src/main/java/com/github/elenterius/biomancy/block/biolab/BioLabStateData.java @@ -3,10 +3,9 @@ import com.github.elenterius.biomancy.crafting.recipe.BioLabRecipe; import com.github.elenterius.biomancy.crafting.state.FuelConsumingRecipeCraftingStateData; import com.github.elenterius.biomancy.util.fuel.IFuelHandler; -import net.minecraft.world.Container; import net.minecraft.world.item.crafting.Recipe; -public class BioLabStateData extends FuelConsumingRecipeCraftingStateData { +public class BioLabStateData extends FuelConsumingRecipeCraftingStateData { public BioLabStateData(IFuelHandler fuelHandler) { super(fuelHandler); diff --git a/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlock.java b/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlock.java index 4ec5c446c..8cb8afd7d 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlock.java @@ -64,7 +64,7 @@ public BlockEntityTicker getTicker(Level level, Block @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (level.getBlockEntity(pos) instanceof DecomposerBlockEntity decomposer && decomposer.canPlayerOpenInv(player)) { + if (level.getBlockEntity(pos) instanceof DecomposerBlockEntity decomposer && decomposer.canPlayerInteract(player)) { if (!level.isClientSide) { NetworkHooks.openScreen((ServerPlayer) player, decomposer, buffer -> buffer.writeBlockPos(pos)); SoundUtil.broadcastBlockSound((ServerLevel) level, pos, ModSoundEvents.UI_DECOMPOSER_OPEN); diff --git a/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlockEntity.java index 83dd24c1d..43a42c8a1 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerBlockEntity.java @@ -10,8 +10,9 @@ import com.github.elenterius.biomancy.init.ModCapabilities; import com.github.elenterius.biomancy.init.ModRecipes; import com.github.elenterius.biomancy.init.ModSoundEvents; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.HandlerBehaviors; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.inventory.InventoryHandlers; +import com.github.elenterius.biomancy.inventory.ItemHandlerUtil; import com.github.elenterius.biomancy.menu.DecomposerMenu; import com.github.elenterius.biomancy.styles.TextComponentUtil; import com.github.elenterius.biomancy.util.ILoopingSoundHelper; @@ -27,7 +28,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.util.RandomSource; import net.minecraft.world.Container; -import net.minecraft.world.Containers; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -37,7 +37,6 @@ import net.minecraft.world.item.crafting.RecipeManager; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -57,7 +56,7 @@ import java.util.ArrayList; import java.util.List; -public class DecomposerBlockEntity extends MachineBlockEntity implements MenuProvider, GeoBlockEntity { +public class DecomposerBlockEntity extends MachineBlockEntity implements MenuProvider, GeoBlockEntity { public static final int FUEL_SLOTS = 1; public static final int INPUT_SLOTS = DecomposerRecipe.MAX_INGREDIENTS; @@ -72,9 +71,9 @@ public class DecomposerBlockEntity extends MachineBlockEntity fuelInventory; - private final BehavioralInventory inputInventory; - private final BehavioralInventory outputInventory; + private final InventoryHandler fuelInventory; + private final InventoryHandler inputInventory; + private final InventoryHandler outputInventory; private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private ILoopingSoundHelper loopingSoundHelper = ILoopingSoundHelper.NULL; @@ -85,11 +84,11 @@ public class DecomposerBlockEntity extends MachineBlockEntity new FluidFuelConsumerHandler(fuelHandler)); @@ -115,25 +114,27 @@ public Component getName() { @Nullable @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return DecomposerMenu.createServerMenu(containerId, playerInventory, fuelInventory, inputInventory, outputInventory, stateData); + return DecomposerMenu.createServerMenu(containerId, playerInventory, this); } @Override - public boolean canPlayerOpenInv(Player player) { - if (level == null || level.getBlockEntity(worldPosition) != this) return false; - return player.distanceToSqr(Vec3.atCenterOf(worldPosition)) < 8d * 8d; - } - - @Override - protected DecomposerStateData getStateData() { + public DecomposerStateData getStateData() { return stateData; } @Override - protected Container getInputInventory() { + public InventoryHandler getInputInventory() { return inputInventory; } + public InventoryHandler getFuelInventory() { + return fuelInventory; + } + + public InventoryHandler getOutputInventory() { + return outputInventory; + } + @Override protected IFuelHandler getFuelHandler() { return fuelHandler; @@ -141,18 +142,18 @@ protected IFuelHandler getFuelHandler() { @Override public ItemStack getStackInFuelSlot() { - return fuelInventory.getItem(0); + return fuelInventory.getStackInSlot(0); } @Override public void setStackInFuelSlot(ItemStack stack) { - fuelInventory.setItem(0, stack); + fuelInventory.setStackInSlot(0, stack); } @Override protected boolean doesRecipeResultFitIntoOutputInv(DecomposerRecipe craftingGoal, ItemStack ignored) { DecomposerRecipeResult precomputedResult = getComputedRecipeResult(craftingGoal); - return outputInventory.doAllItemsFit(precomputedResult.items); + return ItemHandlerUtil.doAllItemsFit(outputInventory.getRaw(), precomputedResult.items); } DecomposerRecipeResult getComputedRecipeResult(DecomposerRecipe craftingGoal) { @@ -165,12 +166,12 @@ DecomposerRecipeResult getComputedRecipeResult(DecomposerRecipe craftingGoal) { @Override protected @Nullable DecomposerRecipe resolveRecipeFromInput(Level level) { - return RECIPE_TYPE.get().getRecipeFromContainer(level, inputInventory).orElse(null); + return RECIPE_TYPE.get().getRecipeFromContainer(level, inputInventory.getRecipeWrapper()).orElse(null); } @Override protected boolean doesRecipeMatchInput(DecomposerRecipe recipeToTest, Level level) { - return recipeToTest.matches(inputInventory, level); + return recipeToTest.matches(inputInventory.getRecipeWrapper(), level); } @Override @@ -201,9 +202,9 @@ public void load(CompoundTag tag) { @Override public void dropAllInvContents(Level level, BlockPos pos) { - Containers.dropContents(level, pos, fuelInventory); - Containers.dropContents(level, pos, inputInventory); - Containers.dropContents(level, pos, outputInventory); + ItemHandlerUtil.dropContents(level, pos, fuelInventory); + ItemHandlerUtil.dropContents(level, pos, inputInventory); + ItemHandlerUtil.dropContents(level, pos, outputInventory); } @Override @@ -211,9 +212,9 @@ public void dropAllInvContents(Level level, BlockPos pos) { if (remove) return super.getCapability(cap, side); if (cap == ModCapabilities.ITEM_HANDLER) { - if (side == null || side == Direction.DOWN) return outputInventory.getOptionalItemHandler().cast(); - if (side == Direction.UP) return inputInventory.getOptionalItemHandler().cast(); - return fuelInventory.getOptionalItemHandler().cast(); + if (side == null || side == Direction.DOWN) return outputInventory.getLazyOptional().cast(); + if (side == Direction.UP) return inputInventory.getLazyOptional().cast(); + return fuelInventory.getLazyOptional().cast(); } if (cap == ModCapabilities.FLUID_HANDLER) { @@ -245,12 +246,12 @@ public void reviveCaps() { protected boolean craftRecipe(DecomposerRecipe recipeToCraft, Level level) { DecomposerRecipeResult precomputedResult = getComputedRecipeResult(recipeToCraft); - if (!outputInventory.doAllItemsFit(precomputedResult.items)) return false; + if (!ItemHandlerUtil.doAllItemsFit(outputInventory.getRaw(), precomputedResult.items)) return false; - inputInventory.removeItem(0, recipeToCraft.getIngredientQuantity().count()); //consume input + inputInventory.extractItem(0, recipeToCraft.getIngredientQuantity().count(), false); //consume input for (ItemStack stack : precomputedResult.items) { //output result - outputInventory.insertItemStack(stack); + ItemHandlerUtil.insertItem(outputInventory.getRaw(), stack); } SoundUtil.broadcastBlockSound((ServerLevel) level, getBlockPos(), ModSoundEvents.DECOMPOSER_CRAFTING_COMPLETED); @@ -292,7 +293,6 @@ public AnimatableInstanceCache getAnimatableInstanceCache() { return cache; } - @Override public void setRemoved() { if (level != null && level.isClientSide) { @@ -302,6 +302,7 @@ public void setRemoved() { } record DecomposerRecipeResult(ResourceLocation recipeId, int seed, List items) { + @Nullable public static DecomposerRecipeResult deserialize(CompoundTag tag, RecipeManager recipeManager) { String id = tag.getString("recipeId"); diff --git a/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerStateData.java b/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerStateData.java index 2eb77c333..d0bb07161 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerStateData.java +++ b/src/main/java/com/github/elenterius/biomancy/block/decomposer/DecomposerStateData.java @@ -3,10 +3,9 @@ import com.github.elenterius.biomancy.crafting.recipe.DecomposerRecipe; import com.github.elenterius.biomancy.crafting.state.FuelConsumingRecipeCraftingStateData; import com.github.elenterius.biomancy.util.fuel.IFuelHandler; -import net.minecraft.world.Container; import net.minecraft.world.item.crafting.Recipe; -public class DecomposerStateData extends FuelConsumingRecipeCraftingStateData { +public class DecomposerStateData extends FuelConsumingRecipeCraftingStateData { public DecomposerStateData(IFuelHandler fuelHandler) { super(fuelHandler); diff --git a/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlock.java b/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlock.java index b08e863c3..3ccea0a55 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlock.java @@ -72,7 +72,7 @@ public BlockEntityTicker getTicker(Level level, Block @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (level.getBlockEntity(pos) instanceof DigesterBlockEntity digester && digester.canPlayerOpenInv(player)) { + if (level.getBlockEntity(pos) instanceof DigesterBlockEntity digester && digester.canPlayerInteract(player)) { if (!level.isClientSide) { NetworkHooks.openScreen((ServerPlayer) player, digester, buffer -> buffer.writeBlockPos(pos)); SoundUtil.broadcastBlockSound((ServerLevel) level, pos, ModSoundEvents.UI_DIGESTER_OPEN); diff --git a/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlockEntity.java index 6ef6e5ef6..e78b96b6f 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterBlockEntity.java @@ -9,8 +9,9 @@ import com.github.elenterius.biomancy.init.ModCapabilities; import com.github.elenterius.biomancy.init.ModRecipes; import com.github.elenterius.biomancy.init.ModSoundEvents; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.HandlerBehaviors; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.inventory.InventoryHandlers; +import com.github.elenterius.biomancy.inventory.ItemHandlerUtil; import com.github.elenterius.biomancy.menu.DigesterMenu; import com.github.elenterius.biomancy.styles.TextComponentUtil; import com.github.elenterius.biomancy.util.ILoopingSoundHelper; @@ -22,12 +23,7 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientGamePacketListener; -import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.Container; -import net.minecraft.world.Containers; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -36,9 +32,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -57,7 +51,7 @@ import java.util.Objects; -public class DigesterBlockEntity extends MachineBlockEntity implements MenuProvider, GeoBlockEntity { +public class DigesterBlockEntity extends MachineBlockEntity implements MenuProvider, GeoBlockEntity { public static final int FUEL_SLOTS = 1; public static final int INPUT_SLOTS = 1; @@ -71,9 +65,9 @@ public class DigesterBlockEntity extends MachineBlockEntity fuelInventory; - private final BehavioralInventory inputInventory; - private final BehavioralInventory outputInventory; + private final InventoryHandler fuelInventory; + private final InventoryHandler inputInventory; + private final InventoryHandler outputInventory; private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private ILoopingSoundHelper loopingSoundHelper = ILoopingSoundHelper.NULL; @@ -82,11 +76,12 @@ public class DigesterBlockEntity extends MachineBlockEntity new FluidFuelConsumerHandler(fuelHandler)); @@ -112,24 +107,27 @@ public Component getName() { @Nullable @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return DigesterMenu.createServerMenu(containerId, playerInventory, fuelInventory, inputInventory, outputInventory, stateData); - } - - public boolean canPlayerOpenInv(Player player) { - if (level == null || level.getBlockEntity(worldPosition) != this) return false; - return player.distanceToSqr(Vec3.atCenterOf(worldPosition)) < 8d * 8d; + return DigesterMenu.createServerMenu(containerId, playerInventory, this); } @Override - protected DigesterStateData getStateData() { + public DigesterStateData getStateData() { return stateData; } @Override - protected Container getInputInventory() { + public InventoryHandler getInputInventory() { return inputInventory; } + public InventoryHandler getFuelInventory() { + return fuelInventory; + } + + public InventoryHandler getOutputInventory() { + return outputInventory; + } + @Override protected IFuelHandler getFuelHandler() { return fuelHandler; @@ -137,41 +135,41 @@ protected IFuelHandler getFuelHandler() { @Override public ItemStack getStackInFuelSlot() { - return fuelInventory.getItem(0); + return fuelInventory.getStackInSlot(0); } @Override public void setStackInFuelSlot(ItemStack stack) { - fuelInventory.setItem(0, stack); + fuelInventory.setStackInSlot(0, stack); } @Override protected boolean doesRecipeResultFitIntoOutputInv(DigestingRecipe craftingGoal, ItemStack stackToCraft) { - return outputInventory.doesItemStackFit(stackToCraft); + return ItemHandlerUtil.doesItemFit(outputInventory.getRaw(), stackToCraft); } @Override protected @Nullable DigestingRecipe resolveRecipeFromInput(Level level) { - return RECIPE_TYPE.get().getRecipeFromContainer(level, inputInventory).orElse(null); + return RECIPE_TYPE.get().getRecipeFromContainer(level, inputInventory.getRecipeWrapper()).orElse(null); } @Override protected boolean doesRecipeMatchInput(DigestingRecipe recipeToTest, Level level) { - return recipeToTest.matches(inputInventory, level); + return recipeToTest.matches(inputInventory.getRecipeWrapper(), level); } @Override protected boolean craftRecipe(DigestingRecipe recipeToCraft, Level level) { - ItemStack result = recipeToCraft.assemble(inputInventory, level.registryAccess()); + ItemStack result = recipeToCraft.assemble(inputInventory.getRecipeWrapper(), level.registryAccess()); if (!result.isEmpty() && doesRecipeResultFitIntoOutputInv(recipeToCraft, result)) { ItemStack craftingRemainder = getCraftingRemainder(); - inputInventory.removeItem(0, 1); //consume input - outputInventory.insertItemStack(result); //output result + inputInventory.extractItem(0, 1, false); //consume input + ItemHandlerUtil.insertItem(outputInventory.getRaw(), result); //output result if (!craftingRemainder.isEmpty()) { - outputInventory.insertItemStack(craftingRemainder); + ItemHandlerUtil.insertItem(outputInventory.getRaw(), craftingRemainder); } SoundUtil.broadcastBlockSound((ServerLevel) level, getBlockPos(), ModSoundEvents.DIGESTER_CRAFTING_COMPLETED); @@ -184,7 +182,7 @@ protected boolean craftRecipe(DigestingRecipe recipeToCraft, Level level) { } private ItemStack getCraftingRemainder() { - ItemStack stack = inputInventory.getItem(0); + ItemStack stack = inputInventory.getStackInSlot(0); if (stack.hasCraftingRemainingItem()) { return stack.getCraftingRemainingItem(); @@ -198,7 +196,7 @@ private ItemStack getCraftingRemainder() { } public ItemStack getInputSlotStack() { - return inputInventory.getItem(0); + return inputInventory.getStackInSlot(0); } @Override @@ -223,9 +221,9 @@ public void load(CompoundTag tag) { @Override public void dropAllInvContents(Level level, BlockPos pos) { - Containers.dropContents(level, pos, fuelInventory); - Containers.dropContents(level, pos, inputInventory); - Containers.dropContents(level, pos, outputInventory); + ItemHandlerUtil.dropContents(level, pos, fuelInventory); + ItemHandlerUtil.dropContents(level, pos, inputInventory); + ItemHandlerUtil.dropContents(level, pos, outputInventory); } @Override @@ -233,9 +231,9 @@ public void dropAllInvContents(Level level, BlockPos pos) { if (remove) return super.getCapability(cap, side); if (cap == ModCapabilities.ITEM_HANDLER) { - if (side == null || side == Direction.DOWN) return outputInventory.getOptionalItemHandler().cast(); - if (side == Direction.UP) return inputInventory.getOptionalItemHandler().cast(); - return fuelInventory.getOptionalItemHandler().cast(); + if (side == null || side == Direction.DOWN) return outputInventory.getLazyOptional().cast(); + if (side == Direction.UP) return inputInventory.getLazyOptional().cast(); + return fuelInventory.getLazyOptional().cast(); } if (cap == ModCapabilities.FLUID_HANDLER) { @@ -263,13 +261,6 @@ public void reviveCaps() { optionalFluidConsumer = LazyOptional.of(() -> new FluidFuelConsumerHandler(fuelHandler)); } - @Override - public void setChanged() { - syncToClient(); - super.setChanged(); - } - - //client side only private PlayState handleAnimationState(AnimationState event) { Boolean isCrafting = getBlockState().getValue(MachineBlock.CRAFTING); @@ -303,24 +294,4 @@ public void setRemoved() { super.setRemoved(); } - @Override - public CompoundTag getUpdateTag() { - CompoundTag tag = new CompoundTag(); - tag.put("InputSlots", inputInventory.serializeNBT()); - return tag; - } - - @Nullable - @Override - public Packet getUpdatePacket() { - return ClientboundBlockEntityDataPacket.create(this); - } - - protected void syncToClient() { - if (level != null && !level.isClientSide) { - BlockState state = getBlockState(); - level.sendBlockUpdated(getBlockPos(), state, state, Block.UPDATE_CLIENTS); - } - } - } diff --git a/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterStateData.java b/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterStateData.java index 2fc59bbad..d4b347f42 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterStateData.java +++ b/src/main/java/com/github/elenterius/biomancy/block/digester/DigesterStateData.java @@ -3,10 +3,9 @@ import com.github.elenterius.biomancy.crafting.recipe.DigestingRecipe; import com.github.elenterius.biomancy.crafting.state.FuelConsumingRecipeCraftingStateData; import com.github.elenterius.biomancy.util.fuel.IFuelHandler; -import net.minecraft.world.Container; import net.minecraft.world.item.crafting.Recipe; -public class DigesterStateData extends FuelConsumingRecipeCraftingStateData { +public class DigesterStateData extends FuelConsumingRecipeCraftingStateData { public DigesterStateData(IFuelHandler fuelHandler) { super(fuelHandler); diff --git a/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlock.java b/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlock.java index 661d3e745..75ec8a29e 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlock.java @@ -31,7 +31,6 @@ import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; @@ -56,6 +55,7 @@ import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.items.ItemHandlerHelper; import net.minecraftforge.network.NetworkHooks; import javax.annotation.Nullable; @@ -135,7 +135,7 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player if (player instanceof ServerPlayer serverPlayer && !ChestBlock.isChestBlockedAt(level, pos)) { BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof FleshkinChestBlockEntity chest) { - if (chest.canPlayerOpenContainer(player)) { + if (chest.canPlayerInteract(player)) { ItemStack stack = player.getItemInHand(hand); if (stack.getItem() instanceof EssenceItem essenceItem) { @@ -154,7 +154,7 @@ public InteractionResult use(BlockState state, Level level, BlockPos pos, Player MenuProvider menuProvider = getMenuProvider(state, level, pos); if (menuProvider != null) { - NetworkHooks.openScreen(serverPlayer, menuProvider, byteBuffer -> {}); + NetworkHooks.openScreen(serverPlayer, menuProvider, buffer -> buffer.writeBlockPos(pos)); return InteractionResult.SUCCESS; } } @@ -219,7 +219,7 @@ public boolean hasAnalogOutputSignal(BlockState state) { @Override public int getAnalogOutputSignal(BlockState state, Level level, BlockPos pos) { if (level.getBlockEntity(pos) instanceof FleshkinChestBlockEntity chest) { - return AbstractContainerMenu.getRedstoneSignalFromContainer(chest.getInventory()); + return ItemHandlerHelper.calcRedstoneFromInventory(chest.getInventory()); } return 0; } diff --git a/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlockEntity.java index fbc7fe682..2ae504d04 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/fleshkinchest/FleshkinChestBlockEntity.java @@ -4,7 +4,9 @@ import com.github.elenterius.biomancy.init.ModBlockEntities; import com.github.elenterius.biomancy.init.ModDamageSources; import com.github.elenterius.biomancy.init.ModSoundEvents; -import com.github.elenterius.biomancy.inventory.SimpleInventory; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.inventory.InventoryHandlers; +import com.github.elenterius.biomancy.inventory.ItemHandlerUtil; import com.github.elenterius.biomancy.menu.FleshkinChestMenu; import com.github.elenterius.biomancy.styles.TextComponentUtil; import com.github.elenterius.biomancy.util.animation.TriggerableAnimation; @@ -15,8 +17,6 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; -import net.minecraft.world.Container; -import net.minecraft.world.Containers; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntitySelector; import net.minecraft.world.entity.LivingEntity; @@ -47,7 +47,8 @@ public class FleshkinChestBlockEntity extends OwnableContainerBlockEntity implem public static final int SLOTS = 6 * 7; - private final SimpleInventory inventory; + private final InventoryHandler inventory; + private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); private final ContainerOpenersCounter openersCounter = new ContainerOpenersCounter() { @@ -71,34 +72,37 @@ protected void openerCountChanged(Level level, BlockPos pos, BlockState state, i @Override protected boolean isOwnContainer(Player player) { if (player.containerMenu instanceof FleshkinChestMenu menu) { - Container container = menu.getContainer(); - return container == FleshkinChestBlockEntity.this.inventory; + return menu.getInventory() == FleshkinChestBlockEntity.this.inventory; } return false; } }; + private boolean lidShouldBeOpen = false; private boolean lidIsOpen = false; public FleshkinChestBlockEntity(BlockPos pos, BlockState state) { super(ModBlockEntities.FLESHKIN_CHEST.get(), pos, state); - inventory = SimpleInventory.createServerContents(SLOTS, this::canPlayerOpenContainer, this::setChanged); - inventory.setOpenInventoryConsumer(this::startOpen); - inventory.setCloseInventoryConsumer(this::stopOpen); + + inventory = InventoryHandlers.standard(SLOTS, this::onInventoryChanged); } - private void startOpen(Player player) { - if (remove || player.isSpectator()) return; + protected void onInventoryChanged() { + if (level != null && !level.isClientSide) setChanged(); + } + + public void startOpen(Player player) { + if (isRemoved() || player.isSpectator()) return; openersCounter.incrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); } - private void stopOpen(Player player) { - if (remove || player.isSpectator()) return; + public void stopOpen(Player player) { + if (isRemoved() || player.isSpectator()) return; openersCounter.decrementOpeners(player, getLevel(), getBlockPos(), getBlockState()); } public void recheckOpen() { - if (remove) return; + if (isRemoved()) return; openersCounter.recheckOpeners(getLevel(), getBlockPos(), getBlockState()); } @@ -142,10 +146,10 @@ public Component getDefaultName() { @Nullable @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return FleshkinChestMenu.createServerMenu(containerId, playerInventory, inventory); + return FleshkinChestMenu.createServerMenu(containerId, playerInventory, this); } - public Container getInventory() { + public InventoryHandler getInventory() { return inventory; } @@ -163,11 +167,7 @@ public void load(CompoundTag tag) { @Override public void dropContainerContents(Level level, BlockPos pos) { - if (!inventory.isEmpty()) Containers.dropContents(level, pos, inventory); - } - - public boolean isEmpty() { - return inventory.isEmpty(); + ItemHandlerUtil.dropContents(level, pos, inventory); } @NotNull diff --git a/src/main/java/com/github/elenterius/biomancy/block/mawhopper/MawHopperBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/mawhopper/MawHopperBlockEntity.java index f478188e5..e99310f7b 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/mawhopper/MawHopperBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/mawhopper/MawHopperBlockEntity.java @@ -5,8 +5,8 @@ import com.github.elenterius.biomancy.block.property.VertexType; import com.github.elenterius.biomancy.init.ModBlockEntities; import com.github.elenterius.biomancy.init.ModCapabilities; -import com.github.elenterius.biomancy.inventory.itemhandler.EnhancedItemHandler; -import com.github.elenterius.biomancy.inventory.itemhandler.SingleItemStackHandler; +import com.github.elenterius.biomancy.inventory.ItemHandlerWrapper; +import com.github.elenterius.biomancy.inventory.SingleItemStackHandler; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -174,7 +174,7 @@ private boolean tryToInsertItems(IItemHandler itemHandler) { if (stack.isEmpty()) return false; int oldCount = stack.getCount(); - EnhancedItemHandler handler = new EnhancedItemHandler(itemHandler); + ItemHandlerWrapper handler = new ItemHandlerWrapper(itemHandler); ItemStack remainder = handler.insertItem(stack, false); boolean success = remainder.getCount() != oldCount; @@ -189,7 +189,7 @@ private boolean tryToInsertItems(IItemHandler itemHandler) { private boolean tryToExtractItems(IItemHandler itemHandler) { if (inventory.isFull()) return false; - EnhancedItemHandler handler = new EnhancedItemHandler(itemHandler); + ItemHandlerWrapper handler = new ItemHandlerWrapper(itemHandler); int amount = Math.min(ITEM_TRANSFER_AMOUNT, inventory.getMaxAmount() - inventory.getAmount()); Predicate canAcceptItem = stack -> inventory.insertItem(stack, true).isEmpty(); diff --git a/src/main/java/com/github/elenterius/biomancy/block/modularlarynx/ModularLarynxBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/modularlarynx/ModularLarynxBlockEntity.java index d26df35a1..c11a51baa 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/modularlarynx/ModularLarynxBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/modularlarynx/ModularLarynxBlockEntity.java @@ -3,7 +3,7 @@ import com.github.elenterius.biomancy.block.property.MobSoundType; import com.github.elenterius.biomancy.init.ModBlockEntities; import com.github.elenterius.biomancy.init.ModCapabilities; -import com.github.elenterius.biomancy.inventory.itemhandler.SingleItemStackHandler; +import com.github.elenterius.biomancy.inventory.SingleItemStackHandler; import com.github.elenterius.biomancy.item.EssenceItem; import com.github.elenterius.biomancy.util.MobSoundUtil; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/github/elenterius/biomancy/block/ownable/OwnableContainerBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/ownable/OwnableContainerBlockEntity.java index 0ea40c237..32bd3ed7a 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/ownable/OwnableContainerBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/ownable/OwnableContainerBlockEntity.java @@ -33,8 +33,8 @@ protected OwnableContainerBlockEntity(BlockEntityType type, BlockPos pos, Blo } @Override - public boolean canPlayerOpenContainer(Player player) { - return super.canPlayerOpenContainer(player) && isActionAllowed(player, Actions.USE_BLOCK); + public boolean canPlayerInteract(Player player) { + return super.canPlayerInteract(player) && isActionAllowed(player, Actions.USE_BLOCK); } @Override diff --git a/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlock.java b/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlock.java index 5dc3b6926..330a15338 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlock.java +++ b/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlock.java @@ -61,7 +61,7 @@ public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable L @Override public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - if (level.getBlockEntity(pos) instanceof StorageSacBlockEntity sac && sac.canPlayerOpenInv(player)) { + if (level.getBlockEntity(pos) instanceof StorageSacBlockEntity sac && sac.canPlayerInteract(player)) { if (!level.isClientSide) { NetworkHooks.openScreen((ServerPlayer) player, sac, buffer -> buffer.writeBlockPos(pos)); SoundUtil.broadcastBlockSound((ServerLevel) level, pos, ModSoundEvents.UI_STORAGE_SAC_OPEN); diff --git a/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlockEntity.java index 225b504e4..3ed424c93 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/storagesac/StorageSacBlockEntity.java @@ -3,11 +3,13 @@ import com.github.elenterius.biomancy.block.base.SimpleContainerBlockEntity; import com.github.elenterius.biomancy.init.ModBlockEntities; import com.github.elenterius.biomancy.init.ModCapabilities; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.HandlerBehaviors; +import com.github.elenterius.biomancy.inventory.InventoryHandler; +import com.github.elenterius.biomancy.inventory.InventoryHandlers; +import com.github.elenterius.biomancy.inventory.ItemHandlerUtil; import com.github.elenterius.biomancy.menu.StorageSacMenu; import com.github.elenterius.biomancy.styles.TextComponentUtil; import com.github.elenterius.biomancy.util.ItemStackCounter; +import com.github.elenterius.biomancy.util.PlayerInteractionPredicate; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -16,7 +18,6 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.util.Mth; -import net.minecraft.world.Containers; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -24,7 +25,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; @@ -33,30 +33,29 @@ import java.util.ArrayList; import java.util.List; -public class StorageSacBlockEntity extends SimpleContainerBlockEntity { +public class StorageSacBlockEntity extends SimpleContainerBlockEntity implements PlayerInteractionPredicate { public static final int SLOTS = 3 * 5; public static final String TOP5_BY_COUNT_KEY = "Top5ByCount"; public static final String INVENTORY_KEY = "Inventory"; - private final BehavioralInventory inventory; + private final InventoryHandler inventory; protected final ItemStackCounter itemCounter = new ItemStackCounter(); private List top5ItemsByCount = List.of(); public StorageSacBlockEntity(BlockPos pos, BlockState state) { super(ModBlockEntities.STORAGE_SAC.get(), pos, state); - inventory = BehavioralInventory.createServerContents(SLOTS, HandlerBehaviors::denyItemWithFilledInventory, this::canPlayerOpenContainer, this::onContentsChanged); + inventory = InventoryHandlers.denyItemWithFilledInventory(SLOTS, this::onInventoryChanged); } @Nullable @Override public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { - return StorageSacMenu.createServerMenu(containerId, playerInventory, inventory); + return StorageSacMenu.createServerMenu(containerId, playerInventory, this); } - public boolean canPlayerOpenInv(Player player) { - if (level == null || level.getBlockEntity(worldPosition) != this) return false; - return player.distanceToSqr(Vec3.atCenterOf(worldPosition)) < 8d * 8d; + public InventoryHandler getInventory() { + return inventory; } @Override @@ -78,15 +77,17 @@ public boolean isEmpty() { return inventory.isEmpty(); } - protected void onContentsChanged() { + protected void onInventoryChanged() { + if (level == null || level.isClientSide) return; + countAllItems(); setChanged(); syncToClient(); } protected void syncToClient() { - if (level == null) return; - if (level.isClientSide) return; + if (level == null || level.isClientSide) return; + BlockState state = getBlockState(); level.sendBlockUpdated(getBlockPos(), state, state, Block.UPDATE_CLIENTS); //trigger sync to client using the data from getUpdateTag() } @@ -165,14 +166,14 @@ public CompoundTag serializeTop5() { @Override public void dropContainerContents(Level level, BlockPos pos) { - Containers.dropContents(level, pos, inventory); + ItemHandlerUtil.dropContents(level, pos, inventory); } @Nonnull @Override public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { if (!remove && cap == ModCapabilities.ITEM_HANDLER) { - return inventory.getOptionalItemHandler().cast(); + return inventory.getLazyOptional().cast(); } return super.getCapability(cap, side); } diff --git a/src/main/java/com/github/elenterius/biomancy/block/tongue/TongueBlockEntity.java b/src/main/java/com/github/elenterius/biomancy/block/tongue/TongueBlockEntity.java index eea77ccfc..760e15758 100644 --- a/src/main/java/com/github/elenterius/biomancy/block/tongue/TongueBlockEntity.java +++ b/src/main/java/com/github/elenterius/biomancy/block/tongue/TongueBlockEntity.java @@ -2,8 +2,8 @@ import com.github.elenterius.biomancy.block.base.SimpleSyncedBlockEntity; import com.github.elenterius.biomancy.init.ModBlockEntities; -import com.github.elenterius.biomancy.inventory.itemhandler.EnhancedItemHandler; -import com.github.elenterius.biomancy.inventory.itemhandler.SingleItemStackHandler; +import com.github.elenterius.biomancy.inventory.ItemHandlerWrapper; +import com.github.elenterius.biomancy.inventory.SingleItemStackHandler; import com.github.elenterius.biomancy.util.LevelUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; @@ -81,7 +81,7 @@ private void serverTick(ServerLevel level, BlockPos pos, BlockState state) { private void tryToExtractItems(IItemHandler itemHandler) { if (!inventory.isEmpty()) return; - EnhancedItemHandler handler = new EnhancedItemHandler(itemHandler); + ItemHandlerWrapper handler = new ItemHandlerWrapper(itemHandler); ItemStack extractedStack = handler.extractItemAny(ITEM_TRANSFER_AMOUNT, false); if (!extractedStack.isEmpty()) { inventory.insertItem(0, extractedStack, false); diff --git a/src/main/java/com/github/elenterius/biomancy/client/gui/DecomposerScreen.java b/src/main/java/com/github/elenterius/biomancy/client/gui/DecomposerScreen.java index a86f3d9fb..11272633c 100644 --- a/src/main/java/com/github/elenterius/biomancy/client/gui/DecomposerScreen.java +++ b/src/main/java/com/github/elenterius/biomancy/client/gui/DecomposerScreen.java @@ -68,7 +68,7 @@ protected void renderTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY) { } private void drawFuelTooltip(GuiGraphics guiGraphics, int mouseX, int mouseY) { - int maxFuel = menu.getMAxFuelAmount(); + int maxFuel = menu.getMaxFuelAmount(); int fuelAmount = menu.getFuelAmount(); int totalFuelCost = menu.getFuelCost(); GuiRenderUtil.drawFuelTooltip(font, guiGraphics, mouseX, mouseY, maxFuel, fuelAmount, totalFuelCost); diff --git a/src/main/java/com/github/elenterius/biomancy/client/gui/tooltip/StorageSacTooltipClientComponent.java b/src/main/java/com/github/elenterius/biomancy/client/gui/tooltip/StorageSacTooltipClientComponent.java index e83f7ed6f..ef22490f4 100644 --- a/src/main/java/com/github/elenterius/biomancy/client/gui/tooltip/StorageSacTooltipClientComponent.java +++ b/src/main/java/com/github/elenterius/biomancy/client/gui/tooltip/StorageSacTooltipClientComponent.java @@ -1,7 +1,7 @@ package com.github.elenterius.biomancy.client.gui.tooltip; import com.github.elenterius.biomancy.BiomancyMod; -import com.github.elenterius.biomancy.inventory.itemhandler.EnhancedItemHandler; +import com.github.elenterius.biomancy.inventory.ItemHandlerWrapper; import com.github.elenterius.biomancy.tooltip.StorageSacTooltipComponent; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; @@ -15,7 +15,7 @@ public class StorageSacTooltipClientComponent implements ClientTooltipComponent public static final ResourceLocation TEXTURE = BiomancyMod.createRL("textures/gui/tooltip_storage_sac.png"); private static final int OFFSET = 2; - private final @Nullable EnhancedItemHandler itemHandler; + private final @Nullable ItemHandlerWrapper itemHandler; private final boolean isStorageSacEmpty; public StorageSacTooltipClientComponent(StorageSacTooltipComponent tooltip) { diff --git a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DigestingRecipe.java b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DigestingRecipe.java index e9d2c8dd9..02af715ff 100644 --- a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DigestingRecipe.java +++ b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DigestingRecipe.java @@ -1,8 +1,7 @@ package com.github.elenterius.biomancy.crafting.recipe; -import net.minecraft.world.Container; import net.minecraft.world.item.crafting.Ingredient; -public non-sealed interface DigestingRecipe extends ProcessingRecipe { +public non-sealed interface DigestingRecipe extends ProcessingRecipe { Ingredient getIngredient(); } diff --git a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DynamicProcessingRecipe.java b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DynamicProcessingRecipe.java index 110c5c36c..f9735fa97 100644 --- a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DynamicProcessingRecipe.java +++ b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/DynamicProcessingRecipe.java @@ -2,14 +2,13 @@ import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeType; /** * Recipe with dynamic cost, time and/or result */ -public abstract non-sealed class DynamicProcessingRecipe implements ProcessingRecipe { +public abstract non-sealed class DynamicProcessingRecipe implements ProcessingRecipe { private final ResourceLocation id; private final RecipeType type; diff --git a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/ProcessingRecipe.java b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/ProcessingRecipe.java index 2aa6e92b1..97215cc17 100644 --- a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/ProcessingRecipe.java +++ b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/ProcessingRecipe.java @@ -3,13 +3,13 @@ import net.minecraft.world.Container; import net.minecraft.world.item.crafting.Recipe; -public sealed interface ProcessingRecipe extends Recipe permits DigestingRecipe, DynamicProcessingRecipe, StaticProcessingRecipe { +public sealed interface ProcessingRecipe extends Recipe permits DigestingRecipe, DynamicProcessingRecipe, StaticProcessingRecipe { - int getCraftingTimeTicks(T inputInventory); + int getCraftingTimeTicks(Container inputInventory); - int getCraftingCostNutrients(T inputInventory); + int getCraftingCostNutrients(Container inputInventory); - default boolean isRecipeEqual(ProcessingRecipe other) { + default boolean isRecipeEqual(ProcessingRecipe other) { return getId().equals(other.getId()); } diff --git a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/StaticProcessingRecipe.java b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/StaticProcessingRecipe.java index 240bdb251..56fa4ac27 100644 --- a/src/main/java/com/github/elenterius/biomancy/crafting/recipe/StaticProcessingRecipe.java +++ b/src/main/java/com/github/elenterius/biomancy/crafting/recipe/StaticProcessingRecipe.java @@ -3,7 +3,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Container; -public abstract non-sealed class StaticProcessingRecipe implements ProcessingRecipe { +public abstract non-sealed class StaticProcessingRecipe implements ProcessingRecipe { private final ResourceLocation id; diff --git a/src/main/java/com/github/elenterius/biomancy/crafting/state/FuelConsumingRecipeCraftingStateData.java b/src/main/java/com/github/elenterius/biomancy/crafting/state/FuelConsumingRecipeCraftingStateData.java index 64a8c74a5..9f0845c76 100644 --- a/src/main/java/com/github/elenterius/biomancy/crafting/state/FuelConsumingRecipeCraftingStateData.java +++ b/src/main/java/com/github/elenterius/biomancy/crafting/state/FuelConsumingRecipeCraftingStateData.java @@ -2,9 +2,8 @@ import com.github.elenterius.biomancy.crafting.recipe.ProcessingRecipe; import com.github.elenterius.biomancy.util.fuel.IFuelHandler; -import net.minecraft.world.Container; -public abstract class FuelConsumingRecipeCraftingStateData, C extends Container> extends RecipeCraftingStateData { +public abstract class FuelConsumingRecipeCraftingStateData extends RecipeCraftingStateData { public static final int FUEL_INDEX = 3; diff --git a/src/main/java/com/github/elenterius/biomancy/crafting/state/RecipeCraftingStateData.java b/src/main/java/com/github/elenterius/biomancy/crafting/state/RecipeCraftingStateData.java index 56510c342..74f63504f 100644 --- a/src/main/java/com/github/elenterius/biomancy/crafting/state/RecipeCraftingStateData.java +++ b/src/main/java/com/github/elenterius/biomancy/crafting/state/RecipeCraftingStateData.java @@ -11,7 +11,7 @@ import java.util.Optional; -public abstract class RecipeCraftingStateData, C extends Container> implements ContainerData { +public abstract class RecipeCraftingStateData implements ContainerData { public static final String RECIPE_ID_KEY = "RecipeId"; public static final String TIME_ELAPSED_KEY = "TimeElapsed"; @@ -64,7 +64,7 @@ public Optional getCraftingGoalRecipe(Level level) { return Optional.empty(); } - public void setCraftingGoalRecipe(T recipe, C inputInventory) { + public void setCraftingGoalRecipe(T recipe, Container inputInventory) { recipeId = recipe.getId(); timeForCompletion = recipe.getCraftingTimeTicks(inputInventory); nutrientsCost = recipe.getCraftingCostNutrients(inputInventory); diff --git a/src/main/java/com/github/elenterius/biomancy/integration/jei/BiomancyJeiPlugin.java b/src/main/java/com/github/elenterius/biomancy/integration/jei/BiomancyJeiPlugin.java index d0e16a74a..b2019fe6b 100644 --- a/src/main/java/com/github/elenterius/biomancy/integration/jei/BiomancyJeiPlugin.java +++ b/src/main/java/com/github/elenterius/biomancy/integration/jei/BiomancyJeiPlugin.java @@ -11,7 +11,7 @@ import com.github.elenterius.biomancy.menu.BioLabMenu; import com.github.elenterius.biomancy.menu.DecomposerMenu; import com.github.elenterius.biomancy.menu.DigesterMenu; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; +import com.github.elenterius.biomancy.menu.ISlotZone; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.constants.RecipeTypes; diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/BaseInventory.java b/src/main/java/com/github/elenterius/biomancy/inventory/BaseInventory.java deleted file mode 100644 index b72a17c5a..000000000 --- a/src/main/java/com/github/elenterius/biomancy/inventory/BaseInventory.java +++ /dev/null @@ -1,240 +0,0 @@ -package com.github.elenterius.biomancy.inventory; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemHandlerHelper; - -import java.util.List; -import java.util.function.Consumer; -import java.util.function.Predicate; - -public abstract class BaseInventory> implements Container, INBTSerializable { - - protected T itemHandler; - protected LazyOptional optionalItemHandler; - - protected Predicate canPlayerAccessInventory = x -> true; - protected Notify markDirtyNotifier = () -> {}; - protected Consumer onOpenInventory = player -> {}; - protected Consumer onCloseInventory = player -> {}; - - BaseInventory() {} - - BaseInventory(T itemHandler) { - this.itemHandler = itemHandler; - optionalItemHandler = LazyOptional.of(() -> this.itemHandler); - } - - public T getItemHandler() { - return itemHandler; - } - - public LazyOptional getOptionalItemHandler() { - return optionalItemHandler; - } - - public void invalidate() { - optionalItemHandler.invalidate(); - } - - public void revive() { - optionalItemHandler = LazyOptional.of(() -> itemHandler); - } - - @Override - public CompoundTag serializeNBT() { - return itemHandler.serializeNBT(); - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - itemHandler.deserializeNBT(nbt); - } - - @Override - public boolean stillValid(Player player) { - return canPlayerAccessInventory.test(player); - } - - @Override - public void setChanged() { - markDirtyNotifier.invoke(); - } - - @Override - public void startOpen(Player player) { - onOpenInventory.accept(player); - } - - @Override - public void stopOpen(Player player) { - onCloseInventory.accept(player); - } - - public void setCanPlayerAccessInventory(Predicate predicate) { - canPlayerAccessInventory = predicate; - } - - public void setMarkDirtyNotifier(Notify callback) { - markDirtyNotifier = callback; - } - - public void setOpenInventoryConsumer(Consumer consumer) { - onOpenInventory = consumer; - } - - public void setCloseInventoryConsumer(Consumer consumer) { - onCloseInventory = consumer; - } - - @Override - public int getContainerSize() { - return itemHandler.getSlots(); - } - - @Override - public int getMaxStackSize() { - return itemHandler.getSlotLimit(0); - } - - @Override - public boolean isEmpty() { - for (int i = 0; i < itemHandler.getSlots(); i++) { - if (!itemHandler.getStackInSlot(i).isEmpty()) return false; - } - return true; - } - - public boolean isFull() { - for (int i = 0; i < itemHandler.getSlots(); i++) { - ItemStack stack = itemHandler.getStackInSlot(i); - if (stack.isEmpty() || stack.getCount() < itemHandler.getSlotLimit(i)) return false; - } - return true; - } - - @Override - public boolean canPlaceItem(int index, ItemStack stack) { - return itemHandler.isItemValid(index, stack); - } - - public boolean doesItemStackFit(int index, ItemStack stack) { - if (!itemHandler.isItemValid(index, stack)) return false; - ItemStack remainder = itemHandler.insertItem(index, stack, true); - return remainder.isEmpty(); - } - - public boolean doesItemStackFit(ItemStack stack) { - for (int i = 0; i < itemHandler.getSlots(); i++) { - if (!itemHandler.isItemValid(i, stack)) return false; - stack = itemHandler.insertItem(i, stack, true); - if (stack.isEmpty()) return true; - } - return false; - } - - private class SimulatedInventory { - - int slots = itemHandler.getSlots(); - int[] availableSlotSpace = new int[slots]; - ItemStack[] itemInSlot = new ItemStack[slots]; - - public SimulatedInventory() { - for (int i = 0; i < slots; i++) { - ItemStack stack = itemHandler.getStackInSlot(i); - itemInSlot[i] = stack; - availableSlotSpace[i] = itemHandler.getSlotLimit(i) - stack.getCount(); - } - } - - boolean canInsertAt(int index, ItemStack stack) { - if (stack.isEmpty() || availableSlotSpace[index] <= 0) return false; - if (!itemHandler.isItemValid(index, stack)) return false; - if (itemInSlot[index].isEmpty()) return true; - return ItemHandlerHelper.canItemStacksStack(stack, itemInSlot[index]); - } - - ItemStack insertAt(int index, ItemStack stack) { - if (!canInsertAt(index, stack)) return stack; - - int insertAmount = Math.min(availableSlotSpace[index], stack.getCount()); - availableSlotSpace[index] -= insertAmount; - - if (itemInSlot[index].isEmpty()) itemInSlot[index] = stack; - - return ItemHandlerHelper.copyStackWithSize(stack, stack.getCount() - insertAmount); //remainder - } - } - - public boolean doAllItemsFit(List items) { - SimulatedInventory inv = new SimulatedInventory(); - - for (ItemStack stack : items) { - if (stack.isEmpty()) continue; - - for (int i = 0; i < inv.slots; i++) { - stack = inv.insertAt(i, stack); //override stack with remainder - } - - if (!stack.isEmpty()) return false; - } - - return true; - } - - public ItemStack insertItemStack(int index, ItemStack stack) { - return insertItemStack(index, stack, false); - } - - public ItemStack insertItemStack(int index, ItemStack stack, boolean simulate) { - return itemHandler.insertItem(index, stack, simulate); - } - - public ItemStack insertItemStack(ItemStack stack) { - return insertItemStack(stack, false); - } - - public ItemStack insertItemStack(ItemStack stack, boolean simulate) { - for (int i = 0; i < itemHandler.getSlots(); i++) { - stack = itemHandler.insertItem(i, stack, simulate); - if (stack.isEmpty()) return ItemStack.EMPTY; - } - return stack; - } - - @Override - public ItemStack getItem(int index) { - return itemHandler.getStackInSlot(index); - } - - @Override - public ItemStack removeItem(int index, int count) { - if (count < 0) throw new IllegalArgumentException("Invalid count: " + count); - return itemHandler.extractItem(index, count, false); - } - - @Override - public ItemStack removeItemNoUpdate(int index) { - int maxStackSize = itemHandler.getSlotLimit(index); - return itemHandler.extractItem(index, maxStackSize, false); - } - - @Override - public void setItem(int index, ItemStack stack) { - itemHandler.setStackInSlot(index, stack); - } - - @Override - public void clearContent() { - for (int i = 0; i < itemHandler.getSlots(); ++i) { - itemHandler.setStackInSlot(i, ItemStack.EMPTY); - } - } - -} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/BehavioralInventory.java b/src/main/java/com/github/elenterius/biomancy/inventory/BehavioralInventory.java deleted file mode 100644 index 51fb6278d..000000000 --- a/src/main/java/com/github/elenterius/biomancy/inventory/BehavioralInventory.java +++ /dev/null @@ -1,79 +0,0 @@ -package com.github.elenterius.biomancy.inventory; - -import com.github.elenterius.biomancy.inventory.itemhandler.FixedSizeItemStackHandler; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; - -import java.util.function.Predicate; -import java.util.function.UnaryOperator; - -@Deprecated -public class BehavioralInventory> extends BaseInventory { - - private final T behavioralItemHandler; - - BehavioralInventory(int slotAmount) { - //noinspection unchecked - itemHandler = (T) new FixedSizeItemStackHandler(slotAmount) { - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - setChanged(); - } - }; - behavioralItemHandler = itemHandler; - optionalItemHandler = LazyOptional.of(() -> behavioralItemHandler); - } - - BehavioralInventory(int slotAmount, UnaryOperator operator) { - //noinspection unchecked - T handler = (T) new FixedSizeItemStackHandler(slotAmount) { - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - setChanged(); - } - }; - itemHandler = handler; - behavioralItemHandler = operator.apply(handler); - optionalItemHandler = LazyOptional.of(() -> behavioralItemHandler); - } - - BehavioralInventory(int slotAmount, UnaryOperator operator, Predicate canPlayerAccessInventory, Notify markDirtyNotifier) { - this(slotAmount, operator); - this.canPlayerAccessInventory = canPlayerAccessInventory; - this.markDirtyNotifier = markDirtyNotifier; - } - - BehavioralInventory(int slotAmount, Predicate canPlayerAccessInventory, Notify markDirtyNotifier) { - this(slotAmount); - this.canPlayerAccessInventory = canPlayerAccessInventory; - this.markDirtyNotifier = markDirtyNotifier; - } - - public static > BehavioralInventory createServerContents(int slotAmount, UnaryOperator operator, Predicate canPlayerAccessInventory, Notify markDirtyNotifier) { - return new BehavioralInventory<>(slotAmount, operator, canPlayerAccessInventory, markDirtyNotifier); - } - - public static > BehavioralInventory createServerContents(int slotAmount, Predicate canPlayerAccessInventory, Notify markDirtyNotifier) { - return new BehavioralInventory<>(slotAmount, canPlayerAccessInventory, markDirtyNotifier); - } - - public static > BehavioralInventory createClientContents(int slotAmount) { - return new BehavioralInventory<>(slotAmount); - } - - public T getItemHandlerWithBehavior() { - return behavioralItemHandler; - } - - @Override - public void revive() { - optionalItemHandler = LazyOptional.of(() -> behavioralItemHandler); - } - -} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/BehavioralItemHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/BehavioralItemHandler.java new file mode 100644 index 000000000..454f2643e --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/inventory/BehavioralItemHandler.java @@ -0,0 +1,147 @@ +package com.github.elenterius.biomancy.inventory; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.function.Predicate; + +public interface BehavioralItemHandler extends IItemHandler { + + IItemHandler withoutBehavior(); + + abstract class Wrapper implements BehavioralItemHandler { + + protected final T itemHandler; + + public Wrapper(T itemHandler) { + this.itemHandler = itemHandler; + } + + @Override + public IItemHandler withoutBehavior() { + return itemHandler; + } + + @Override + public int getSlots() { + return itemHandler.getSlots(); + } + + @Nonnull + @Override + public ItemStack getStackInSlot(int slot) { + return itemHandler.getStackInSlot(slot); + } + + @Nonnull + @Override + public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + return itemHandler.insertItem(slot, stack, simulate); + } + + @Nonnull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + return itemHandler.extractItem(slot, amount, simulate); + } + + @Override + public int getSlotLimit(int slot) { + return itemHandler.getSlotLimit(slot); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return itemHandler.isItemValid(slot, stack); + } + + } + + /** + * prevents item insertion, therefore only allowing item extraction (e.g. output slots). + */ + class DenyInput extends Wrapper implements SerializableItemHandler { + + public DenyInput(SerializableItemHandler itemHandler) { + super(itemHandler); + } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) { + return false; + } + + @Override + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + return stack; + } + + @Override + public CompoundTag serializeNBT() { + return itemHandler.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag tag) { + itemHandler.deserializeNBT(tag); + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + itemHandler.setStackInSlot(slot, stack); + } + } + + /** + * only allows item insertion of matching items + */ + class FilterInput> extends Wrapper implements SerializableItemHandler { + + private final List filters; + + public FilterInput(SerializableItemHandler itemHandler, List slotFilters) { + super(itemHandler); + assert slotFilters.size() == itemHandler.getSlots(); + filters = slotFilters; + } + + private boolean isInvalidSlot(int slot) { + return slot < 0 || slot >= filters.size(); + } + + @Override + public boolean isItemValid(int slot, @Nonnull ItemStack stack) { + if (isInvalidSlot(slot)) return false; + return filters.get(slot).test(stack) && itemHandler.isItemValid(slot, stack); + } + + @Override + @Nonnull + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + if (isInvalidSlot(slot)) return stack; + if (!filters.get(slot).test(stack)) return stack; + return itemHandler.insertItem(slot, stack, simulate); + } + + @Override + public CompoundTag serializeNBT() { + return itemHandler.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag tag) { + itemHandler.deserializeNBT(tag); + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + itemHandler.setStackInSlot(slot, stack); + } + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/FixedSizeItemStackHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/FixedSizeItemStackHandler.java similarity index 95% rename from src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/FixedSizeItemStackHandler.java rename to src/main/java/com/github/elenterius/biomancy/inventory/FixedSizeItemStackHandler.java index 7e5fbba7f..646a9113f 100644 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/FixedSizeItemStackHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/inventory/FixedSizeItemStackHandler.java @@ -1,4 +1,4 @@ -package com.github.elenterius.biomancy.inventory.itemhandler; +package com.github.elenterius.biomancy.inventory; import com.github.elenterius.biomancy.init.ModItems; import com.github.elenterius.biomancy.item.GiftSacItem; @@ -11,7 +11,7 @@ import java.util.ArrayList; import java.util.List; -public class FixedSizeItemStackHandler extends ItemStackHandler { +public class FixedSizeItemStackHandler extends ItemStackHandler implements SerializableItemHandler { public FixedSizeItemStackHandler(int size) { super(size); diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/InjectorItemInventory.java b/src/main/java/com/github/elenterius/biomancy/inventory/InjectorItemInventory.java index 84439d553..b65185c82 100644 --- a/src/main/java/com/github/elenterius/biomancy/inventory/InjectorItemInventory.java +++ b/src/main/java/com/github/elenterius/biomancy/inventory/InjectorItemInventory.java @@ -1,15 +1,15 @@ package com.github.elenterius.biomancy.inventory; import com.github.elenterius.biomancy.api.serum.SerumContainer; -import com.github.elenterius.biomancy.inventory.itemhandler.LargeSingleItemStackHandler; -import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.IItemHandler; -public class InjectorItemInventory extends BaseInventory { +public class InjectorItemInventory { private final ItemStack cachedInventoryHost; + private final LargeSingleItemStackHandler itemHandler; + private final LazyOptional optionalItemHandler; private InjectorItemInventory(short maxSlotSize, ItemStack inventoryHost) { itemHandler = new LargeSingleItemStackHandler(maxSlotSize) { @@ -21,91 +21,40 @@ public boolean isItemValid(ItemStack stack) { @Override protected void onContentsChanged() { - setChanged(); + serializeToHost(); } }; optionalItemHandler = LazyOptional.of(() -> itemHandler); cachedInventoryHost = inventoryHost; } + public static InjectorItemInventory create(short maxSlotSize, ItemStack inventoryHost) { + InjectorItemInventory inventory = new InjectorItemInventory(maxSlotSize, inventoryHost); + inventory.deserializeFromHost(); + return inventory; + } + private void serializeToHost() { cachedInventoryHost.getOrCreateTag().put("inventory", itemHandler.serializeNBT()); } private void deserializeFromHost() { - deserializeNBT(cachedInventoryHost.getOrCreateTag().getCompound("inventory")); - } - - @Override - public void setChanged() { - serializeToHost(); - super.setChanged(); - } - - @Override - public boolean stillValid(Player player) { - if (cachedInventoryHost.isEmpty()) return false; - return super.stillValid(player); - } - - @Override - public int getMaxStackSize() { - return itemHandler.getMaxAmount(); - } - - @Override - public boolean isEmpty() { - return itemHandler.isEmpty(); - } - - @Override - public boolean isFull() { - return itemHandler.isFull(); + itemHandler.deserializeNBT(cachedInventoryHost.getOrCreateTag().getCompound("inventory")); } - @Override - public boolean doesItemStackFit(ItemStack stack) { - ItemStack remainder = itemHandler.insertItem(0, stack, true); - return remainder.isEmpty(); + public boolean stillValid() { + return !cachedInventoryHost.isEmpty(); } - @Override - public ItemStack insertItemStack(ItemStack stack) { - return itemHandler.insertItem(0, stack, false); - } - - - @Override - public ItemStack removeItemNoUpdate(int index) { - return itemHandler.extractItem(index, itemHandler.getMaxAmount(), false); - } - - @Override - public void clearContent() { - itemHandler.setStackInSlot(0, ItemStack.EMPTY); - } - - @Override public LargeSingleItemStackHandler getItemHandler() { deserializeFromHost(); //prime cheese - return super.getItemHandler(); + return itemHandler; } - @Override - public LazyOptional getOptionalItemHandler() { + public LazyOptional getLazyOptional() { deserializeFromHost(); //prime cheese //we now get the inventory from the ItemStack NBT, this makes it available on the client as well if someone gets the cap - return super.getOptionalItemHandler(); - } - - public static InjectorItemInventory createServerContents(short maxSlotSize, ItemStack inventoryHost) { - InjectorItemInventory inventory = new InjectorItemInventory(maxSlotSize, inventoryHost); - inventory.deserializeFromHost(); - return inventory; - } - - public static InjectorItemInventory createClientContents(short maxSlotSize, ItemStack inventoryHost) { - return new InjectorItemInventory(maxSlotSize, inventoryHost); + return optionalItemHandler; } } diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandler.java new file mode 100644 index 000000000..a3e0477f4 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandler.java @@ -0,0 +1,102 @@ +package com.github.elenterius.biomancy.inventory; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.wrapper.RecipeWrapper; +import org.jetbrains.annotations.NotNull; + +public final class InventoryHandler implements SerializableItemHandler { + + private final SerializableItemHandler itemHandler; + private LazyOptional optionalItemHandler; + + private final RecipeWrapper recipeWrapper; + + public InventoryHandler(SerializableItemHandler itemHandler) { + this.itemHandler = itemHandler; + recipeWrapper = new RecipeWrapper(itemHandler); + optionalItemHandler = LazyOptional.of(() -> itemHandler); + } + + public boolean isEmpty() { + for (int i = 0; i < itemHandler.getSlots(); i++) { + if (!itemHandler.getStackInSlot(i).isEmpty()) return false; + } + return true; + } + + @Override + public CompoundTag serializeNBT() { + return itemHandler.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + itemHandler.deserializeNBT(nbt); + } + + public SerializableItemHandler get() { + return itemHandler; + } + + /** + * @return raw item handler without any attached behavior + */ + public IItemHandler getRaw() { + return itemHandler instanceof BehavioralItemHandler handler ? handler.withoutBehavior() : itemHandler; + } + + public LazyOptional getLazyOptional() { + return optionalItemHandler; + } + + public RecipeWrapper getRecipeWrapper() { + return recipeWrapper; + } + + public void invalidate() { + optionalItemHandler.invalidate(); + } + + public void revive() { + optionalItemHandler = LazyOptional.of(() -> itemHandler); + } + + @Override + public void setStackInSlot(int slot, @NotNull ItemStack stack) { + itemHandler.setStackInSlot(slot, stack); + } + + @Override + public int getSlots() { + return itemHandler.getSlots(); + } + + @Override + public @NotNull ItemStack getStackInSlot(int slot) { + return itemHandler.getStackInSlot(slot); + } + + @Override + public @NotNull ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { + return itemHandler.insertItem(slot, stack, simulate); + } + + @Override + public @NotNull ItemStack extractItem(int slot, int amount, boolean simulate) { + return itemHandler.extractItem(slot, amount, simulate); + } + + @Override + public int getSlotLimit(int slot) { + return itemHandler.getSlotLimit(slot); + } + + @Override + public boolean isItemValid(int slot, ItemStack stack) { + return itemHandler.isItemValid(slot, stack); + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandlers.java b/src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandlers.java new file mode 100644 index 000000000..22d079eab --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/inventory/InventoryHandlers.java @@ -0,0 +1,164 @@ +package com.github.elenterius.biomancy.inventory; + +import com.github.elenterius.biomancy.api.nutrients.Nutrients; +import com.github.elenterius.biomancy.init.ModCapabilities; +import net.minecraft.world.item.BundleItem; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.util.LazyOptional; +import net.minecraftforge.items.IItemHandler; + +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.IntStream; + +/** + * allows us to add specific behavior to any IItemHandler or IFluidHandler without the need of subclassing + */ +public final class InventoryHandlers { + + public static final Predicate EMPTY_ITEM_INVENTORY_PREDICATE = stack -> { + // if (stack.getItem() instanceof BlockItem blockItem) { + // Block block = blockItem.getBlock(); + // if (block instanceof ShulkerBoxBlock) { + // return stack.getTagElement("BlockEntityTag") == null; + // } + // } + + if (stack.getItem() instanceof BundleItem) return false; + if (!stack.getItem().canFitInsideContainerItems()) return false; + + LazyOptional capability = stack.getCapability(ModCapabilities.ITEM_HANDLER); + final boolean[] isEmpty = {true}; + capability.ifPresent(itemHandler -> { + int slots = itemHandler.getSlots(); + if (slots > 200) { //if we have more than 200 slots we don't bother checking them and just return false + isEmpty[0] = false; + return; + } + //ItemHandler cap doesn't have a isEmpty() method which forces us to sequentially check every slot if it is empty + for (int i = 0; i < slots; i++) { + if (!itemHandler.getStackInSlot(i).isEmpty()) { + isEmpty[0] = false; + break; + } + } + }); + return isEmpty[0]; + }; + + private InventoryHandlers() {} + + /** + * default item handler behavior + */ + public static InventoryHandler standard(int slotAmount) { + return new InventoryHandler(new FixedSizeItemStackHandler(slotAmount)); + } + + public static InventoryHandler standard(int slotAmount, Notify onInventoryChanged) { + FixedSizeItemStackHandler handler = new FixedSizeItemStackHandler(slotAmount) { + @Override + protected void onContentsChanged(int slot) { + onInventoryChanged.invoke(); + } + }; + return new InventoryHandler(handler); + } + + /** + * prevents item insertion, only item extraction is possible (e.g. output inventories) + */ + public static InventoryHandler denyInput(T itemStackHandler) { + return new InventoryHandler(new BehavioralItemHandler.DenyInput(itemStackHandler)); + } + + /** + * prevents item insertion, only item extraction is possible (e.g. output inventories) + */ + public static InventoryHandler denyInput(int slotAmount, Notify onInventoryChanged) { + FixedSizeItemStackHandler handler = new FixedSizeItemStackHandler(slotAmount) { + @Override + protected void onContentsChanged(int slot) { + onInventoryChanged.invoke(); + } + }; + return new InventoryHandler(new BehavioralItemHandler.DenyInput(handler)); + } + + /** + * only allows item insertion of valid items + */ + public static > InventoryHandler filterInput(int slotAmount, List slotFilters) { + return filterInput(new FixedSizeItemStackHandler(slotAmount), slotFilters); + } + + /** + * only allows item insertion of valid items + */ + public static > InventoryHandler filterInput(int slotAmount, List slotFilters, Notify onInventoryChanged) { + FixedSizeItemStackHandler handler = new FixedSizeItemStackHandler(slotAmount) { + @Override + protected void onContentsChanged(int slot) { + onInventoryChanged.invoke(); + } + }; + return filterInput(handler, slotFilters); + } + + /** + * only allows item insertion of valid items + */ + public static > InventoryHandler filterInput(T itemStackHandler, List slotFilters) { + return new InventoryHandler(new BehavioralItemHandler.FilterInput<>(itemStackHandler, slotFilters)); + } + + /** + * prevents nesting of items with inventories,
+ * i.e. insertion of filled shulker boxes and items with filled inventories (item handler capability) + */ + public static InventoryHandler denyItemWithFilledInventory(T itemHandler) { + return new InventoryHandler(new BehavioralItemHandler.FilterInput<>(itemHandler, IntStream.range(0, itemHandler.getSlots()).mapToObj(x -> EMPTY_ITEM_INVENTORY_PREDICATE).toList())); + } + + /** + * prevents nesting of items with inventories,
+ * i.e. insertion of filled shulker boxes and items with filled inventories (item handler capability) + */ + public static InventoryHandler denyItemWithFilledInventory(int slotAmount, Notify onInventoryChanged) { + FixedSizeItemStackHandler handler = new FixedSizeItemStackHandler(slotAmount) { + @Override + protected void onContentsChanged(int slot) { + onInventoryChanged.invoke(); + } + }; + return denyItemWithFilledInventory(handler); + } + + /** + * only allows the insertion of items that are biofuel (solid & fluid container) + */ + public static InventoryHandler filterFuel(int slotAmount) { + return filterFuel(new FixedSizeItemStackHandler(slotAmount)); + } + + /** + * only allows the insertion of items that are biofuel (solid & fluid container) + */ + public static InventoryHandler filterFuel(int slotAmount, Notify onInventoryChanged) { + FixedSizeItemStackHandler handler = new FixedSizeItemStackHandler(slotAmount) { + @Override + protected void onContentsChanged(int slot) { + onInventoryChanged.invoke(); + } + }; + return filterFuel(handler); + } + + /** + * only allows the insertion of items that are biofuel (solid & fluid container) + */ + public static InventoryHandler filterFuel(T itemHandler) { + return filterInput(itemHandler, IntStream.range(0, itemHandler.getSlots()).mapToObj(x -> Nutrients.FUEL_PREDICATE).toList()); + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerUtil.java b/src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerUtil.java new file mode 100644 index 000000000..9c3860b82 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerUtil.java @@ -0,0 +1,127 @@ +package com.github.elenterius.biomancy.inventory; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.Containers; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; + +import java.util.List; + +public final class ItemHandlerUtil { + + private ItemHandlerUtil() {} + + public static void dropContents(Level level, BlockPos pos, IItemHandler itemHandler) { + dropContents(level, pos.getX(), pos.getY(), pos.getZ(), itemHandler); + } + + public static void dropContents(Level level, Entity entity, IItemHandler itemHandler) { + dropContents(level, entity.getX(), entity.getY(), entity.getZ(), itemHandler); + } + + public static void dropContents(Level level, double x, double y, double z, IItemHandler itemHandler) { + if (level.isClientSide()) return; + + for (int slot = 0; slot < itemHandler.getSlots(); slot++) { + Containers.dropItemStack(level, x, y, z, itemHandler.extractItem(slot, Integer.MAX_VALUE, false)); + } + } + + public static boolean doesItemFit(IItemHandler itemHandler, int index, ItemStack stack) { + if (!itemHandler.isItemValid(index, stack)) return false; + ItemStack remainder = itemHandler.insertItem(index, stack, true); + return remainder.isEmpty(); + } + + public static boolean doesItemFit(IItemHandler itemHandler, ItemStack stack) { + for (int i = 0; i < itemHandler.getSlots(); i++) { + if (!itemHandler.isItemValid(i, stack)) continue; + stack = itemHandler.insertItem(i, stack, true); + if (stack.isEmpty()) return true; + } + return false; + } + + public static ItemStack insertItem(IItemHandler itemHandler, int slot, ItemStack stack) { + return itemHandler.insertItem(slot, stack, false); + } + + public static ItemStack insertItem(IItemHandler itemHandler, ItemStack stack) { + return insertItem(itemHandler, stack, false); + } + + public static ItemStack insertItem(IItemHandler itemHandler, ItemStack stack, boolean simulate) { + if (stack.isEmpty()) return stack; + + for (int i = 0; i < itemHandler.getSlots(); i++) { + stack = itemHandler.insertItem(i, stack, simulate); + if (stack.isEmpty()) return ItemStack.EMPTY; + } + return stack; + } + + public static boolean doAllItemsFit(IItemHandler itemHandler, List items) { + InsertSimulation simulation = new InsertSimulation(itemHandler); + return simulation.insertAllItems(items); + } + + private static class InsertSimulation { + + private final IItemHandler itemHandler; + int slots; + int[] availableSlotSpace; + ItemStack[] itemInSlot; + + private InsertSimulation(IItemHandler itemHandler) { + this.itemHandler = itemHandler; + + slots = itemHandler.getSlots(); + availableSlotSpace = new int[slots]; + itemInSlot = new ItemStack[slots]; + + for (int i = 0; i < slots; i++) { + ItemStack stack = itemHandler.getStackInSlot(i); + itemInSlot[i] = stack; + availableSlotSpace[i] = itemHandler.getSlotLimit(i) - stack.getCount(); + } + } + + private boolean canInsertItem(int index, ItemStack stack) { + if (stack.isEmpty() || availableSlotSpace[index] <= 0) return false; + if (!itemHandler.isItemValid(index, stack)) return false; + if (itemInSlot[index].isEmpty()) return true; + return ItemHandlerHelper.canItemStacksStack(stack, itemInSlot[index]); + } + + private ItemStack insertItem(int index, ItemStack stack) { + if (!canInsertItem(index, stack)) return stack; + + int insertAmount = Math.min(availableSlotSpace[index], stack.getCount()); + availableSlotSpace[index] -= insertAmount; + + if (itemInSlot[index].isEmpty()) itemInSlot[index] = stack; + + return stack.copyWithCount(stack.getCount() - insertAmount); //remainder + } + + private boolean insertAllItems(List items) { + for (ItemStack stack : items) { + if (stack.isEmpty()) continue; + + for (int i = 0; i < slots; i++) { + stack = insertItem(i, stack); //override stack with remainder + } + + if (!stack.isEmpty()) return false; + } + + return true; + } + + } + +} + diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/EnhancedItemHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerWrapper.java similarity index 88% rename from src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/EnhancedItemHandler.java rename to src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerWrapper.java index a4a457061..737d9ce3f 100644 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/EnhancedItemHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/inventory/ItemHandlerWrapper.java @@ -1,14 +1,15 @@ -package com.github.elenterius.biomancy.inventory.itemhandler; +package com.github.elenterius.biomancy.inventory; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemHandlerHelper; -import javax.annotation.Nonnull; import java.util.Collection; import java.util.function.Predicate; +public record ItemHandlerWrapper(IItemHandler inner) implements DefaultOperations, QueryOperations, TransferOperations {} + interface Forwarding { T inner(); } @@ -53,15 +54,15 @@ default boolean hasAny(Collection items) { return false; } - default boolean doesItemStackFit(int index, ItemStack stack) { + default boolean doesItemFit(int index, ItemStack stack) { if (!inner().isItemValid(index, stack)) return false; ItemStack remainder = inner().insertItem(index, stack, true); return remainder.isEmpty(); } - default boolean doesItemStackFit(ItemStack stack) { + default boolean doesItemFit(ItemStack stack) { for (int i = 0; i < inner().getSlots(); i++) { - if (!inner().isItemValid(i, stack)) return false; + if (!inner().isItemValid(i, stack)) continue; stack = inner().insertItem(i, stack, true); if (stack.isEmpty()) return true; } @@ -70,7 +71,12 @@ default boolean doesItemStackFit(ItemStack stack) { } -interface TransferOperations extends Forwarding { +interface TransferOperations extends IItemHandler, Forwarding { + + default ItemStack insertItem(int slot, ItemStack stack) { + return inner().insertItem(slot, stack, false); + } + default ItemStack insertItem(ItemStack stack) { return insertItem(stack, false); } @@ -102,6 +108,10 @@ default ItemStack insertItemOnExistingFirst(ItemStack stack, boolean simulate) { return insertItem(stack, simulate); } + default ItemStack extractItem(int slot, int amount) { + return inner().extractItem(slot, amount, false); + } + default ItemStack extractItemFirstFound() { return extractItemFirstFound(false); } @@ -173,25 +183,22 @@ else if (ItemHandlerHelper.canItemStacksStack(stackInSlot, extracted)) { } } -interface ForwardingItemHandler extends IItemHandler, Forwarding { +interface DefaultOperations extends IItemHandler, Forwarding { @Override default int getSlots() { return inner().getSlots(); } - @Nonnull @Override default ItemStack getStackInSlot(int slot) { return inner().getStackInSlot(slot); } - @Nonnull @Override default ItemStack insertItem(int slot, ItemStack stack, boolean simulate) { return inner().insertItem(slot, stack, simulate); } - @Nonnull @Override default ItemStack extractItem(int slot, int amount, boolean simulate) { return inner().extractItem(slot, amount, simulate); @@ -207,5 +214,3 @@ default boolean isItemValid(int slot, ItemStack stack) { return inner().isItemValid(slot, stack); } } - -public record EnhancedItemHandler(IItemHandler inner) implements ForwardingItemHandler, TransferOperations, QueryOperations {} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/ItemStackInventory.java b/src/main/java/com/github/elenterius/biomancy/inventory/ItemStackInventory.java index dfcd67614..5ab97a30e 100644 --- a/src/main/java/com/github/elenterius/biomancy/inventory/ItemStackInventory.java +++ b/src/main/java/com/github/elenterius/biomancy/inventory/ItemStackInventory.java @@ -8,11 +8,14 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.ItemStackHandler; -public class ItemStackInventory extends BaseInventory { +public class ItemStackInventory { private final ItemStack cachedInventoryHost; private final InventorySerializer serializer; + private final ItemStackHandler itemHandler; + private final LazyOptional optionalItemHandler; + ItemStackInventory(int slots, int maxSlotSize, ItemStack inventoryHost, InventorySerializer serializer) { this.serializer = serializer; itemHandler = new ItemStackHandler(slots) { @@ -23,66 +26,53 @@ public int getSlotLimit(int slot) { @Override protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - setChanged(); + serializeToHost(); } }; optionalItemHandler = LazyOptional.of(() -> itemHandler); cachedInventoryHost = inventoryHost; } - public static ItemStackInventory createServerContents(int slots, int maxSlotSize, ItemStack inventoryHost, InventorySerializer inventorySerializer) { + public static ItemStackInventory create(int slots, int maxSlotSize, ItemStack inventoryHost, InventorySerializer inventorySerializer) { ItemStackInventory inventory = new ItemStackInventory(slots, maxSlotSize, inventoryHost, inventorySerializer); inventory.deserializeFromHost(); return inventory; } - public static ItemStackInventory createServerContents(int slots, int maxSlotSize, ItemStack inventoryHost) { + public static ItemStackInventory create(int slots, int maxSlotSize, ItemStack inventoryHost) { ItemStackInventory inventory = new ItemStackInventory(slots, maxSlotSize, inventoryHost, InventorySerializer.DEFAULT); inventory.deserializeFromHost(); return inventory; } - public static ItemStackInventory createClientContents(int slots, int maxSlotSize, ItemStack inventoryHost) { - return new ItemStackInventory(slots, maxSlotSize, inventoryHost, InventorySerializer.DEFAULT); - } - private void serializeToHost() { - serializer.serialize(cachedInventoryHost.getOrCreateTag(), this); + serializer.serialize(cachedInventoryHost.getOrCreateTag(), itemHandler); } private void deserializeFromHost() { - serializer.deserialize(cachedInventoryHost.getOrCreateTag(), this); + serializer.deserialize(cachedInventoryHost.getOrCreateTag(), itemHandler); } - @Override - public void setChanged() { - serializeToHost(); - super.setChanged(); - } - - @Override public boolean stillValid(Player player) { - if (cachedInventoryHost.isEmpty()) return false; - return super.stillValid(player); + return !cachedInventoryHost.isEmpty(); } - @Override - public ItemStackHandler getItemHandler() { + public IItemHandler getItemHandler() { deserializeFromHost(); //prime cheese - return super.getItemHandler(); + return itemHandler; } - @Override - public LazyOptional getOptionalItemHandler() { + public LazyOptional getLazyOptional() { deserializeFromHost(); //prime cheese //we now get the inventory from the ItemStack NBT, this makes it available on the client as well if someone gets the cap - return super.getOptionalItemHandler(); + return optionalItemHandler; } public interface InventorySerializer { String NBT_KEY = "Inventory"; + InventorySerializer DEFAULT = new InventorySerializer() {}; + InventorySerializer BLOCK_ENTITY_TAG = new InventorySerializer() { public static final String BLOCK_ENTITY_KEY = "BlockEntityTag"; diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/LargeSingleItemStackHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/LargeSingleItemStackHandler.java similarity index 97% rename from src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/LargeSingleItemStackHandler.java rename to src/main/java/com/github/elenterius/biomancy/inventory/LargeSingleItemStackHandler.java index 215f3e855..f31e8ed93 100644 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/LargeSingleItemStackHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/inventory/LargeSingleItemStackHandler.java @@ -1,4 +1,4 @@ -package com.github.elenterius.biomancy.inventory.itemhandler; +package com.github.elenterius.biomancy.inventory; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/SerializableItemHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/SerializableItemHandler.java new file mode 100644 index 000000000..cb124e65c --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/inventory/SerializableItemHandler.java @@ -0,0 +1,9 @@ +package com.github.elenterius.biomancy.inventory; + +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.items.IItemHandlerModifiable; + +public interface SerializableItemHandler extends IItemHandlerModifiable, INBTSerializable { + +} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/SimpleInventory.java b/src/main/java/com/github/elenterius/biomancy/inventory/SimpleInventory.java deleted file mode 100644 index 4f4f66cb5..000000000 --- a/src/main/java/com/github/elenterius/biomancy/inventory/SimpleInventory.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.github.elenterius.biomancy.inventory; - -import com.github.elenterius.biomancy.inventory.itemhandler.FixedSizeItemStackHandler; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.ItemStackHandler; - -import java.util.function.Predicate; - -public class SimpleInventory extends BaseInventory { - - SimpleInventory(int slotAmount) { - itemHandler = new FixedSizeItemStackHandler(slotAmount) { - @Override - protected void onContentsChanged(int slot) { - super.onContentsChanged(slot); - setChanged(); - } - }; - optionalItemHandler = LazyOptional.of(() -> itemHandler); - } - - SimpleInventory(int slotAmount, Notify markDirtyNotifier) { - this(slotAmount); - this.markDirtyNotifier = markDirtyNotifier; - } - - SimpleInventory(int slotAmount, Predicate canPlayerAccessInventory, Notify markDirtyNotifier) { - this(slotAmount); - this.canPlayerAccessInventory = canPlayerAccessInventory; - this.markDirtyNotifier = markDirtyNotifier; - } - - public static SimpleInventory createServerContents(int slotAmount, Notify markDirtyNotifier) { - return new SimpleInventory(slotAmount, markDirtyNotifier); - } - - public static SimpleInventory createServerContents(int slotAmount, Predicate canPlayerAccessInventory, Notify markDirtyNotifier) { - return new SimpleInventory(slotAmount, canPlayerAccessInventory, markDirtyNotifier); - } - - public static SimpleInventory createClientContents(int slotAmount) { - return new SimpleInventory(slotAmount); - } - -} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/SingleItemStackHandler.java b/src/main/java/com/github/elenterius/biomancy/inventory/SingleItemStackHandler.java similarity index 95% rename from src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/SingleItemStackHandler.java rename to src/main/java/com/github/elenterius/biomancy/inventory/SingleItemStackHandler.java index 2c46f3062..ce1119fd4 100644 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/SingleItemStackHandler.java +++ b/src/main/java/com/github/elenterius/biomancy/inventory/SingleItemStackHandler.java @@ -1,15 +1,14 @@ -package com.github.elenterius.biomancy.inventory.itemhandler; +package com.github.elenterius.biomancy.inventory; import net.minecraft.nbt.CompoundTag; import net.minecraft.util.Mth; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemHandlerHelper; -public class SingleItemStackHandler implements IItemHandler, IItemHandlerModifiable, INBTSerializable { +public class SingleItemStackHandler implements SerializableItemHandler, IItemHandlerModifiable, INBTSerializable { public static final String ITEM_TAG = "Item"; diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/HandlerBehaviors.java b/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/HandlerBehaviors.java deleted file mode 100644 index 8a9f22c6b..000000000 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/HandlerBehaviors.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.github.elenterius.biomancy.inventory.itemhandler; - -import com.github.elenterius.biomancy.api.nutrients.Nutrients; -import com.github.elenterius.biomancy.init.ModCapabilities; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.BundleItem; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; - -import java.util.function.Predicate; - -/** - * allows us to add specific behavior to any IItemHandler or IFluidHandler without the need of subclassing - */ -@Deprecated(forRemoval = true) -public final class HandlerBehaviors { - - private HandlerBehaviors() {} - - /** - * default item handler behavior - */ - public static > T standard(T itemStackHandler) { - return itemStackHandler; - } - - /** - * prevents item insertion, only item extraction is possible (e.g. output inventories) - */ - public static > T denyInput(T itemStackHandler) { - //noinspection unchecked - return (T) new ItemHandlerDelegator.DenyInput<>(itemStackHandler); - } - - /** - * only allows item insertion of valid items - */ - public static > T filterInput(T itemStackHandler, Predicate validItems) { - //noinspection unchecked - return (T) new ItemHandlerDelegator.FilterInput<>(itemStackHandler, validItems); - } - - public static final Predicate EMPTY_ITEM_INVENTORY_PREDICATE = stack -> { - // if (stack.getItem() instanceof BlockItem blockItem) { - // Block block = blockItem.getBlock(); - // if (block instanceof ShulkerBoxBlock) { - // return stack.getTagElement("BlockEntityTag") == null; - // } - // } - - if (stack.getItem() instanceof BundleItem) return false; - if (!stack.getItem().canFitInsideContainerItems()) return false; - - LazyOptional capability = stack.getCapability(ModCapabilities.ITEM_HANDLER); - final boolean[] isEmpty = {true}; - capability.ifPresent(itemHandler -> { - int slots = itemHandler.getSlots(); - if (slots > 200) { //if we have more than 200 slots we don't bother checking them and just return false - isEmpty[0] = false; - return; - } - //ItemHandler cap doesn't have a isEmpty() method which forces us to sequentially check every slot if it is empty - for (int i = 0; i < slots; i++) { - if (!itemHandler.getStackInSlot(i).isEmpty()) { - isEmpty[0] = false; - break; - } - } - }); - return isEmpty[0]; - }; - - /** - * prevents nesting of items with inventories,
- * i.e. insertion of filled shulker boxes and items with filled inventories (item handler capability) - */ - public static > T denyItemWithFilledInventory(T itemStackHandler) { - //noinspection unchecked - return (T) new ItemHandlerDelegator.FilterInput<>(itemStackHandler, EMPTY_ITEM_INVENTORY_PREDICATE); - } - - /** - * only allows the insertion of items that are biofuel (solid & fluid container) - */ - public static > T filterFuel(T itemStackHandler) { - //noinspection unchecked - return (T) new ItemHandlerDelegator.FilterInput<>(itemStackHandler, Nutrients::isValidFuel); - } - -} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/ItemHandlerDelegator.java b/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/ItemHandlerDelegator.java deleted file mode 100644 index d800bcf50..000000000 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/ItemHandlerDelegator.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.github.elenterius.biomancy.inventory.itemhandler; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; - -import javax.annotation.Nonnull; -import java.util.function.Predicate; - -/** - * ItemHandler delegator that is used to expose inventory capabilities with additional behavior - * - * @param the ItemStackHandler to delegate - */ -public abstract class ItemHandlerDelegator> implements IItemHandler, IItemHandlerModifiable, INBTSerializable { - - protected final T itemStackHandler; - - protected ItemHandlerDelegator(T itemStackHandlerIn) { - itemStackHandler = itemStackHandlerIn; - } - - @Override - public void setStackInSlot(int slot, @Nonnull ItemStack stack) { - itemStackHandler.setStackInSlot(slot, stack); - } - - @Override - public int getSlots() { - return itemStackHandler.getSlots(); - } - - @Nonnull - @Override - public ItemStack getStackInSlot(int slot) { - return itemStackHandler.getStackInSlot(slot); - } - - @Nonnull - @Override - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - return itemStackHandler.insertItem(slot, stack, simulate); - } - - @Nonnull - @Override - public ItemStack extractItem(int slot, int amount, boolean simulate) { - return itemStackHandler.extractItem(slot, amount, simulate); - } - - @Override - public int getSlotLimit(int slot) { - return itemStackHandler.getSlotLimit(slot); - } - - @Override - public boolean isItemValid(int slot, @Nonnull ItemStack stack) { - return itemStackHandler.isItemValid(slot, stack); - } - - @Override - public CompoundTag serializeNBT() { - return itemStackHandler.serializeNBT(); - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - itemStackHandler.deserializeNBT(nbt); - } - - /** - * prevents item insertion, therefore only allowing item extraction (e.g. output slots). - */ - public static class DenyInput> extends ItemHandlerDelegator { - - public DenyInput(T itemStackHandlerIn) { - super(itemStackHandlerIn); - } - - @Override - public boolean isItemValid(int slot, @Nonnull ItemStack stack) { - return false; - } - - @Override - @Nonnull - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - return stack; - } - - } - - /** - * only allows item insertion of matching items - */ - public static class FilterInput> extends ItemHandlerDelegator { - - private final Predicate validItems; - - public FilterInput(T itemStackHandlerIn, Predicate validItems) { - super(itemStackHandlerIn); - this.validItems = validItems; - } - - @Override - public boolean isItemValid(int slot, @Nonnull ItemStack stack) { - return validItems.test(stack) && itemStackHandler.isItemValid(slot, stack); - } - - @Override - @Nonnull - public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - if (!validItems.test(stack)) return stack; - return itemStackHandler.insertItem(slot, stack, simulate); - } - - } -} diff --git a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/package-info.java b/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/package-info.java deleted file mode 100644 index bb41ff6f7..000000000 --- a/src/main/java/com/github/elenterius/biomancy/inventory/itemhandler/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -package com.github.elenterius.biomancy.inventory.itemhandler; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/com/github/elenterius/biomancy/item/StorageSacBlockItem.java b/src/main/java/com/github/elenterius/biomancy/item/StorageSacBlockItem.java index 0e2fb2a01..00b13b894 100644 --- a/src/main/java/com/github/elenterius/biomancy/item/StorageSacBlockItem.java +++ b/src/main/java/com/github/elenterius/biomancy/item/StorageSacBlockItem.java @@ -3,8 +3,8 @@ import com.github.elenterius.biomancy.block.storagesac.StorageSacBlockEntity; import com.github.elenterius.biomancy.client.util.ClientTextUtil; import com.github.elenterius.biomancy.init.ModCapabilities; +import com.github.elenterius.biomancy.inventory.ItemHandlerWrapper; import com.github.elenterius.biomancy.inventory.ItemStackInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.EnhancedItemHandler; import com.github.elenterius.biomancy.tooltip.StorageSacTooltipComponent; import com.github.elenterius.biomancy.util.ComponentUtil; import net.minecraft.core.Direction; @@ -38,8 +38,8 @@ public StorageSacBlockItem(Block block, Properties properties) { super(block, properties); } - public static Optional getItemHandler(ItemStack stack) { - return stack.getCapability(ModCapabilities.ITEM_HANDLER).map(EnhancedItemHandler::new); + public static Optional getItemHandler(ItemStack stack) { + return stack.getCapability(ModCapabilities.ITEM_HANDLER).map(ItemHandlerWrapper::new); } @Nullable @@ -60,7 +60,7 @@ public boolean overrideStackedOnOther(ItemStack stack, Slot slot, ClickAction ac final ItemStack otherStack = slot.getItem(); if (otherStack.isEmpty()) { - Optional itemHandler = getItemHandler(stack); + Optional itemHandler = getItemHandler(stack); ItemStack stackFromInv = itemHandler.map(h -> h.extractItemFirstFound(slot.getMaxStackSize(), false)).orElse(ItemStack.EMPTY); int insertAmount = stackFromInv.getCount(); ItemStack remainder = slot.safeInsert(stackFromInv); @@ -85,7 +85,7 @@ public boolean overrideOtherStackedOnMe(ItemStack stack, ItemStack otherStack, S if (action != ClickAction.SECONDARY || !slot.allowModification(player)) return false; if (otherStack.isEmpty()) { - ItemStack stackFromInv = getItemHandler(stack).map(EnhancedItemHandler::extractItemFirstFound).orElse(ItemStack.EMPTY); + ItemStack stackFromInv = getItemHandler(stack).map(ItemHandlerWrapper::extractItemFirstFound).orElse(ItemStack.EMPTY); if (!stackFromInv.isEmpty()) { playRemoveFromSacSound(player); access.set(stackFromInv); @@ -129,16 +129,16 @@ private void playSound(Player player, SoundEvent soundEvent) { private static class InventoryCapability implements ICapabilityProvider { public static final ItemStackInventory.InventorySerializer SERIALIZER = ItemStackInventory.InventorySerializer.BLOCK_ENTITY_TAG; - private final ItemStackInventory itemHandler; + private final ItemStackInventory inventory; public InventoryCapability(ItemStack stack) { - itemHandler = ItemStackInventory.createServerContents(StorageSacBlockEntity.SLOTS, 64, stack, SERIALIZER); + inventory = ItemStackInventory.create(StorageSacBlockEntity.SLOTS, 64, stack, SERIALIZER); } @Nonnull @Override public LazyOptional getCapability(@Nonnull Capability capability, @Nullable Direction facing) { - return ModCapabilities.ITEM_HANDLER.orEmpty(capability, itemHandler.getOptionalItemHandler()); + return ModCapabilities.ITEM_HANDLER.orEmpty(capability, inventory.getLazyOptional()); } } diff --git a/src/main/java/com/github/elenterius/biomancy/item/injector/InjectorItem.java b/src/main/java/com/github/elenterius/biomancy/item/injector/InjectorItem.java index 31ce1ade5..d1a3c1447 100644 --- a/src/main/java/com/github/elenterius/biomancy/item/injector/InjectorItem.java +++ b/src/main/java/com/github/elenterius/biomancy/item/injector/InjectorItem.java @@ -10,7 +10,7 @@ import com.github.elenterius.biomancy.init.ModEnchantments; import com.github.elenterius.biomancy.init.ModSoundEvents; import com.github.elenterius.biomancy.inventory.InjectorItemInventory; -import com.github.elenterius.biomancy.inventory.itemhandler.LargeSingleItemStackHandler; +import com.github.elenterius.biomancy.inventory.LargeSingleItemStackHandler; import com.github.elenterius.biomancy.item.ItemTooltipStyleProvider; import com.github.elenterius.biomancy.item.KeyPressListener; import com.github.elenterius.biomancy.item.armor.AcolyteArmorItem; @@ -139,7 +139,7 @@ private static boolean dispenserAffectEntity(ServerLevel level, BlockPos pos, Se } public static Optional getItemHandler(ItemStack stack) { - return stack.getCapability(ModCapabilities.ITEM_HANDLER).filter(LargeSingleItemStackHandler.class::isInstance).map(LargeSingleItemStackHandler.class::cast); + return stack.getCapability(ModCapabilities.ITEM_HANDLER).map(LargeSingleItemStackHandler.class::cast); } @OnlyIn(Dist.CLIENT) @@ -503,13 +503,13 @@ private static class InventoryCapability implements ICapabilityProvider { private final InjectorItemInventory itemHandler; public InventoryCapability(ItemStack stack) { - itemHandler = InjectorItemInventory.createServerContents(MAX_SLOT_SIZE, stack); + itemHandler = InjectorItemInventory.create(MAX_SLOT_SIZE, stack); } @NotNull @Override public LazyOptional getCapability(@NotNull Capability capability, @Nullable Direction facing) { - return ModCapabilities.ITEM_HANDLER.orEmpty(capability, itemHandler.getOptionalItemHandler()); + return ModCapabilities.ITEM_HANDLER.orEmpty(capability, itemHandler.getLazyOptional()); } } diff --git a/src/main/java/com/github/elenterius/biomancy/menu/BioForgeMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/BioForgeMenu.java index d8682517f..d56d9fa15 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/BioForgeMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/BioForgeMenu.java @@ -8,77 +8,56 @@ import com.github.elenterius.biomancy.crafting.recipe.IngredientStack; import com.github.elenterius.biomancy.init.ModMenuTypes; import com.github.elenterius.biomancy.init.ModSoundEvents; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.menu.slot.FuelSlot; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; -import com.github.elenterius.biomancy.menu.slot.OutputSlot; import com.github.elenterius.biomancy.util.ItemStackCounter; import com.github.elenterius.biomancy.util.SoundUtil; -import com.github.elenterius.biomancy.util.fuel.FuelHandler; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.inventory.ContainerLevelAccess; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.SlotItemHandler; import org.apache.logging.log4j.MarkerManager; +import org.jetbrains.annotations.Nullable; -import javax.annotation.Nullable; import java.util.List; public class BioForgeMenu extends PlayerContainerMenu { final ResultContainer resultContainer = new ResultContainer(); - final int resultSlotIndex; - private final BehavioralInventory fuelInventory; - private final BioForgeStateData stateData; + private final BioForgeBlockEntity bioforge; private int playerInvChanges; private final ItemStackCounter itemCounter = new ItemStackCounter(); @Nullable private BioForgeRecipe selectedRecipe; - protected BioForgeMenu(int id, Inventory playerInventory, BehavioralInventory fuelInventory, BioForgeStateData stateData) { + protected BioForgeMenu(int id, Inventory playerInventory, @Nullable BioForgeBlockEntity bioforge) { super(ModMenuTypes.BIO_FORGE.get(), id, playerInventory, 124, 137, 195); - this.fuelInventory = fuelInventory; - this.fuelInventory.startOpen(playerInventory.player); - this.stateData = stateData; + this.bioforge = bioforge; - addSlot(new FuelSlot(fuelInventory, 0, 139, 53)); - resultSlotIndex = addSlot(new CustomResultSlot(playerInventory.player, resultContainer, 0, 194 + 2, 33 + 2)).index; + if (bioforge != null) { + bioforge.startOpen(playerInventory.player); - addDataSlots(stateData); + addSlot(new SlotItemHandler(bioforge.getFuelInventory(), 0, 139, 53)); + addSlot(new CustomResultSlot(playerInventory.player, resultContainer, 0, 194 + 2, 33 + 2)); + + addDataSlots(bioforge.getStateData()); + } } - private ContainerLevelAccess containerLevelAccess = ContainerLevelAccess.NULL; //only exists on the logical server side private long prevSoundTime; public BioForgeStateData getStateData() { - return stateData; + return bioforge.getStateData(); } - public BioForgeMenu(int id, Inventory playerInventory, BehavioralInventory fuelInventory, BioForgeStateData stateData, ContainerLevelAccess containerLevelAccess) { - this(id, playerInventory, fuelInventory, stateData); - this.containerLevelAccess = containerLevelAccess; - } - - public static BioForgeMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf buffer) { - BehavioralInventory fuelInventory = BehavioralInventory.createClientContents(BioForgeBlockEntity.FUEL_SLOTS); - - BioForgeStateData stateData; - if (playerInventory.player.level().getBlockEntity(buffer.readBlockPos()) instanceof BioForgeBlockEntity bioForge) { - stateData = bioForge.getStateData(); - } - else { - FuelHandler fuelHandler = FuelHandler.createNutrientFuelHandler(BioForgeBlockEntity.MAX_FUEL, () -> {}); - stateData = new BioForgeStateData(fuelHandler); - } - - return new BioForgeMenu(screenId, playerInventory, fuelInventory, stateData); + public static BioForgeMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf extraData) { + BioForgeBlockEntity bioforge = playerInventory.player.level().getBlockEntity(extraData.readBlockPos()) instanceof BioForgeBlockEntity be ? be : null; + return new BioForgeMenu(screenId, playerInventory, bioforge); } @Override @@ -129,7 +108,7 @@ public void setSelectedRecipe(@Nullable BioForgeRecipe recipe, ServerPlayer serv public void removed(Player player) { super.removed(player); resultContainer.clearContent(); - fuelInventory.stopOpen(player); + if (bioforge != null) bioforge.stopOpen(player); } @Override @@ -139,14 +118,15 @@ public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { @Override public boolean stillValid(Player player) { - return fuelInventory.stillValid(player); + return bioforge != null && bioforge.canPlayerInteract(player); } + public float getFuelAmountNormalized() { return Mth.clamp((float) getFuelAmount() / BioForgeBlockEntity.MAX_FUEL, 0f, 1f); } public int getFuelAmount() { - return stateData.fuelHandler.getFuelAmount(); + return bioforge.getStateData().fuelHandler.getFuelAmount(); } public int getMaxFuelAmount() { @@ -247,11 +227,11 @@ public int getSlotCount() { } - public static BioForgeMenu createServerMenu(int screenId, Inventory playerInventory, BehavioralInventory fuelInventory, BioForgeStateData stateData, ContainerLevelAccess containerLevelAccess) { - return new BioForgeMenu(screenId, playerInventory, fuelInventory, stateData, containerLevelAccess); + public static BioForgeMenu createServerMenu(int screenId, Inventory playerInventory, BioForgeBlockEntity bioforge) { + return new BioForgeMenu(screenId, playerInventory, bioforge); } - private class CustomResultSlot extends OutputSlot { + private class CustomResultSlot extends Slot { private final Player player; private int removeCount; @@ -261,6 +241,11 @@ public CustomResultSlot(Player player, ResultContainer container, int index, int this.player = player; } + @Override + public boolean mayPlace(ItemStack stack) { + return false; + } + @Override public ItemStack remove(int amount) { if (hasItem()) { @@ -299,13 +284,13 @@ public void onTake(Player player, ItemStack stack) { checkTakeAchievements(stack); onPlayerMainInventoryChanged(player.getInventory()); //ensures the recipe output slot is filled again if possible, integral for quick crafting to work - containerLevelAccess.execute((level, pos) -> { - long time = level.getGameTime(); + if (bioforge != null && bioforge.getLevel() instanceof ServerLevel serverLevel) { + long time = serverLevel.getGameTime(); if (prevSoundTime != time) { - SoundUtil.broadcastBlockSound((ServerLevel) level, pos, ModSoundEvents.UI_BIO_FORGE_TAKE_RESULT); + SoundUtil.broadcastBlockSound(serverLevel, bioforge.getBlockPos(), ModSoundEvents.UI_BIO_FORGE_TAKE_RESULT); prevSoundTime = time; } - }); + } setChanged(); } @@ -345,7 +330,7 @@ private void consumeCraftingIngredients(Player player, BioForgeRecipe recipe) { inventory.setChanged(); //consume nutrients - stateData.fuelHandler.addFuelAmount(-recipe.getCraftingCostNutrients()); + bioforge.getStateData().fuelHandler.addFuelAmount(-recipe.getCraftingCostNutrients()); } } diff --git a/src/main/java/com/github/elenterius/biomancy/menu/BioLabMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/BioLabMenu.java index e2eb90888..0543d3e82 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/BioLabMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/BioLabMenu.java @@ -3,14 +3,8 @@ import com.github.elenterius.biomancy.BiomancyMod; import com.github.elenterius.biomancy.api.nutrients.Nutrients; import com.github.elenterius.biomancy.block.biolab.BioLabBlockEntity; -import com.github.elenterius.biomancy.block.biolab.BioLabStateData; import com.github.elenterius.biomancy.init.ModMenuTypes; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.inventory.SimpleInventory; -import com.github.elenterius.biomancy.menu.slot.FuelSlot; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; -import com.github.elenterius.biomancy.menu.slot.OutputSlot; -import com.github.elenterius.biomancy.util.fuel.FuelHandler; +import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; @@ -18,76 +12,75 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; import org.apache.logging.log4j.MarkerManager; - -import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; public class BioLabMenu extends PlayerContainerMenu { protected final Level level; - private final Predicate isMenuValidPredicate; - private final BioLabStateData stateData; - protected BioLabMenu(int id, Inventory playerInventory, BehavioralInventory fuelInventory, SimpleInventory inputInventory, BehavioralInventory outputInventory, BioLabStateData stateData) { + private final BioLabBlockEntity bioLab; + + protected BioLabMenu(int id, Inventory playerInventory, @Nullable BioLabBlockEntity bioLab) { super(ModMenuTypes.BIO_LAB.get(), id, playerInventory, 137, 195); level = playerInventory.player.level(); - //we don't check all three inventories because they all call the same method in the decomposer tile entity - isMenuValidPredicate = inputInventory::stillValid; + this.bioLab = bioLab; - this.stateData = stateData; + if (bioLab != null) { + addSlot(new SlotItemHandler(bioLab.getFuelInventory(), 0, 31, 88)); - addSlot(new FuelSlot(fuelInventory, 0, 31, 88)); + IItemHandler itemHandler = bioLab.getInputInventory(); + addSlot(new SlotItemHandler(itemHandler, 0, 50, 28)); + addSlot(new SlotItemHandler(itemHandler, 1, 70, 28)); + addSlot(new SlotItemHandler(itemHandler, 2, 90, 28)); + addSlot(new SlotItemHandler(itemHandler, 3, 110, 28)); - addSlot(new Slot(inputInventory, 0, 50, 28)); - addSlot(new Slot(inputInventory, 1, 70, 28)); - addSlot(new Slot(inputInventory, 2, 90, 28)); - addSlot(new Slot(inputInventory, 3, 110, 28)); + addSlot(new SlotItemHandler(itemHandler, 4, 80, 62)); // reactant/vial slot - addSlot(new Slot(inputInventory, 4, 80, 62)); // reactant/vial slot + addSlot(new SlotItemHandler(bioLab.getOutputInventory(), 0, 80, 88)); - addSlot(new OutputSlot(outputInventory, 0, 80, 88)); - - addDataSlots(stateData); + addDataSlots(bioLab.getStateData()); + } } - public static BioLabMenu createServerMenu(int screenId, Inventory playerInventory, BehavioralInventory fuelInventory, SimpleInventory inputInventory, BehavioralInventory outputInventory, BioLabStateData stateData) { - return new BioLabMenu(screenId, playerInventory, fuelInventory, inputInventory, outputInventory, stateData); + public static BioLabMenu createServerMenu(int containerId, Inventory playerInventory, BioLabBlockEntity biolab) { + return new BioLabMenu(containerId, playerInventory, biolab); } - public static BioLabMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf extraData) { - BehavioralInventory fuelInventory = BehavioralInventory.createClientContents(BioLabBlockEntity.FUEL_SLOTS); - SimpleInventory inputInventory = SimpleInventory.createClientContents(BioLabBlockEntity.INPUT_SLOTS); - BehavioralInventory outputInventory = BehavioralInventory.createClientContents(BioLabBlockEntity.OUTPUT_SLOTS); - FuelHandler fuelHandler = FuelHandler.createNutrientFuelHandler(BioLabBlockEntity.MAX_FUEL, () -> {}); - BioLabStateData state = new BioLabStateData(fuelHandler); - return new BioLabMenu(screenId, playerInventory, fuelInventory, inputInventory, outputInventory, state); + public static BioLabMenu createClientMenu(int containerId, Inventory playerInventory, FriendlyByteBuf extraData) { + BlockPos blockPos = extraData.readBlockPos(); + BlockEntity blockEntity = playerInventory.player.level().getBlockEntity(blockPos); + return new BioLabMenu(containerId, playerInventory, blockEntity instanceof BioLabBlockEntity bioLab ? bioLab : null); } @Override public boolean stillValid(Player player) { - return isMenuValidPredicate.test(player); + return bioLab != null && bioLab.canPlayerInteract(player); } public float getCraftingProgressNormalized() { - if (stateData.timeForCompletion == 0) return 0f; - return Mth.clamp(stateData.timeElapsed / (float) stateData.timeForCompletion, 0f, 1f); + if (bioLab.getStateData().timeForCompletion == 0) return 0f; + return Mth.clamp(bioLab.getStateData().timeElapsed / (float) bioLab.getStateData().timeForCompletion, 0f, 1f); } public int getFuelCost() { - return stateData.getFuelCost(); + return bioLab.getStateData().getFuelCost(); } public float getFuelAmountNormalized() { - return Mth.clamp((float) stateData.fuelHandler.getFuelAmount() / stateData.fuelHandler.getMaxFuelAmount(), 0f, 1f); + return Mth.clamp((float) bioLab.getStateData().fuelHandler.getFuelAmount() / bioLab.getStateData().fuelHandler.getMaxFuelAmount(), 0f, 1f); } public int getFuelAmount() { - return stateData.fuelHandler.getFuelAmount(); + return bioLab.getStateData().fuelHandler.getFuelAmount(); } public int getMaxFuelAmount() { - return stateData.fuelHandler.getMaxFuelAmount(); + return bioLab.getStateData().fuelHandler.getMaxFuelAmount(); } @Override diff --git a/src/main/java/com/github/elenterius/biomancy/menu/DecomposerMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/DecomposerMenu.java index 1633544fc..2687b92e2 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/DecomposerMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/DecomposerMenu.java @@ -3,13 +3,7 @@ import com.github.elenterius.biomancy.BiomancyMod; import com.github.elenterius.biomancy.api.nutrients.Nutrients; import com.github.elenterius.biomancy.block.decomposer.DecomposerBlockEntity; -import com.github.elenterius.biomancy.block.decomposer.DecomposerStateData; import com.github.elenterius.biomancy.init.ModMenuTypes; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.menu.slot.FuelSlot; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; -import com.github.elenterius.biomancy.menu.slot.OutputSlot; -import com.github.elenterius.biomancy.util.fuel.FuelHandler; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; @@ -17,74 +11,73 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; import org.apache.logging.log4j.MarkerManager; - -import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; public class DecomposerMenu extends PlayerContainerMenu { protected final Level level; - private final Predicate isMenuValidPredicate; - private final DecomposerStateData stateData; + private final DecomposerBlockEntity decomposer; - protected DecomposerMenu(int id, Inventory playerInventory, BehavioralInventory fuelInventory, BehavioralInventory inputInventory, BehavioralInventory outputInventory, DecomposerStateData stateData) { + protected DecomposerMenu(int id, Inventory playerInventory, @Nullable DecomposerBlockEntity decomposer) { super(ModMenuTypes.DECOMPOSER.get(), id, playerInventory, 111, 169); level = playerInventory.player.level(); - isMenuValidPredicate = inputInventory::stillValid; - this.stateData = stateData; - - addSlot(new FuelSlot(fuelInventory, 0, 39, 66)); - addSlot(new Slot(inputInventory, 0, 66, 26)); - - int posY = 48; - int posX = 88; - addSlot(new OutputSlot(outputInventory, 0, posX, posY)); - addSlot(new OutputSlot(outputInventory, 1, posX, posY + 18)); - addSlot(new OutputSlot(outputInventory, 2, posX + 18, posY)); - addSlot(new OutputSlot(outputInventory, 3, posX + 18, posY + 18)); - addSlot(new OutputSlot(outputInventory, 4, posX + 18 * 2, posY)); - addSlot(new OutputSlot(outputInventory, 5, posX + 18 * 2, posY + 18)); - - addDataSlots(stateData); + + this.decomposer = decomposer; + + if (decomposer != null) { + addSlot(new SlotItemHandler(decomposer.getFuelInventory(), 0, 39, 66)); + addSlot(new SlotItemHandler(decomposer.getInputInventory(), 0, 66, 26)); + + int posY = 48; + int posX = 88; + IItemHandler itemHandler = decomposer.getOutputInventory(); + addSlot(new SlotItemHandler(itemHandler, 0, posX, posY)); + addSlot(new SlotItemHandler(itemHandler, 1, posX, posY + 18)); + addSlot(new SlotItemHandler(itemHandler, 2, posX + 18, posY)); + addSlot(new SlotItemHandler(itemHandler, 3, posX + 18, posY + 18)); + addSlot(new SlotItemHandler(itemHandler, 4, posX + 18 * 2, posY)); + addSlot(new SlotItemHandler(itemHandler, 5, posX + 18 * 2, posY + 18)); + + addDataSlots(decomposer.getStateData()); + } } - public static DecomposerMenu createServerMenu(int screenId, Inventory playerInventory, BehavioralInventory fuelInventory, BehavioralInventory inputInventory, BehavioralInventory outputInventory, DecomposerStateData stateData) { - return new DecomposerMenu(screenId, playerInventory, fuelInventory, inputInventory, outputInventory, stateData); + public static DecomposerMenu createServerMenu(int screenId, Inventory playerInventory, DecomposerBlockEntity decomposer) { + return new DecomposerMenu(screenId, playerInventory, decomposer); } public static DecomposerMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf extraData) { - BehavioralInventory fuelInventory = BehavioralInventory.createClientContents(DecomposerBlockEntity.FUEL_SLOTS); - BehavioralInventory inputInventory = BehavioralInventory.createClientContents(DecomposerBlockEntity.INPUT_SLOTS); - BehavioralInventory outputInventory = BehavioralInventory.createClientContents(DecomposerBlockEntity.OUTPUT_SLOTS); - FuelHandler fuelHandler = FuelHandler.createNutrientFuelHandler(DecomposerBlockEntity.MAX_FUEL, () -> {}); - DecomposerStateData state = new DecomposerStateData(fuelHandler); - return new DecomposerMenu(screenId, playerInventory, fuelInventory, inputInventory, outputInventory, state); + DecomposerBlockEntity decomposer = playerInventory.player.level().getBlockEntity(extraData.readBlockPos()) instanceof DecomposerBlockEntity be ? be : null; + return new DecomposerMenu(screenId, playerInventory, decomposer); } @Override public boolean stillValid(Player player) { - return isMenuValidPredicate.test(player); + return decomposer != null && decomposer.canPlayerInteract(player); } public float getCraftingProgressNormalized() { - if (stateData.timeForCompletion == 0) return 0f; - return Mth.clamp(stateData.timeElapsed / (float) stateData.timeForCompletion, 0f, 1f); + if (decomposer.getStateData().timeForCompletion == 0) return 0f; + return Mth.clamp(decomposer.getStateData().timeElapsed / (float) decomposer.getStateData().timeForCompletion, 0f, 1f); } public float getFuelAmountNormalized() { - return Mth.clamp((float) stateData.fuelHandler.getFuelAmount() / stateData.fuelHandler.getMaxFuelAmount(), 0f, 1f); + return Mth.clamp((float) decomposer.getStateData().fuelHandler.getFuelAmount() / decomposer.getStateData().fuelHandler.getMaxFuelAmount(), 0f, 1f); } public int getFuelAmount() { - return stateData.fuelHandler.getFuelAmount(); + return decomposer.getStateData().fuelHandler.getFuelAmount(); } - public int getMAxFuelAmount() { - return stateData.fuelHandler.getMaxFuelAmount(); + public int getMaxFuelAmount() { + return decomposer.getStateData().fuelHandler.getMaxFuelAmount(); } public int getFuelCost() { - return stateData.getFuelCost(); + return decomposer.getStateData().getFuelCost(); } @Override diff --git a/src/main/java/com/github/elenterius/biomancy/menu/DigesterMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/DigesterMenu.java index d2da4c68b..90efb8a9f 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/DigesterMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/DigesterMenu.java @@ -3,13 +3,7 @@ import com.github.elenterius.biomancy.BiomancyMod; import com.github.elenterius.biomancy.api.nutrients.Nutrients; import com.github.elenterius.biomancy.block.digester.DigesterBlockEntity; -import com.github.elenterius.biomancy.block.digester.DigesterStateData; import com.github.elenterius.biomancy.init.ModMenuTypes; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.menu.slot.FuelSlot; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; -import com.github.elenterius.biomancy.menu.slot.OutputSlot; -import com.github.elenterius.biomancy.util.fuel.FuelHandler; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.Mth; import net.minecraft.world.entity.player.Inventory; @@ -17,69 +11,68 @@ import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; import org.apache.logging.log4j.MarkerManager; - -import java.util.function.Predicate; +import org.jetbrains.annotations.Nullable; public class DigesterMenu extends PlayerContainerMenu { protected final Level level; - private final Predicate isMenuValidPredicate; - private final DigesterStateData stateData; + private final DigesterBlockEntity digester; - protected DigesterMenu(int id, Inventory playerInventory, BehavioralInventory fuelInventory, BehavioralInventory inputInventory, BehavioralInventory outputInventory, DigesterStateData stateData) { + protected DigesterMenu(int id, Inventory playerInventory, @Nullable DigesterBlockEntity digester) { super(ModMenuTypes.DIGESTER.get(), id, playerInventory, 111, 169); level = playerInventory.player.level(); - isMenuValidPredicate = inputInventory::stillValid; - this.stateData = stateData; - addSlot(new FuelSlot(fuelInventory, 0, 39, 68)); + this.digester = digester; + + if (digester != null) { + addSlot(new SlotItemHandler(digester.getFuelInventory(), 0, 39, 68)); - addSlot(new Slot(inputInventory, 0, 80, 24)); + addSlot(new SlotItemHandler(digester.getInputInventory(), 0, 80, 24)); - addSlot(new OutputSlot(outputInventory, 0, 69, 68)); - addSlot(new OutputSlot(outputInventory, 1, 91, 68)); + IItemHandler itemHandler = digester.getOutputInventory(); + addSlot(new SlotItemHandler(itemHandler, 0, 69, 68)); + addSlot(new SlotItemHandler(itemHandler, 1, 91, 68)); - addDataSlots(stateData); + addDataSlots(digester.getStateData()); + } } - public static DigesterMenu createServerMenu(int screenId, Inventory playerInventory, BehavioralInventory fuelInventory, BehavioralInventory inputInventory, BehavioralInventory outputInventory, DigesterStateData stateData) { - return new DigesterMenu(screenId, playerInventory, fuelInventory, inputInventory, outputInventory, stateData); + public static DigesterMenu createServerMenu(int screenId, Inventory playerInventory, DigesterBlockEntity digester) { + return new DigesterMenu(screenId, playerInventory, digester); } public static DigesterMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf extraData) { - BehavioralInventory fuelInventory = BehavioralInventory.createClientContents(DigesterBlockEntity.FUEL_SLOTS); - BehavioralInventory inputInventory = BehavioralInventory.createClientContents(DigesterBlockEntity.INPUT_SLOTS); - BehavioralInventory outputInventory = BehavioralInventory.createClientContents(DigesterBlockEntity.OUTPUT_SLOTS); - FuelHandler fuelHandler = FuelHandler.createNutrientFuelHandler(DigesterBlockEntity.MAX_FUEL, () -> {}); - DigesterStateData state = new DigesterStateData(fuelHandler); - return new DigesterMenu(screenId, playerInventory, fuelInventory, inputInventory, outputInventory, state); + DigesterBlockEntity digester = playerInventory.player.level().getBlockEntity(extraData.readBlockPos()) instanceof DigesterBlockEntity be ? be : null; + return new DigesterMenu(screenId, playerInventory, digester); } @Override public boolean stillValid(Player player) { - return isMenuValidPredicate.test(player); + return digester != null && digester.canPlayerInteract(player); } public float getCraftingProgressNormalized() { - if (stateData.timeForCompletion == 0) return 0f; - return Mth.clamp(stateData.timeElapsed / (float) stateData.timeForCompletion, 0f, 1f); + if (digester.getStateData().timeForCompletion == 0) return 0f; + return Mth.clamp(digester.getStateData().timeElapsed / (float) digester.getStateData().timeForCompletion, 0f, 1f); } public float getFuelAmountNormalized() { - return Mth.clamp((float) stateData.fuelHandler.getFuelAmount() / stateData.fuelHandler.getMaxFuelAmount(), 0f, 1f); + return Mth.clamp((float) digester.getStateData().fuelHandler.getFuelAmount() / digester.getStateData().fuelHandler.getMaxFuelAmount(), 0f, 1f); } public int getFuelAmount() { - return stateData.fuelHandler.getFuelAmount(); + return digester.getStateData().fuelHandler.getFuelAmount(); } public int getMaxFuelAmount() { - return stateData.fuelHandler.getMaxFuelAmount(); + return digester.getStateData().fuelHandler.getMaxFuelAmount(); } public int getFuelCost() { - return stateData.getFuelCost(); + return digester.getStateData().getFuelCost(); } @Override diff --git a/src/main/java/com/github/elenterius/biomancy/menu/FleshkinChestMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/FleshkinChestMenu.java index 9d86424ac..9dfffc0dc 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/FleshkinChestMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/FleshkinChestMenu.java @@ -3,49 +3,54 @@ import com.github.elenterius.biomancy.BiomancyMod; import com.github.elenterius.biomancy.block.fleshkinchest.FleshkinChestBlockEntity; import com.github.elenterius.biomancy.init.ModMenuTypes; -import com.github.elenterius.biomancy.inventory.SimpleInventory; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; +import com.github.elenterius.biomancy.inventory.InventoryHandler; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.SlotItemHandler; import org.apache.logging.log4j.MarkerManager; +import org.jetbrains.annotations.Nullable; public class FleshkinChestMenu extends PlayerContainerMenu { - private final SimpleInventory inventory; + private final FleshkinChestBlockEntity chest; - protected FleshkinChestMenu(int id, Inventory playerInventory, SimpleInventory chestInventory) { + protected FleshkinChestMenu(int id, Inventory playerInventory, @Nullable FleshkinChestBlockEntity chest) { super(ModMenuTypes.FLESHKIN_CHEST.get(), id, playerInventory, 150, 208); - inventory = chestInventory; - inventory.startOpen(playerInventory.player); + this.chest = chest; - int posX = 26; - int posY = 24; - int rows = 6; - int columns = 7; - for (int y = 0; y < rows; y++) { - for (int x = 0; x < columns; x++) { - addSlot(new Slot(inventory, y * columns + x, posX + x * 18, posY + y * 18)); + if (chest != null) { + chest.startOpen(playerInventory.player); + IItemHandler itemHandler = chest.getInventory(); + + int posX = 26; + int posY = 24; + int rows = 6; + int columns = 7; + for (int y = 0; y < rows; y++) { + for (int x = 0; x < columns; x++) { + addSlot(new SlotItemHandler(itemHandler, y * columns + x, posX + x * 18, posY + y * 18)); + } } } } - public static FleshkinChestMenu createServerMenu(int screenId, Inventory playerInventory, SimpleInventory chestInventory) { - return new FleshkinChestMenu(screenId, playerInventory, chestInventory); + public static FleshkinChestMenu createServerMenu(int screenId, Inventory playerInventory, FleshkinChestBlockEntity chest) { + return new FleshkinChestMenu(screenId, playerInventory, chest); } public static FleshkinChestMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf extraData) { - SimpleInventory chestInventory = SimpleInventory.createClientContents(FleshkinChestBlockEntity.SLOTS); - return new FleshkinChestMenu(screenId, playerInventory, chestInventory); + FleshkinChestBlockEntity chest = playerInventory.player.level().getBlockEntity(extraData.readBlockPos()) instanceof FleshkinChestBlockEntity be ? be : null; + return new FleshkinChestMenu(screenId, playerInventory, chest); } @Override public boolean stillValid(Player player) { - return inventory.stillValid(player); + return chest != null && chest.canPlayerInteract(player); } @Override @@ -75,14 +80,14 @@ public ItemStack quickMoveStack(Player player, int index) { return copyOfStack; } - public Container getContainer() { - return inventory; + public InventoryHandler getInventory() { + return chest.getInventory(); } @Override public void removed(Player player) { super.removed(player); - inventory.stopOpen(player); + if (chest != null) chest.stopOpen(player); } public enum SlotZone implements ISlotZone { diff --git a/src/main/java/com/github/elenterius/biomancy/menu/slot/ISlotZone.java b/src/main/java/com/github/elenterius/biomancy/menu/ISlotZone.java similarity index 68% rename from src/main/java/com/github/elenterius/biomancy/menu/slot/ISlotZone.java rename to src/main/java/com/github/elenterius/biomancy/menu/ISlotZone.java index 33296df29..f28d41387 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/slot/ISlotZone.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/ISlotZone.java @@ -1,4 +1,4 @@ -package com.github.elenterius.biomancy.menu.slot; +package com.github.elenterius.biomancy.menu; public interface ISlotZone { diff --git a/src/main/java/com/github/elenterius/biomancy/menu/PlayerContainerMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/PlayerContainerMenu.java index 09778cd4a..ad1ac4580 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/PlayerContainerMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/PlayerContainerMenu.java @@ -1,6 +1,5 @@ package com.github.elenterius.biomancy.menu; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MenuType; diff --git a/src/main/java/com/github/elenterius/biomancy/menu/StorageSacMenu.java b/src/main/java/com/github/elenterius/biomancy/menu/StorageSacMenu.java index 1197a02d1..208fb1322 100644 --- a/src/main/java/com/github/elenterius/biomancy/menu/StorageSacMenu.java +++ b/src/main/java/com/github/elenterius/biomancy/menu/StorageSacMenu.java @@ -3,46 +3,50 @@ import com.github.elenterius.biomancy.BiomancyMod; import com.github.elenterius.biomancy.block.storagesac.StorageSacBlockEntity; import com.github.elenterius.biomancy.init.ModMenuTypes; -import com.github.elenterius.biomancy.inventory.BehavioralInventory; -import com.github.elenterius.biomancy.menu.slot.ISlotZone; -import com.github.elenterius.biomancy.menu.slot.NonNestingSlot; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.SlotItemHandler; import org.apache.logging.log4j.MarkerManager; +import org.jetbrains.annotations.Nullable; public class StorageSacMenu extends PlayerContainerMenu { - private final BehavioralInventory inventory; + private final StorageSacBlockEntity storageSac; - protected StorageSacMenu(int id, Inventory playerInventory, BehavioralInventory inventory) { + protected StorageSacMenu(int id, Inventory playerInventory, @Nullable StorageSacBlockEntity storageSac) { super(ModMenuTypes.STORAGE_SAC.get(), id, playerInventory, 88, 146); - this.inventory = inventory; + this.storageSac = storageSac; - int posX = 44; - int posY = 17; - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 5; x++) { - addSlot(new NonNestingSlot(this.inventory, x + 5 * y, posX + x * 18, posY + y * 18)); + if (storageSac != null) { + IItemHandlerModifiable itemHandler = storageSac.getInventory(); + + int posX = 44; + int posY = 17; + for (int y = 0; y < 3; y++) { + for (int x = 0; x < 5; x++) { + addSlot(new SlotItemHandler(itemHandler, x + 5 * y, posX + x * 18, posY + y * 18)); + } } } } - public static StorageSacMenu createServerMenu(int screenId, Inventory playerInventory, BehavioralInventory inventory) { - return new StorageSacMenu(screenId, playerInventory, inventory); + public static StorageSacMenu createServerMenu(int screenId, Inventory playerInventory, StorageSacBlockEntity storageSac) { + return new StorageSacMenu(screenId, playerInventory, storageSac); } public static StorageSacMenu createClientMenu(int screenId, Inventory playerInventory, FriendlyByteBuf extraData) { - BehavioralInventory inventory = BehavioralInventory.createClientContents(StorageSacBlockEntity.SLOTS); - return new StorageSacMenu(screenId, playerInventory, inventory); + StorageSacBlockEntity storageSac = playerInventory.player.level().getBlockEntity(extraData.readBlockPos()) instanceof StorageSacBlockEntity be ? be : null; + return new StorageSacMenu(screenId, playerInventory, storageSac); } @Override public boolean stillValid(Player player) { - return inventory.stillValid(player); + return storageSac != null && storageSac.canPlayerInteract(player); } @Override diff --git a/src/main/java/com/github/elenterius/biomancy/menu/slot/FuelSlot.java b/src/main/java/com/github/elenterius/biomancy/menu/slot/FuelSlot.java deleted file mode 100644 index b7edb1891..000000000 --- a/src/main/java/com/github/elenterius/biomancy/menu/slot/FuelSlot.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.github.elenterius.biomancy.menu.slot; - -import com.github.elenterius.biomancy.api.nutrients.Nutrients; -import net.minecraft.world.Container; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; - -public class FuelSlot extends Slot { - - public FuelSlot(Container pContainer, int index, int x, int y) { - super(pContainer, index, x, y); - } - - @Override - public boolean mayPlace(ItemStack stack) { - return Nutrients.isValidFuel(stack); - } - -} diff --git a/src/main/java/com/github/elenterius/biomancy/menu/slot/NonNestingSlot.java b/src/main/java/com/github/elenterius/biomancy/menu/slot/NonNestingSlot.java deleted file mode 100644 index e266fd3fa..000000000 --- a/src/main/java/com/github/elenterius/biomancy/menu/slot/NonNestingSlot.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.elenterius.biomancy.menu.slot; - -import com.github.elenterius.biomancy.inventory.itemhandler.HandlerBehaviors; -import net.minecraft.world.Container; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; - -public class NonNestingSlot extends Slot { - - public NonNestingSlot(Container container, int index, int x, int y) { - super(container, index, x, y); - } - - @Override - public boolean mayPlace(ItemStack stack) { - //only allow empty item inventories - return HandlerBehaviors.EMPTY_ITEM_INVENTORY_PREDICATE.test(stack); - } - -} \ No newline at end of file diff --git a/src/main/java/com/github/elenterius/biomancy/menu/slot/OutputSlot.java b/src/main/java/com/github/elenterius/biomancy/menu/slot/OutputSlot.java deleted file mode 100644 index 4e57c0a05..000000000 --- a/src/main/java/com/github/elenterius/biomancy/menu/slot/OutputSlot.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.github.elenterius.biomancy.menu.slot; - -import net.minecraft.world.Container; -import net.minecraft.world.inventory.Slot; -import net.minecraft.world.item.ItemStack; - -public class OutputSlot extends Slot { - - public OutputSlot(Container container, int index, int xPos, int yPos) { - super(container, index, xPos, yPos); - } - - @Override - public boolean mayPlace(ItemStack stack) { - return false; - } - -} diff --git a/src/main/java/com/github/elenterius/biomancy/menu/slot/package-info.java b/src/main/java/com/github/elenterius/biomancy/menu/slot/package-info.java deleted file mode 100644 index 64245cf77..000000000 --- a/src/main/java/com/github/elenterius/biomancy/menu/slot/package-info.java +++ /dev/null @@ -1,7 +0,0 @@ -@ParametersAreNonnullByDefault -@MethodsReturnNonnullByDefault -package com.github.elenterius.biomancy.menu.slot; - -import net.minecraft.MethodsReturnNonnullByDefault; - -import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file diff --git a/src/main/java/com/github/elenterius/biomancy/tooltip/StorageSacTooltipComponent.java b/src/main/java/com/github/elenterius/biomancy/tooltip/StorageSacTooltipComponent.java index f9bca9178..355ce8aca 100644 --- a/src/main/java/com/github/elenterius/biomancy/tooltip/StorageSacTooltipComponent.java +++ b/src/main/java/com/github/elenterius/biomancy/tooltip/StorageSacTooltipComponent.java @@ -1,20 +1,20 @@ package com.github.elenterius.biomancy.tooltip; -import com.github.elenterius.biomancy.inventory.itemhandler.EnhancedItemHandler; +import com.github.elenterius.biomancy.inventory.ItemHandlerWrapper; import net.minecraft.world.inventory.tooltip.TooltipComponent; import org.jetbrains.annotations.Nullable; public class StorageSacTooltipComponent implements TooltipComponent { @Nullable - private final EnhancedItemHandler itemHandler; + private final ItemHandlerWrapper itemHandler; - public StorageSacTooltipComponent(@Nullable EnhancedItemHandler itemHandler) { + public StorageSacTooltipComponent(@Nullable ItemHandlerWrapper itemHandler) { this.itemHandler = itemHandler; } @Nullable - public EnhancedItemHandler getItemHandler() { + public ItemHandlerWrapper getItemHandler() { return itemHandler; } diff --git a/src/main/java/com/github/elenterius/biomancy/util/ItemStackFilter.java b/src/main/java/com/github/elenterius/biomancy/util/ItemStackFilter.java new file mode 100644 index 000000000..051f9c1d1 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/util/ItemStackFilter.java @@ -0,0 +1,79 @@ +package com.github.elenterius.biomancy.util; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.items.ItemHandlerHelper; + +import java.util.function.Predicate; + +public class ItemStackFilter implements Predicate, INBTSerializable { + + public static final String FILTER_KEY = "filter"; + public static final String STRICT_KEY = "strict"; + + public static final ItemStackFilter ALLOW_ALL = of(ItemStack.EMPTY, false); + + private ItemStack filter; + private boolean isStrict; + + protected ItemStackFilter(ItemStack filter, boolean isStrict) { + this.filter = filter; + this.isStrict = isStrict; + } + + protected ItemStackFilter(CompoundTag tag) { + deserializeNBT(tag); + } + + public static ItemStackFilter of(CompoundTag tag) { + return new ItemStackFilter(tag); + } + + public static ItemStackFilter of(Item filter) { + return of(filter.getDefaultInstance(), false); + } + + public static ItemStackFilter of(ItemStack filter) { + return of(filter, true); + } + + public static ItemStackFilter of(ItemStack filter, boolean isStrict) { + if (filter.hasTag()) { + CompoundTag stackTag = filter.getTag(); + assert stackTag != null; + stackTag.remove("Enchantments"); + stackTag.remove("AttributeModifiers"); + } + return new ItemStackFilter(filter, isStrict); + } + + @Override + public boolean test(ItemStack stack) { + if (stack.isEmpty()) return false; + if (filter.isEmpty()) return true; + + if (isStrict) { + return ItemHandlerHelper.canItemStacksStack(filter, stack); + } + else { + return filter.is(stack.getItem()); + } + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag tag = new CompoundTag(); + tag.put(FILTER_KEY, filter.serializeNBT()); + tag.putBoolean(STRICT_KEY, isStrict); + return tag; + } + + @Override + public void deserializeNBT(CompoundTag tag) { + filter = ItemStack.of(tag.getCompound(FILTER_KEY)); + isStrict = tag.getBoolean(STRICT_KEY); + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/util/ItemStackFilterList.java b/src/main/java/com/github/elenterius/biomancy/util/ItemStackFilterList.java new file mode 100644 index 000000000..b38b19767 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/util/ItemStackFilterList.java @@ -0,0 +1,92 @@ +package com.github.elenterius.biomancy.util; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.util.INBTSerializable; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +public class ItemStackFilterList extends AbstractList implements INBTSerializable { + + private List filters; + + protected ItemStackFilterList(List filters) { + this.filters = new ArrayList<>(filters); + } + + public static ItemStackFilterList of(ItemStackFilter filter) { + return new ItemStackFilterList(List.of(filter)); + } + + public static ItemStackFilterList of(ItemStackFilter filter, int size) { + return new ItemStackFilterList(IntStream.range(0, size).mapToObj(x -> filter).toList()); + } + + public static ItemStackFilterList of(List filters) { + return new ItemStackFilterList(filters); + } + + public void setAllFilters(List filters) { + this.filters = filters; + } + + public void setAllFilters(ItemStackFilter filter) { + filters = IntStream.range(0, filters.size()).mapToObj(x -> filter).toList(); + } + + public void setFilter(int index, ItemStackFilter filter) { + filters.set(index, filter); + } + + @Override + public ItemStackFilter set(int index, ItemStackFilter filter) { + return filters.set(index, filter); + } + + @Override + public ItemStackFilter get(int index) { + return filters.get(index); + } + + @Override + public int size() { + return filters.size(); + } + + public boolean test(int index, ItemStack stack) { + if (index <= 0 || index > size()) return false; + return filters.get(index).test(stack); + } + + @Override + public void deserializeNBT(CompoundTag tag) { + ListTag listTag = tag.getList("filters", Tag.TAG_COMPOUND); + + List newFilters = new ArrayList<>(); + for (int i = 0; i < listTag.size(); i++) { + newFilters.add(ItemStackFilter.of(listTag.getCompound(i))); + } + + filters = List.copyOf(newFilters); + } + + @Override + public CompoundTag serializeNBT() { + + ListTag listTag = new ListTag(); + for (ItemStackFilter filter : filters) { + listTag.add(filter.serializeNBT()); + } + + CompoundTag tag = new CompoundTag(); + tag.put("filters", listTag); + + return tag; + } + +} diff --git a/src/main/java/com/github/elenterius/biomancy/util/PlayerInteractionPredicate.java b/src/main/java/com/github/elenterius/biomancy/util/PlayerInteractionPredicate.java new file mode 100644 index 000000000..132b5e909 --- /dev/null +++ b/src/main/java/com/github/elenterius/biomancy/util/PlayerInteractionPredicate.java @@ -0,0 +1,7 @@ +package com.github.elenterius.biomancy.util; + +import net.minecraft.world.entity.player.Player; + +public interface PlayerInteractionPredicate { + boolean canPlayerInteract(Player player); +}