From 2b7fa6bf05ffa8f362abfaf7b47e9bebec5478e5 Mon Sep 17 00:00:00 2001 From: wmaxlees Date: Wed, 18 Sep 2024 11:28:21 -0600 Subject: [PATCH 01/17] Added storageblock registry and added rack. Updated warehouse to work with registry? --- .../minecolonies/api/IMinecoloniesAPI.java | 3 + .../api/MinecoloniesAPIProxy.java | 3 + .../storageblocks/IStorageBlockInterface.java | 35 +++++ .../storageblocks/ModStorageBlocks.java | 47 +++++++ .../registry/StorageBlockEntry.java | 127 ++++++++++++++++++ .../apiimp/CommonMinecoloniesAPIImpl.java | 14 ++ .../workerbuildings/BuildingWareHouse.java | 52 +++---- .../RackStorageBlockInterface.java | 36 +++++ 8 files changed, 291 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java create mode 100644 src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java diff --git a/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java b/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java index 8c90e379254..b76f95bb137 100755 --- a/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java +++ b/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java @@ -27,6 +27,7 @@ import com.minecolonies.api.research.ModResearchCostTypes.ResearchCostType; import com.minecolonies.api.research.effects.registry.ResearchEffectEntry; import com.minecolonies.api.research.registry.ResearchRequirementEntry; +import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.NewRegistryEvent; @@ -101,4 +102,6 @@ static IMinecoloniesAPI getInstance() void onRegistryNewRegistry(NewRegistryEvent event); IForgeRegistry getEquipmentTypeRegistry(); + + IForgeRegistry getStorageBlockRegistry(); } diff --git a/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java b/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java index 12d82f35011..bd88f630941 100755 --- a/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java +++ b/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java @@ -27,6 +27,7 @@ import com.minecolonies.api.research.ModResearchCostTypes.ResearchCostType; import com.minecolonies.api.research.effects.registry.ResearchEffectEntry; import com.minecolonies.api.research.registry.ResearchRequirementEntry; +import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.NewRegistryEvent; @@ -235,4 +236,6 @@ public IForgeRegistry getEquipmentTypeRegistry() { return apiInstance.getEquipmentTypeRegistry(); } + + public IForgeRegistry getStorageBlockRegistry() { return apiInstance.getStorageBlockRegistry(); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java new file mode 100644 index 00000000000..caa5b4691b4 --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java @@ -0,0 +1,35 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import net.minecraft.world.level.block.entity.BlockEntity; + +public interface IStorageBlockInterface +{ + /** + * Whether the storageblock should be included in building containers automatically. + * @return Whether the storageblock should be included in building containers automatically. + */ + boolean automaticallyAddToBuilding(); + + /** + * Sets whether the block is part of a warehouse. + * + * @param blockEntity The blockentity to set + * @param inWarehouse Whether it's in a warehouse + */ + void setInWarehouse(BlockEntity blockEntity, boolean inWarehouse); + + /** + * Gets the current upgrade level of the storageblock + * + * @param blockEntity The blockentity to get the level of + * @return The current level + */ + int getUpgradeLevel(BlockEntity blockEntity); + + /** + * Upgrades the size of the storage, if applicable. + * + * @param blockEntity The blockentity to increase the level of + */ + void increaseUpgradeLevel(BlockEntity blockEntity); +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java new file mode 100644 index 00000000000..30ca679a39d --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -0,0 +1,47 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import com.minecolonies.api.MinecoloniesAPIProxy; +import com.minecolonies.api.tileentities.AbstractTileEntityRack; +import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; +import com.minecolonies.api.util.constant.Constants; +import com.minecolonies.core.tileentities.TileEntityRack; +import com.minecolonies.core.tileentities.storagecontainers.RackStorageBlockInterface; +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; + +import java.util.Optional; + +public final class ModStorageBlocks +{ + public static final DeferredRegister DEFERRED_REGISTER = DeferredRegister.create(new ResourceLocation(Constants.MOD_ID, "storageblocks"), Constants.MOD_ID); + + public static final RegistryObject rack; + static + { + rack = DEFERRED_REGISTER.register("rack", + () -> new StorageBlockEntry.Builder() + .setIsStorageBlock(blockEntity -> blockEntity instanceof AbstractTileEntityRack) + .setRegistryName(new ResourceLocation(Constants.MOD_ID, "rack")) + .setStorageInterface(new RackStorageBlockInterface()) + .build()); + } + + public static Optional getStorageBlockInterface(BlockEntity blockEntity) { + for (StorageBlockEntry entry : MinecoloniesAPIProxy.getInstance().getStorageBlockRegistry()) { + if (entry.matches(blockEntity)) { + return Optional.of(entry.getStorageInterface()); + } + } + + return Optional.empty(); + } + + /** + * Private constructor so this class can't be instantiated. + */ + private ModStorageBlocks() {} +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java new file mode 100644 index 00000000000..905e4e021f5 --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -0,0 +1,127 @@ +package com.minecolonies.api.tileentities.storageblocks.registry; + +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.entity.BlockEntity; + +import java.util.function.Predicate; + +public final class StorageBlockEntry +{ + /** + * The registry identifier for this storage block. + */ + private final ResourceLocation registryName; + + /** + * Predicate to determine whether a given BlockEntity + * is this storage block type. + */ + private final Predicate isStorageBlock; + + /** + * The interface that will be used to interact with the particular block. + */ + private final IStorageBlockInterface storageInterface; + + /** + * Constructor + * + * @param registryName The registry name of this entry + * @param isStorageBlock The predicate to determine if a block is this storage block type + * @param storageInterface The interface used to interact with the particular block + */ + public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, IStorageBlockInterface storageInterface) + { + this.registryName = registryName; + this.isStorageBlock = isStorageBlock; + this.storageInterface = storageInterface; + } + + /** + * Check whether a particular blockentity is this type of storageblock + * + * @param blockEntity The block entity to check + * @return Whether the blockentity matches or not. + */ + public boolean matches(final BlockEntity blockEntity) + { + return isStorageBlock.test(blockEntity); + } + + /** + * Get the storageinterface that knows how to interact with this block type. + * + * @return The interface. + */ + public IStorageBlockInterface getStorageInterface() + { + return storageInterface; + } + + public static class Builder + { + /** + * The registry identifier for this storage block. + */ + private ResourceLocation registryName; + + /** + * Predicate to determine whether a given BlockEntity + * is this storage block type. + */ + private Predicate isStorageBlock; + + /** + * The interface that will be used to interact with the particular block. + */ + private IStorageBlockInterface storageInterface; + + /** + * Set the registry name for the StorageBlockEntry being built. + * + * @param registryName The new registry name + * @return this + */ + public Builder setRegistryName(ResourceLocation registryName) + { + this.registryName = registryName; + return this; + } + + /** + * Set the predicate to check if a block is the given storage block type + * for the StorageBlockEntry being built. + * + * @param isStorageBlock The new predicate + * @return this + */ + public Builder setIsStorageBlock(Predicate isStorageBlock) + { + this.isStorageBlock = isStorageBlock; + return this; + } + + /** + * Set the interface that will be used to interact with blocks of this kind. + * + * @param storageInterface The interface + * @return this + */ + public Builder setStorageInterface(IStorageBlockInterface storageInterface) + { + this.storageInterface = storageInterface; + return this; + } + + /** + * Build the StorageBlockEntry. + * + * @return the new StorageBlockEntry + */ + public StorageBlockEntry build() + { + return new StorageBlockEntry(registryName, isStorageBlock, storageInterface); + } + } +} diff --git a/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java b/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java index 7400bf0fa5e..9e2cd755708 100755 --- a/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java +++ b/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java @@ -29,6 +29,7 @@ import com.minecolonies.api.research.ModResearchCostTypes.ResearchCostType; import com.minecolonies.api.research.effects.registry.ResearchEffectEntry; import com.minecolonies.api.research.registry.ResearchRequirementEntry; +import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.MineColonies; import com.minecolonies.core.colony.CitizenDataManager; @@ -80,6 +81,7 @@ public class CommonMinecoloniesAPIImpl implements IMinecoloniesAPI private IForgeRegistry questDialogueAnswerRegistry; private IForgeRegistry happinessFactorTypeRegistry; private IForgeRegistry happinessFunctionRegistry; + private IForgeRegistry storageBlockRegistry; @Override @NotNull @@ -326,6 +328,12 @@ public void onRegistryNewRegistry(final NewRegistryEvent event) .setDefaultKey(new ResourceLocation(Constants.MOD_ID, "null")) .disableSaving().allowModification() .setIDRange(0, Integer.MAX_VALUE - 1), (b) -> happinessFunctionRegistry = b); + + event.create(new RegistryBuilder() + .setName(new ResourceLocation(Constants.MOD_ID, "storageblocks")) + .setDefaultKey(new ResourceLocation(Constants.MOD_ID, "null")) + .disableSaving().allowModification() + .setIDRange(0, Integer.MAX_VALUE - 1), (b) -> storageBlockRegistry = b); } @Override @@ -393,5 +401,11 @@ public IForgeRegistry getEquipmentTypeRegistry() { return equipmentTypeRegistry; } + + @Override + public IForgeRegistry getStorageBlockRegistry() + { + return storageBlockRegistry; + } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 5d2f253f037..10d6012ac18 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -9,8 +9,9 @@ import com.minecolonies.api.colony.buildings.workerbuildings.IWareHouse; import com.minecolonies.api.colony.requestsystem.resolver.IRequestResolver; import com.minecolonies.api.tileentities.*; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.constant.TypeConstants; -import com.minecolonies.core.blocks.BlockMinecoloniesRack; import com.minecolonies.core.client.gui.WindowHutMinPlaceholder; import com.minecolonies.core.colony.buildings.AbstractBuilding; import com.minecolonies.core.colony.buildings.modules.CourierAssignmentModule; @@ -21,7 +22,6 @@ import com.minecolonies.core.colony.requestsystem.resolvers.WarehouseConcreteRequestResolver; import com.minecolonies.core.colony.requestsystem.resolvers.WarehouseRequestResolver; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; -import com.minecolonies.core.tileentities.TileEntityRack; import com.minecolonies.core.tileentities.TileEntityWareHouse; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; @@ -29,6 +29,8 @@ import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.NotNull; +import java.util.Optional; + /** * Class of the warehouse building. */ @@ -63,17 +65,16 @@ public BuildingWareHouse(final IColony c, final BlockPos l) @Override public void requestRepair(final BlockPos builder) { - //To ensure that the racks are all set to in the warehouse when repaired. + //To ensure that the storageblocks are all set to in the warehouse when repaired. for (final BlockPos pos : containerList) { - if (getColony().getWorld() != null) - { - final BlockEntity entity = getColony().getWorld().getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - ((AbstractTileEntityRack) entity).setInWarehouse(true); - } + if (getColony().getWorld() == null) { + continue; } + + final BlockEntity entity = getColony().getWorld().getBlockEntity(pos); + Optional blockInterface = ModStorageBlocks.getStorageBlockInterface(entity); + blockInterface.ifPresent(i -> i.setInWarehouse(entity, true)); } super.requestRepair(builder); @@ -119,18 +120,19 @@ public int getMaxBuildingLevel() @Override public void registerBlockPosition(@NotNull final Block block, @NotNull final BlockPos pos, @NotNull final Level world) { - if (block instanceof BlockMinecoloniesRack) - { - final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - ((AbstractTileEntityRack) entity).setInWarehouse(true); - while (((TileEntityRack) entity).getUpgradeSize() < getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade()) - { - ((TileEntityRack) entity).upgradeRackSize(); - } - } + BlockEntity entity = world.getBlockEntity(pos); + Optional blockInterface = ModStorageBlocks.getStorageBlockInterface(entity); + + if (blockInterface.isEmpty() || !blockInterface.get().automaticallyAddToBuilding()) { + return; } + + blockInterface.get().setInWarehouse(entity, true); + int targetLevel = getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade(); + while (blockInterface.get().getUpgradeLevel(entity) < targetLevel) { + blockInterface.get().increaseUpgradeLevel(entity); + } + super.registerBlockPosition(block, pos, world); } @@ -167,11 +169,9 @@ public void upgradeContainers(final Level world) { for (final BlockPos pos : getContainers()) { - final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack && !(entity instanceof TileEntityColonyBuilding)) - { - ((AbstractTileEntityRack) entity).upgradeRackSize(); - } + BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + storageInterface.ifPresent(i -> i.increaseUpgradeLevel(entity)); } getFirstModuleOccurance(WarehouseModule.class).incrementStorageUpgrade(); } diff --git a/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java new file mode 100644 index 00000000000..a8bd1443a97 --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java @@ -0,0 +1,36 @@ +package com.minecolonies.core.tileentities.storagecontainers; + +import com.minecolonies.api.tileentities.AbstractTileEntityRack; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import net.minecraft.world.level.block.entity.BlockEntity; + +public class RackStorageBlockInterface implements IStorageBlockInterface +{ + @Override + public boolean automaticallyAddToBuilding() + { + return true; + } + + @Override + public void setInWarehouse(BlockEntity blockEntity, final boolean inWarehouse) + { + getRack(blockEntity).setInWarehouse(inWarehouse); + } + + @Override + public int getUpgradeLevel(BlockEntity blockEntity) + { + return getRack(blockEntity).getUpgradeSize(); + } + + @Override + public void increaseUpgradeLevel(BlockEntity blockEntity) + { + getRack(blockEntity).upgradeRackSize(); + } + + private AbstractTileEntityRack getRack(BlockEntity blockEntity) { + return (AbstractTileEntityRack) blockEntity; + } +} From 190ddbd0e184ae47073f09ed8e3dbb708a0083e7 Mon Sep 17 00:00:00 2001 From: wmaxlees Date: Wed, 18 Sep 2024 12:07:05 -0600 Subject: [PATCH 02/17] Updated InventoryUtils to work with the new registry --- .../storageblocks/IStorageBlockInterface.java | 54 +++++++++++- .../storageblocks/ModStorageBlocks.java | 2 +- .../minecolonies/api/util/InventoryUtils.java | 85 ++++++++++++------- .../workerbuildings/BuildingWareHouse.java | 3 + .../RackStorageBlockInterface.java | 66 +++++++++++++- 5 files changed, 170 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java index caa5b4691b4..201db7b96c1 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java @@ -1,7 +1,12 @@ package com.minecolonies.api.tileentities.storageblocks; +import com.minecolonies.api.crafting.ItemStorage; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; +import java.util.Map; +import java.util.function.Predicate; + public interface IStorageBlockInterface { /** @@ -16,7 +21,7 @@ public interface IStorageBlockInterface * @param blockEntity The blockentity to set * @param inWarehouse Whether it's in a warehouse */ - void setInWarehouse(BlockEntity blockEntity, boolean inWarehouse); + void setInWarehouse(final BlockEntity blockEntity, final boolean inWarehouse); /** * Gets the current upgrade level of the storageblock @@ -24,12 +29,55 @@ public interface IStorageBlockInterface * @param blockEntity The blockentity to get the level of * @return The current level */ - int getUpgradeLevel(BlockEntity blockEntity); + int getUpgradeLevel(final BlockEntity blockEntity); /** * Upgrades the size of the storage, if applicable. * * @param blockEntity The blockentity to increase the level of */ - void increaseUpgradeLevel(BlockEntity blockEntity); + void increaseUpgradeLevel(final BlockEntity blockEntity); + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param blockEntity the blockentity to check + * @param storage The item to check for + */ + int getCount(final BlockEntity blockEntity, final ItemStorage storage); + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param blockEntity the blockentity to check + * @param predicate The predicate used to select items + */ + int getItemCount(final BlockEntity blockEntity, final Predicate predicate); + + /** + * Return the number of free slots in the container. + * + * @param blockEntity the block entity to check + * @return The free slots + */ + int getFreeSlots(final BlockEntity blockEntity); + + /** + * Gets all items and their count from the storage block. + * + * @param blockEntity the block entity to check + * @return The items and their count + */ + Map getAllContent(final BlockEntity blockEntity); + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param blockEntity the block entity to check + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + int getCount(final BlockEntity blockEntity, final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index 30ca679a39d..ac1b32c141f 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -24,7 +24,7 @@ public final class ModStorageBlocks { rack = DEFERRED_REGISTER.register("rack", () -> new StorageBlockEntry.Builder() - .setIsStorageBlock(blockEntity -> blockEntity instanceof AbstractTileEntityRack) + .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityRack) .setRegistryName(new ResourceLocation(Constants.MOD_ID, "rack")) .setStorageInterface(new RackStorageBlockInterface()) .build()); diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 0f5a8edd69b..ef25184dddc 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -6,6 +6,8 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.BlockPos; @@ -750,11 +752,13 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - totalCount += ((TileEntityRack) entity).getCount(stack); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; } + totalCount += storageInterface.get().getCount(entity, stack); + if (totalCount >= count) { return Integer.MAX_VALUE; @@ -782,11 +786,13 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - totalCount += ((TileEntityRack) entity).getItemCount(stack); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; } + totalCount += storageInterface.get().getItemCount(entity, stack); + if (totalCount >= count) { return totalCount; @@ -833,10 +839,12 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - totalCount += ((TileEntityRack) entity).getCount(stack); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; } + + totalCount += storageInterface.get().getCount(entity, stack); } } @@ -858,10 +866,12 @@ public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - totalCount += ((TileEntityRack) entity).getFreeSlots(); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; } + + totalCount += storageInterface.get().getFreeSlots(entity); } } @@ -883,8 +893,12 @@ public static boolean isBuildingFull(final IBuilding ownBuilding) if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack rack && rack.getFreeSlots() > 0) - { + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + if (storageInterface.get().getFreeSlots(entity) > 0) { return false; } } @@ -910,10 +924,12 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - totalCount += ((TileEntityRack) entity).getItemCount(predicate); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; } + + totalCount += storageInterface.get().getItemCount(entity, predicate); } } @@ -939,14 +955,16 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + for (final Map.Entry entry : storageInterface.get().getAllContent(entity).entrySet()) { - for (final Map.Entry entry : ((TileEntityRack) entity).getAllContent().entrySet()) + if (predicate.test(entry.getKey().getItemStack())) { - if (predicate.test(entry.getKey().getItemStack())) - { - allMatching.put(entry.getKey(), allMatching.getOrDefault(entry.getKey(), 0) + entry.getValue()); - } + allMatching.put(entry.getKey(), allMatching.getOrDefault(entry.getKey(), 0) + entry.getValue()); } } } @@ -3200,12 +3218,13 @@ public static boolean hasEnoughInProvider(final BlockEntity entity, final ItemSt { return InventoryUtils.hasBuildingEnoughElseCount( ((TileEntityColonyBuilding) entity).getBuilding(), new ItemStorage(stack), stack.getCount()) >= count; } - else if (entity instanceof TileEntityRack) - { - return ((TileEntityRack) entity).getCount(stack, false, false) >= count; + + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isPresent()) { + return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; } - return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; + return storageInterface.get().getCount(entity, stack, false, false) >= count; } public static List getBuildingInventory(final IBuilding building) @@ -3217,12 +3236,14 @@ public static List getBuildingInventory(final IBuilding building) if (WorldUtil.isBlockLoaded(world, pos)) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + for (final ItemStorage storage : storageInterface.get().getAllContent(entity).keySet()) { - for (final ItemStorage storage : ((TileEntityRack) entity).getAllContent().keySet()) - { - allInInv.add(storage.getItemStack()); - } + allInInv.add(storage.getItemStack()); } } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 10d6012ac18..e5d078e4350 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -170,6 +170,9 @@ public void upgradeContainers(final Level world) for (final BlockPos pos : getContainers()) { BlockEntity entity = world.getBlockEntity(pos); + if (entity instanceof TileEntityColonyBuilding) { + continue; + } Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); storageInterface.ifPresent(i -> i.increaseUpgradeLevel(entity)); } diff --git a/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java index a8bd1443a97..2587e9ff177 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java @@ -1,9 +1,18 @@ package com.minecolonies.core.tileentities.storagecontainers; +import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.core.tileentities.TileEntityRack; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; +import java.util.Map; +import java.util.function.Predicate; + +/** + * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) + */ public class RackStorageBlockInterface implements IStorageBlockInterface { @Override @@ -15,22 +24,71 @@ public boolean automaticallyAddToBuilding() @Override public void setInWarehouse(BlockEntity blockEntity, final boolean inWarehouse) { - getRack(blockEntity).setInWarehouse(inWarehouse); + getAbstractRack(blockEntity).setInWarehouse(inWarehouse); } @Override public int getUpgradeLevel(BlockEntity blockEntity) { - return getRack(blockEntity).getUpgradeSize(); + return getAbstractRack(blockEntity).getUpgradeSize(); } @Override public void increaseUpgradeLevel(BlockEntity blockEntity) { - getRack(blockEntity).upgradeRackSize(); + getAbstractRack(blockEntity).upgradeRackSize(); + } + + @Override + public int getCount(final BlockEntity blockEntity, final ItemStorage storage) + { + return getAbstractRack(blockEntity).getCount(storage); + } + + @Override + public int getItemCount(final BlockEntity blockEntity, final Predicate predicate) + { + return getAbstractRack(blockEntity).getItemCount(predicate); } - private AbstractTileEntityRack getRack(BlockEntity blockEntity) { + @Override + public int getFreeSlots(final BlockEntity blockEntity) + { + return getAbstractRack(blockEntity).getFreeSlots(); + } + + /** + * Gets all items and their count from the storage block. + * + * @param blockEntity the block entity to check + * @return The items and their count + */ + @Override + public Map getAllContent(final BlockEntity blockEntity) + { + return getRack(blockEntity).getAllContent(); + } + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param blockEntity the block entity to check + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + @Override + public int getCount(final BlockEntity blockEntity, final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) + { + return getAbstractRack(blockEntity).getCount(stack, ignoreDamageValue, ignoreNBT); + } + + private AbstractTileEntityRack getAbstractRack(BlockEntity blockEntity) { return (AbstractTileEntityRack) blockEntity; } + + private TileEntityRack getRack(BlockEntity blockEntity) { + return (TileEntityRack) blockEntity; + } } From b9d3f6b0963f9b87475c625b124f6ff2f8cb1298 Mon Sep 17 00:00:00 2001 From: wmaxlees Date: Wed, 18 Sep 2024 12:11:07 -0600 Subject: [PATCH 03/17] Cleaned up imports --- .../api/tileentities/storageblocks/ModStorageBlocks.java | 3 --- src/main/java/com/minecolonies/api/util/InventoryUtils.java | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index ac1b32c141f..a08334953ed 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -1,14 +1,11 @@ package com.minecolonies.api.tileentities.storageblocks; import com.minecolonies.api.MinecoloniesAPIProxy; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.tileentities.TileEntityRack; import com.minecolonies.core.tileentities.storagecontainers.RackStorageBlockInterface; -import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.RegistryObject; diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index ef25184dddc..5624878ec5b 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -9,7 +9,6 @@ import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; -import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; @@ -22,7 +21,6 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ChestBlockEntity; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.items.IItemHandler; From a89570cfe49b1d8192a1feb6346aa22b159b11c5 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sat, 21 Sep 2024 23:19:13 -0600 Subject: [PATCH 04/17] Changed storage checks from hardcoded Rack checks to a registry that handles arbitrary storage block types --- .../storageblocks/IStorageBlockInterface.java | 72 +++++-- .../storageblocks/ModStorageBlocks.java | 26 ++- .../registry/StorageBlockEntry.java | 20 +- .../minecolonies/api/util/InventoryUtils.java | 20 +- .../com/minecolonies/core/MineColonies.java | 2 + .../client/gui/WindowHutAllInventory.java | 66 ++++--- .../core/client/gui/WindowsBarracksSpies.java | 9 +- .../buildings/AbstractBuildingContainer.java | 17 +- .../workerbuildings/BuildingWareHouse.java | 15 +- .../ai/workers/AbstractEntityAIBasic.java | 27 ++- .../service/EntityAIWorkDeliveryman.java | 25 +-- .../core/items/ItemResourceScroll.java | 30 +-- .../TileEntityColonyBuilding.java | 63 +++--- .../tileentities/TileEntityWareHouse.java | 180 +++++++++++------- .../AbstractRackStorageBlockInterface.java | 151 +++++++++++++++ .../AbstractStorageBlockInterface.java | 12 ++ .../RackStorageBlockInterface.java | 153 +++++++++++++++ .../RackStorageBlockInterface.java | 94 --------- 18 files changed, 665 insertions(+), 317 deletions(-) create mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java create mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java create mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java delete mode 100644 src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java index 201db7b96c1..86846747468 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java @@ -1,8 +1,10 @@ package com.minecolonies.api.tileentities.storageblocks; +import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.crafting.ItemStorage; +import net.minecraft.core.BlockPos; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandlerModifiable; import java.util.Map; import java.util.function.Predicate; @@ -11,73 +13,105 @@ public interface IStorageBlockInterface { /** * Whether the storageblock should be included in building containers automatically. + * + * @param building The building that is being constructed. * @return Whether the storageblock should be included in building containers automatically. */ - boolean automaticallyAddToBuilding(); + boolean shouldAutomaticallyAdd(final IBuilding building); /** * Sets whether the block is part of a warehouse. * - * @param blockEntity The blockentity to set * @param inWarehouse Whether it's in a warehouse */ - void setInWarehouse(final BlockEntity blockEntity, final boolean inWarehouse); + void setInWarehouse(final boolean inWarehouse); /** * Gets the current upgrade level of the storageblock * - * @param blockEntity The blockentity to get the level of * @return The current level */ - int getUpgradeLevel(final BlockEntity blockEntity); + int getUpgradeLevel(); /** * Upgrades the size of the storage, if applicable. - * - * @param blockEntity The blockentity to increase the level of */ - void increaseUpgradeLevel(final BlockEntity blockEntity); + void increaseUpgradeLevel(); /** * Gets the amount of a particular item contained in the storageblock * - * @param blockEntity the blockentity to check * @param storage The item to check for */ - int getCount(final BlockEntity blockEntity, final ItemStorage storage); + int getCount(final ItemStorage storage); /** * Gets the amount of a particular item contained in the storageblock * - * @param blockEntity the blockentity to check * @param predicate The predicate used to select items */ - int getItemCount(final BlockEntity blockEntity, final Predicate predicate); + int getItemCount(final Predicate predicate); /** * Return the number of free slots in the container. * - * @param blockEntity the block entity to check * @return The free slots */ - int getFreeSlots(final BlockEntity blockEntity); + int getFreeSlots(); /** * Gets all items and their count from the storage block. * - * @param blockEntity the block entity to check * @return The items and their count */ - Map getAllContent(final BlockEntity blockEntity); + Map getAllContent(); /** * Gets the matching count for a specific item stack and can ignore NBT and damage as well. * - * @param blockEntity the block entity to check * @param stack The stack to check against * @param ignoreDamageValue Whether to ignore damage * @param ignoreNBT Whether to ignore nbt data * @return The count of matching items in the storageblock */ - int getCount(final BlockEntity blockEntity, final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); + int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + boolean isEmpty(); + + /** + * Get the modifiable ItemHandler for the given storageblock + * + * @return the itemhandler + */ + IItemHandlerModifiable getInventory(); + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + boolean hasItemStack(final Predicate predicate); + + /** + * Sets the block position of the building this storage belongs to + * + * @param pos The position of the building + */ + void setBuildingPos(final BlockPos pos); } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index a08334953ed..94fcba1f2c4 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -1,10 +1,13 @@ package com.minecolonies.api.tileentities.storageblocks; import com.minecolonies.api.MinecoloniesAPIProxy; +import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; +import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.tileentities.TileEntityRack; -import com.minecolonies.core.tileentities.storagecontainers.RackStorageBlockInterface; +import com.minecolonies.core.tileentities.storageblocks.AbstractRackStorageBlockInterface; +import com.minecolonies.core.tileentities.storageblocks.RackStorageBlockInterface; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.registries.DeferredRegister; @@ -16,21 +19,34 @@ public final class ModStorageBlocks { public static final DeferredRegister DEFERRED_REGISTER = DeferredRegister.create(new ResourceLocation(Constants.MOD_ID, "storageblocks"), Constants.MOD_ID); - public static final RegistryObject rack; + public static final RegistryObject storageBlockRack; + public static final RegistryObject storageBlockAbstractRack; + static { - rack = DEFERRED_REGISTER.register("rack", + storageBlockRack = DEFERRED_REGISTER.register("rack", () -> new StorageBlockEntry.Builder() .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityRack) .setRegistryName(new ResourceLocation(Constants.MOD_ID, "rack")) - .setStorageInterface(new RackStorageBlockInterface()) + .setStorageInterface(RackStorageBlockInterface::new) .build()); + + storageBlockAbstractRack = DEFERRED_REGISTER.register("abstract_rack", + () -> new StorageBlockEntry.Builder() + .setIsStorageBlock(blockEntity -> blockEntity instanceof AbstractTileEntityRack && !(blockEntity instanceof TileEntityRack)) + .setRegistryName(new ResourceLocation(Constants.MOD_ID, "abstract_rack")) + .setStorageInterface(AbstractRackStorageBlockInterface::new) + .build()); } public static Optional getStorageBlockInterface(BlockEntity blockEntity) { + if (blockEntity == null) { + return Optional.empty(); + } + for (StorageBlockEntry entry : MinecoloniesAPIProxy.getInstance().getStorageBlockRegistry()) { if (entry.matches(blockEntity)) { - return Optional.of(entry.getStorageInterface()); + return Optional.of(entry.getStorageInterface().apply(blockEntity)); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index 905e4e021f5..91be066ae80 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -4,6 +4,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; +import java.util.function.Function; import java.util.function.Predicate; public final class StorageBlockEntry @@ -22,7 +23,7 @@ public final class StorageBlockEntry /** * The interface that will be used to interact with the particular block. */ - private final IStorageBlockInterface storageInterface; + private final Function storageInterface; /** * Constructor @@ -31,7 +32,7 @@ public final class StorageBlockEntry * @param isStorageBlock The predicate to determine if a block is this storage block type * @param storageInterface The interface used to interact with the particular block */ - public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, IStorageBlockInterface storageInterface) + public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, Function storageInterface) { this.registryName = registryName; this.isStorageBlock = isStorageBlock; @@ -54,11 +55,20 @@ public boolean matches(final BlockEntity blockEntity) * * @return The interface. */ - public IStorageBlockInterface getStorageInterface() + public Function getStorageInterface() { return storageInterface; } + /** + * Returns the registry name for this entry + * + * @return The registry name + */ + public ResourceLocation getRegistryName() { + return registryName; + } + public static class Builder { /** @@ -75,7 +85,7 @@ public static class Builder /** * The interface that will be used to interact with the particular block. */ - private IStorageBlockInterface storageInterface; + private Function storageInterface; /** * Set the registry name for the StorageBlockEntry being built. @@ -108,7 +118,7 @@ public Builder setIsStorageBlock(Predicate isStorageBlock) * @param storageInterface The interface * @return this */ - public Builder setStorageInterface(IStorageBlockInterface storageInterface) + public Builder setStorageInterface(Function storageInterface) { this.storageInterface = storageInterface; return this; diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 5624878ec5b..ef7accc4f88 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -755,7 +755,7 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, continue; } - totalCount += storageInterface.get().getCount(entity, stack); + totalCount += storageInterface.get().getCount(stack); if (totalCount >= count) { @@ -789,7 +789,7 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, continue; } - totalCount += storageInterface.get().getItemCount(entity, stack); + totalCount += storageInterface.get().getItemCount(stack); if (totalCount >= count) { @@ -842,7 +842,7 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu continue; } - totalCount += storageInterface.get().getCount(entity, stack); + totalCount += storageInterface.get().getCount(stack); } } @@ -869,7 +869,7 @@ public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) continue; } - totalCount += storageInterface.get().getFreeSlots(entity); + totalCount += storageInterface.get().getFreeSlots(); } } @@ -896,7 +896,7 @@ public static boolean isBuildingFull(final IBuilding ownBuilding) continue; } - if (storageInterface.get().getFreeSlots(entity) > 0) { + if (storageInterface.get().getFreeSlots() > 0) { return false; } } @@ -927,7 +927,7 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu continue; } - totalCount += storageInterface.get().getItemCount(entity, predicate); + totalCount += storageInterface.get().getItemCount(predicate); } } @@ -958,7 +958,7 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide continue; } - for (final Map.Entry entry : storageInterface.get().getAllContent(entity).entrySet()) + for (final Map.Entry entry : storageInterface.get().getAllContent().entrySet()) { if (predicate.test(entry.getKey().getItemStack())) { @@ -3218,11 +3218,11 @@ public static boolean hasEnoughInProvider(final BlockEntity entity, final ItemSt } Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isPresent()) { + if (storageInterface.isEmpty()) { return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; } - return storageInterface.get().getCount(entity, stack, false, false) >= count; + return storageInterface.get().getCount(stack, false, false) >= count; } public static List getBuildingInventory(final IBuilding building) @@ -3239,7 +3239,7 @@ public static List getBuildingInventory(final IBuilding building) continue; } - for (final ItemStorage storage : storageInterface.get().getAllContent(entity).keySet()) + for (final ItemStorage storage : storageInterface.get().getAllContent().keySet()) { allInInv.add(storage.getItemStack()); } diff --git a/src/main/java/com/minecolonies/core/MineColonies.java b/src/main/java/com/minecolonies/core/MineColonies.java index c599e54483d..5e122b1168a 100755 --- a/src/main/java/com/minecolonies/core/MineColonies.java +++ b/src/main/java/com/minecolonies/core/MineColonies.java @@ -19,6 +19,7 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.loot.ModLootConditions; import com.minecolonies.api.sounds.ModSoundEvents; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.apiimp.ClientMinecoloniesAPIImpl; @@ -97,6 +98,7 @@ public MineColonies() ModLootConditions.DEFERRED_REGISTER.register(FMLJavaModLoadingContext.get().getModEventBus()); SupplyLoot.GLM.register(FMLJavaModLoadingContext.get().getModEventBus()); ModBannerPatterns.BANNER_PATTERNS.register(FMLJavaModLoadingContext.get().getModEventBus()); + ModStorageBlocks.DEFERRED_REGISTER.register(FMLJavaModLoadingContext.get().getModEventBus()); ModQuestInitializer.DEFERRED_REGISTER_OBJECTIVE.register(FMLJavaModLoadingContext.get().getModEventBus()); ModQuestInitializer.DEFERRED_REGISTER_TRIGGER.register(FMLJavaModLoadingContext.get().getModEventBus()); diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java index 8bab6e0ba8b..91222eadb22 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java @@ -6,7 +6,8 @@ import com.ldtteam.blockui.views.ScrollingList; import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.core.tileentities.TileEntityRack; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.MessageUtils; import com.minecolonies.api.util.Utils; import com.minecolonies.api.util.constant.Constants; @@ -125,23 +126,28 @@ private void locate(final Button button) for (BlockPos blockPos : containerList) { - final BlockEntity rack = Minecraft.getInstance().level.getBlockEntity(blockPos); - if (rack instanceof TileEntityRack) + final BlockEntity entity = Minecraft.getInstance().level.getBlockEntity(blockPos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + int count = storageInterface.get().getCount(storage.getItemStack(), storage.ignoreDamageValue(), false); + if (count <= 0) { - int count = ((TileEntityRack) rack).getCount(storage.getItemStack(), storage.ignoreDamageValue(), false); - if (count > 0) - { - // Varies the color between red(1 pc) over yellow(32 pcs) to green(64+ pcs) - // mixing equation: alpha | red part | green part - final int color = 0x80000000 | (Mth.clamp((int) (0xff * (2.0f - count / 32.0f)), 0, 255) << 16) - | (Mth.clamp((int) (0xff * count / 32.0f), 0, 255) << 8); - HighlightManager.addHighlight("inventoryHighlight" + blockPos, - new TimedBoxRenderData(blockPos) - .setDuration(Duration.ofSeconds(60)) - .addText("" + count) - .setColor(color)); - } + continue; } + + // Varies the color between red(1 pc) over yellow(32 pcs) to green(64+ pcs) + // mixing equation: alpha | red part | green part + final int color = 0x80000000 | (Mth.clamp((int) (0xff * (2.0f - count / 32.0f)), 0, 255) << 16) + | (Mth.clamp((int) (0xff * count / 32.0f), 0, 255) << 8); + HighlightManager.addHighlight("inventoryHighlight" + blockPos, + new TimedBoxRenderData(blockPos) + .setDuration(Duration.ofSeconds(60)) + .addText("" + count) + .setColor(color)); + } } @@ -201,21 +207,23 @@ private void updateResources() for (final BlockPos blockPos : containerList) { - final BlockEntity rack = world.getBlockEntity(blockPos); - if (rack instanceof TileEntityRack) - { - final Map rackStorage = ((TileEntityRack) rack).getAllContent(); + final BlockEntity entity = world.getBlockEntity(blockPos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + final Map storage = storageInterface.get().getAllContent(); - for (final Map.Entry entry : rackStorage.entrySet()) + for (final Map.Entry entry : storage.entrySet()) + { + if (storedItems.containsKey(entry.getKey())) + { + storedItems.put(entry.getKey(), storedItems.get(entry.getKey()) + entry.getValue()); + } + else { - if (storedItems.containsKey(entry.getKey())) - { - storedItems.put(entry.getKey(), storedItems.get(entry.getKey()) + entry.getValue()); - } - else - { - storedItems.put(entry.getKey(), entry.getValue()); - } + storedItems.put(entry.getKey(), entry.getValue()); } } } diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java index fb2b4449565..111b40fff6c 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java @@ -3,7 +3,8 @@ import com.ldtteam.blockui.controls.*; import com.ldtteam.blockui.views.BOWindow; import com.minecolonies.api.colony.buildings.views.IBuildingView; -import com.minecolonies.core.tileentities.TileEntityRack; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.InventoryUtils; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.Network; @@ -16,6 +17,8 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.wrapper.InvWrapper; +import java.util.Optional; + import static com.minecolonies.api.util.constant.TranslationConstants.DESCRIPTION_BARRACKS_HIRE_SPIES; /** @@ -68,10 +71,10 @@ public WindowsBarracksSpies(final IBuildingView buildingView, final BlockPos bui findPaneOfTypeByID(SPIES_BUTTON_ICON, ItemIcon.class).setItem(Items.GOLD_INGOT.getDefaultInstance()); findPaneOfTypeByID(GOLD_COST_LABEL, Text.class).setText(Component.literal("x5")); - final IItemHandler rackInv = ((TileEntityRack) buildingView.getColony().getWorld().getBlockEntity(buildingPos)).getInventory(); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingView.getColony().getWorld().getBlockEntity(buildingPos)); final IItemHandler playerInv = new InvWrapper(Minecraft.getInstance().player.getInventory()); int goldCount = InventoryUtils.getItemCountInItemHandler(playerInv, Items.GOLD_INGOT); - goldCount += InventoryUtils.getItemCountInItemHandler(rackInv, Items.GOLD_INGOT); + goldCount += storageInterface.map(iStorageBlockInterface -> iStorageBlockInterface.getItemCount(stack -> stack.is(Items.GOLD_INGOT))).orElse(0); if (!buildingView.getColony().isRaiding() || goldCount < GOLD_COST || buildingView.getColony().areSpiesEnabled()) { diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java index 15332162545..3235ba5af1d 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java @@ -6,9 +6,9 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.buildings.IBuildingContainer; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; -import com.minecolonies.core.tileentities.TileEntityRack; -import com.minecolonies.core.blocks.BlockMinecoloniesRack; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -169,14 +169,15 @@ public void registerBlockPosition(@NotNull final Block block, @NotNull final Blo } } } - else if (block instanceof BlockMinecoloniesRack) + else { - addContainerPosition(pos); - final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack rackEntity) - { - rackEntity.setBuildingPos(this.getID()); + BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + return; } + addContainerPosition(pos); + storageInterface.get().setBuildingPos(this.getID()); } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index e5d078e4350..50521879ef1 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -11,6 +11,7 @@ import com.minecolonies.api.tileentities.*; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; +import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.core.client.gui.WindowHutMinPlaceholder; import com.minecolonies.core.colony.buildings.AbstractBuilding; @@ -74,7 +75,7 @@ public void requestRepair(final BlockPos builder) final BlockEntity entity = getColony().getWorld().getBlockEntity(pos); Optional blockInterface = ModStorageBlocks.getStorageBlockInterface(entity); - blockInterface.ifPresent(i -> i.setInWarehouse(entity, true)); + blockInterface.ifPresent(i -> i.setInWarehouse(true)); } super.requestRepair(builder); @@ -123,14 +124,16 @@ public void registerBlockPosition(@NotNull final Block block, @NotNull final Blo BlockEntity entity = world.getBlockEntity(pos); Optional blockInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (blockInterface.isEmpty() || !blockInterface.get().automaticallyAddToBuilding()) { + if (blockInterface.isEmpty() || !blockInterface.get().shouldAutomaticallyAdd(this)) { return; } - blockInterface.get().setInWarehouse(entity, true); + Log.getLogger().atInfo().log("Adding new block to building: {}", block.getClass()); + + blockInterface.get().setInWarehouse(true); int targetLevel = getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade(); - while (blockInterface.get().getUpgradeLevel(entity) < targetLevel) { - blockInterface.get().increaseUpgradeLevel(entity); + while (blockInterface.get().getUpgradeLevel() < targetLevel) { + blockInterface.get().increaseUpgradeLevel(); } super.registerBlockPosition(block, pos, world); @@ -174,7 +177,7 @@ public void upgradeContainers(final Level world) continue; } Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - storageInterface.ifPresent(i -> i.increaseUpgradeLevel(entity)); + storageInterface.ifPresent(IStorageBlockInterface::increaseUpgradeLevel); } getFirstModuleOccurance(WarehouseModule.class).incrementStorageUpgrade(); } diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java index fb84477397f..831e93bfa82 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java @@ -25,6 +25,8 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.inventory.InventoryCitizen; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.api.util.constant.translation.RequestSystemTranslationConstants; @@ -36,7 +38,6 @@ import com.minecolonies.core.colony.jobs.JobDeliveryman; import com.minecolonies.core.colony.requestsystem.resolvers.StationRequestResolver; import com.minecolonies.core.entity.pathfinding.proxy.EntityCitizenWalkToProxy; -import com.minecolonies.core.tileentities.TileEntityRack; import com.minecolonies.core.util.WorkerUtil; import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; @@ -63,6 +64,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.function.Predicate; import static com.minecolonies.api.colony.requestsystem.requestable.deliveryman.AbstractDeliverymanRequestable.getMaxBuildingPriority; @@ -782,7 +784,7 @@ protected final boolean walkToBuilding() } /** - * Check all racks in the workers hut for a required item. + * Check all storageblocks in the workers hut for a required item. * Transfer to worker if found. * * @param is the type of item requested (amount is ignored) @@ -793,12 +795,17 @@ public boolean checkAndTransferFromHut(@Nullable final ItemStack is) for (final BlockPos pos : building.getContainers()) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack && ((TileEntityRack) entity).hasItemStack(is, 1, false)) + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + if (storageInterface.get().hasItemStack(is, 1, false)) { - entity.getCapability(ForgeCapabilities.ITEM_HANDLER, null) - .ifPresent((handler) -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(handler, + InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler( + storageInterface.get().getInventory(), (stack) -> ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack), - getInventory())); + getInventory()); return true; } } @@ -1029,16 +1036,16 @@ public boolean retrieveToolInHut(final EquipmentTypeEntry toolType, final int mi for (final BlockPos pos : building.getContainers()) { final BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isPresent()) { if (ModEquipmentTypes.none.get().equals(toolType)) { return false; } - if (((TileEntityRack) entity).hasItemStack(toolPredicate)) + if (storageInterface.get().hasItemStack(toolPredicate)) { - if (InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(entity.getCapability(ForgeCapabilities.ITEM_HANDLER, null).orElseGet(null), + if (InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(storageInterface.get().getInventory(), toolPredicate, worker.getInventoryCitizen())) { diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java index c93ec2ad0ea..42d957f6424 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java @@ -13,8 +13,9 @@ import com.minecolonies.api.entity.ai.statemachine.states.IAIState; import com.minecolonies.api.entity.citizen.VisibleCitizenStatus; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; -import com.minecolonies.core.tileentities.TileEntityRack; import com.minecolonies.api.util.InventoryUtils; import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.api.util.Log; @@ -41,6 +42,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static com.minecolonies.api.entity.ai.statemachine.states.AIWorkerState.*; @@ -565,18 +567,17 @@ public boolean gatherIfInTileEntity(final BlockEntity entity, final ItemStack is return false; } - if ((entity instanceof TileEntityColonyBuilding - && InventoryUtils.hasBuildingEnoughElseCount(((TileEntityColonyBuilding) entity).getBuilding(), new ItemStorage(is), is.getCount()) >= is.getCount()) || - (entity instanceof TileEntityRack && ((TileEntityRack) entity).getCount(new ItemStorage(is)) >= is.getCount())) + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + return false; + } + + if (storageInterface.get().getCount(new ItemStorage(is)) >= is.getCount()) { - final IItemHandler handler = entity.getCapability(ForgeCapabilities.ITEM_HANDLER, null).resolve().orElse(null); - if (handler != null) - { - return InventoryUtils.transferItemStackIntoNextFreeSlotFromItemHandler(handler, - stack -> !ItemStackUtils.isEmpty(stack) && ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack, true, true), - is.getCount(), - worker.getInventoryCitizen()); - } + return InventoryUtils.transferItemStackIntoNextFreeSlotFromItemHandler(storageInterface.get().getInventory(), + stack -> !ItemStackUtils.isEmpty(stack) && ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack, true, true), + is.getCount(), + worker.getInventoryCitizen()); } return false; diff --git a/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java b/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java index 936b2cc5df7..6baba511186 100755 --- a/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java +++ b/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java @@ -5,6 +5,8 @@ import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.colony.workorders.IWorkOrderView; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.MessageUtils; import com.minecolonies.api.util.constant.TranslationConstants; @@ -14,7 +16,6 @@ import com.minecolonies.core.colony.buildings.workerbuildings.BuildingBuilder; import com.minecolonies.core.colony.buildings.workerbuildings.BuildingWareHouse; import com.minecolonies.core.network.messages.server.ResourceScrollSaveWarehouseSnapshotMessage; -import com.minecolonies.core.tileentities.TileEntityRack; import com.minecolonies.core.tileentities.TileEntityWareHouse; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; @@ -205,20 +206,21 @@ private static ItemResourceScroll.WarehouseSnapshot gatherWarehouseSnapshot( for (final BlockPos container : warehouse.getContainerList()) { final BlockEntity blockEntity = warehouse.getColony().getWorld().getBlockEntity(container); - if (blockEntity instanceof TileEntityRack rack) - { - rack.getAllContent().forEach((item, amount) -> { - final int hashCode = item.getItemStack().hasTag() ? item.getItemStack().getTag().hashCode() : 0; - final String key = item.getItemStack().getDescriptionId() + "-" + hashCode; - if (!resourcesModule.getResources().containsKey(key)) - { - return; - } - - int oldAmount = items.getOrDefault(key, 0); - items.put(key, oldAmount + amount); - }); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(blockEntity); + if (storageInterface.isEmpty()) { + continue; } + storageInterface.get().getAllContent().forEach((item, amount) -> { + final int hashCode = item.getItemStack().hasTag() ? item.getItemStack().getTag().hashCode() : 0; + final String key = item.getItemStack().getDescriptionId() + "-" + hashCode; + if (!resourcesModule.getResources().containsKey(key)) + { + return; + } + + int oldAmount = items.getOrDefault(key, 0); + items.put(key, oldAmount + amount); + }); } return new WarehouseSnapshot(items, hash); diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java index 28cff1c9ead..6cdbfde9745 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java @@ -16,9 +16,10 @@ import com.minecolonies.api.inventory.api.CombinedItemHandler; import com.minecolonies.api.inventory.container.ContainerBuildingInventory; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.ITickable; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.api.util.Log; @@ -46,10 +47,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.Predicate; @@ -225,20 +223,21 @@ public BlockPos getPositionOfChestWithItemStack(@NotNull final Predicate storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; + } + + if (storageInterface.get().hasItemStack(notEmptyPredicate)) + { + return pos; } } } @@ -589,21 +588,21 @@ public LazyOptional getCapability(@NotNull final Capability capability { for (final BlockPos pos : building.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos) && !pos.equals(this.worldPosition)) + if (!WorldUtil.isBlockLoaded(world, pos) || pos.equals(this.worldPosition)) + { + continue; + } + + final BlockEntity te = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(te); + if (storageInterface.isPresent()) + { + handlers.add(storageInterface.get().getInventory()); + storageInterface.get().setBuildingPos(this.getBlockPos()); + } + else { - final BlockEntity te = world.getBlockEntity(pos); - if (te != null) - { - if (te instanceof AbstractTileEntityRack) - { - handlers.add(((AbstractTileEntityRack) te).getInventory()); - ((AbstractTileEntityRack) te).setBuildingPos(this.getBlockPos()); - } - else - { - building.removeContainerPosition(pos); - } - } + building.removeContainerPosition(pos); } } } diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java index c49ade0eb93..0297b8a9928 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java @@ -1,9 +1,10 @@ package com.minecolonies.core.tileentities; import com.minecolonies.api.inventory.InventoryCitizen; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.AbstractTileEntityWareHouse; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.*; import com.minecolonies.core.colony.buildings.modules.BuildingModules; import net.minecraft.world.item.ItemStack; @@ -15,6 +16,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.function.Predicate; import static com.minecolonies.api.util.constant.Constants.TICKS_FIVE_MIN; @@ -46,17 +48,25 @@ public boolean hasMatchingItemStackInWarehouse(@NotNull final Predicate= count) - { - return true; - } - } + continue; + } + + final BlockEntity entity = getLevel().getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + if (storageInterface.get().isEmpty()) { + continue; + } + + totalCount += storageInterface.get().getItemCount(itemStackSelectionPredicate); + if (totalCount >= count) + { + return true; } } } @@ -79,13 +89,21 @@ public boolean hasMatchingItemStackInWarehouse(@NotNull final ItemStack itemStac if (WorldUtil.isBlockLoaded(level, pos)) { final BlockEntity entity = getLevel().getBlockEntity(pos); - if (entity instanceof TileEntityRack && !((AbstractTileEntityRack) entity).isEmpty()) + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { - totalCountFound += ((AbstractTileEntityRack) entity).getCount(itemStack, ignoreDamage, ignoreNBT); - if (totalCountFound >= count) - { - return true; - } + continue; + } + + if (storageInterface.get().isEmpty()) + { + continue; + } + + totalCountFound += storageInterface.get().getCount(itemStack, ignoreDamage, ignoreNBT); + if (totalCountFound >= count) + { + return true; } } } @@ -111,12 +129,25 @@ public List> getMatchingItemStacksInWarehouse(@NotNul if (WorldUtil.isBlockLoaded(level, pos)) { final BlockEntity entity = getLevel().getBlockEntity(pos); - if (entity instanceof final TileEntityRack rack && !rack.isEmpty() && rack.getItemCount(itemStackSelectionPredicate) > 0) + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { - for (final ItemStack stack : (InventoryUtils.filterItemHandler(rack.getInventory(), itemStackSelectionPredicate))) - { - found.add(new Tuple<>(stack, pos)); - } + continue; + } + + if (storageInterface.get().isEmpty()) + { + continue; + } + + if (storageInterface.get().getItemCount(itemStackSelectionPredicate) <= 0) + { + continue; + } + + for (final ItemStack stack : (InventoryUtils.filterItemHandler(storageInterface.get().getInventory(), itemStackSelectionPredicate))) + { + found.add(new Tuple<>(stack, pos)); } } } @@ -135,7 +166,7 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory continue; } - @Nullable final BlockEntity chest = getRackForStack(stack); + @Nullable final BlockEntity chest = getBlockStorageForStack(stack); if (chest == null) { if(level.getGameTime() - lastNotification > TICKS_FIVE_MIN) @@ -166,45 +197,47 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory } /** - * Get a rack for a stack. + * Get a blockstorage for a stack. * @param stack the stack to insert. - * @return the matching rack. + * @return the matching blockstorage. */ - public BlockEntity getRackForStack(final ItemStack stack) + public BlockEntity getBlockStorageForStack(final ItemStack stack) { - BlockEntity rack = getPositionOfChestWithItemStack(stack); - if (rack == null) + BlockEntity storageBlock = getPositionOfStorageBlockWithItemStack(stack); + if (storageBlock == null) { - rack = getPositionOfChestWithSimilarItemStack(stack); - if (rack == null) + storageBlock = getPositionOfStorageBlockWithSimilarItemStack(stack); + if (storageBlock == null) { - rack = searchMostEmptyRack(); + storageBlock = searchMostEmptyStorageBlock(); } } - return rack; + return storageBlock; } /** - * Search the right chest for an itemStack. + * Search the right storageblock for an itemStack. * * @param stack the stack to dump. - * @return the tile entity of the chest + * @return the tile entity of the storageblock */ @Nullable - private BlockEntity getPositionOfChestWithItemStack(@NotNull final ItemStack stack) + private BlockEntity getPositionOfStorageBlockWithItemStack(@NotNull final ItemStack stack) { for (@NotNull final BlockPos pos : getBuilding().getContainers()) { - if (WorldUtil.isBlockLoaded(level, pos)) + if (!WorldUtil.isBlockLoaded(level, pos)) { + continue; + } + final BlockEntity entity = getLevel().getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + if (storageInterface.get().getFreeSlots() > 0 && storageInterface.get().hasItemStack(stack, 1, true)) { - final BlockEntity entity = getLevel().getBlockEntity(pos); - if (entity instanceof AbstractTileEntityRack) - { - if (((AbstractTileEntityRack) entity).getFreeSlots() > 0 && ((AbstractTileEntityRack) entity).hasItemStack(stack, 1, true)) - { - return entity; - } - } + return entity; } } @@ -212,26 +245,32 @@ private BlockEntity getPositionOfChestWithItemStack(@NotNull final ItemStack sta } /** - * Searches a chest with a similar item as the incoming stack. + * Searches a storageblock with a similar item as the incoming stack. * * @param stack the stack. - * @return the entity of the chest. + * @return the entity of the storageblock. */ @Nullable - private BlockEntity getPositionOfChestWithSimilarItemStack(final ItemStack stack) + private BlockEntity getPositionOfStorageBlockWithSimilarItemStack(final ItemStack stack) { for (@NotNull final BlockPos pos : getBuilding().getContainers()) { - if (WorldUtil.isBlockLoaded(level, pos)) - { - final BlockEntity entity = getLevel().getBlockEntity(pos); - if (entity instanceof AbstractTileEntityRack) - { - if (((AbstractTileEntityRack) entity).getFreeSlots() > 0 && ((AbstractTileEntityRack) entity).hasSimilarStack(stack)) - { - return entity; - } - } + if (!WorldUtil.isBlockLoaded(level, pos)) { + continue; + } + + final BlockEntity entity = getLevel().getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } + + if (storageInterface.get().getFreeSlots() <= 0) { + continue; + } + + if (storageInterface.get().hasItemStack(stack, 1, true)) { + return entity; } } return null; @@ -243,26 +282,27 @@ private BlockEntity getPositionOfChestWithSimilarItemStack(final ItemStack stack * @return the tileEntity of this chest. */ @Nullable - private BlockEntity searchMostEmptyRack() + private BlockEntity searchMostEmptyStorageBlock() { int freeSlots = 0; BlockEntity emptiestChest = null; for (@NotNull final BlockPos pos : getBuilding().getContainers()) { final BlockEntity entity = getLevel().getBlockEntity(pos); - if (entity instanceof TileEntityRack) - { - if (((AbstractTileEntityRack) entity).isEmpty()) - { - return entity; - } + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) { + continue; + } - final int tempFreeSlots = ((AbstractTileEntityRack) entity).getFreeSlots(); - if (tempFreeSlots > freeSlots) - { - freeSlots = tempFreeSlots; - emptiestChest = entity; - } + if (storageInterface.get().isEmpty()) { + return entity; + } + + final int tempFreeSlots = storageInterface.get().getFreeSlots(); + if (tempFreeSlots > freeSlots) + { + freeSlots = tempFreeSlots; + emptiestChest = entity; } } return emptiestChest; diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java new file mode 100644 index 00000000000..3552d6526b5 --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java @@ -0,0 +1,151 @@ +package com.minecolonies.core.tileentities.storageblocks; + +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.tileentities.AbstractTileEntityRack; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandlerModifiable; + +import java.util.Map; +import java.util.function.Predicate; + +/** + * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) + */ +public class AbstractRackStorageBlockInterface extends AbstractStorageBlockInterface +{ + public AbstractRackStorageBlockInterface(BlockEntity targetBlockEntity) { + super(targetBlockEntity); + + if (!(targetBlockEntity instanceof AbstractTileEntityRack)) { + throw new RuntimeException("Trying to create an AbstractRackStorageBlockInterface with not instance of AbstractTileEntityRack"); + } + } + + @Override + public boolean shouldAutomaticallyAdd(final IBuilding building) + { + return true; + } + + @Override + public void setInWarehouse(final boolean inWarehouse) + { + getRack().setInWarehouse(inWarehouse); + } + + @Override + public int getUpgradeLevel() + { + return getRack().getUpgradeSize(); + } + + @Override + public void increaseUpgradeLevel() + { + getRack().upgradeRackSize(); + } + + @Override + public int getCount(final ItemStorage storage) + { + return getRack().getCount(storage); + } + + @Override + public int getItemCount(final Predicate predicate) + { + return getRack().getItemCount(predicate); + } + + @Override + public int getFreeSlots() + { + return getRack().getFreeSlots(); + } + + /** + * Gets all items and their count from the storage block. + * + * @return The items and their count + */ + @Override + public Map getAllContent() + { + return null; + } + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + @Override + public int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) + { + return getRack().getCount(stack, ignoreDamageValue, ignoreNBT); + } + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + @Override + public boolean isEmpty() { + return getRack().isEmpty(); + } + + /** + * Get the modifiable ItemHandler for the given storageblock + * + * @return the itemhandler + */ + @Override + public IItemHandlerModifiable getInventory() { + return getRack().getInventory(); + } + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + @Override + public boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage) { + return getRack().hasItemStack(stack, count, ignoreDamage); + } + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + @Override + public boolean hasItemStack(Predicate predicate) { + return getRack().hasItemStack(predicate); + } + + /** + * Sets the block position of the building this storage belongs to + * + * @param pos The position of the building + */ + @Override + public void setBuildingPos(BlockPos pos) { + getRack().setBuildingPos(pos); + } + + private AbstractTileEntityRack getRack() { + return (AbstractTileEntityRack) targetBlockEntity; + } +} diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java new file mode 100644 index 00000000000..3998894f752 --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java @@ -0,0 +1,12 @@ +package com.minecolonies.core.tileentities.storageblocks; + +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import net.minecraft.world.level.block.entity.BlockEntity; + +public abstract class AbstractStorageBlockInterface implements IStorageBlockInterface { + protected final BlockEntity targetBlockEntity; + + public AbstractStorageBlockInterface(BlockEntity targetBlockEntity) { + this.targetBlockEntity = targetBlockEntity; + } +} diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java new file mode 100644 index 00000000000..d3ae0ef73c6 --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java @@ -0,0 +1,153 @@ +package com.minecolonies.core.tileentities.storageblocks; + +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.tileentities.AbstractTileEntityRack; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.core.tileentities.TileEntityRack; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.items.IItemHandlerModifiable; + +import java.util.Map; +import java.util.function.Predicate; + +/** + * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) + */ +public class RackStorageBlockInterface extends AbstractStorageBlockInterface +{ + public RackStorageBlockInterface(BlockEntity targetBlockEntity) { + super(targetBlockEntity); + + if (!(targetBlockEntity instanceof TileEntityRack)) { + throw new IllegalArgumentException("targetBlockEntity must be an instance of TileEntityRack"); + } + } + + @Override + public boolean shouldAutomaticallyAdd(final IBuilding building) + { + return true; + } + + @Override + public void setInWarehouse(final boolean inWarehouse) + { + getRack().setInWarehouse(inWarehouse); + } + + @Override + public int getUpgradeLevel() + { + return getRack().getUpgradeSize(); + } + + @Override + public void increaseUpgradeLevel() + { + getRack().upgradeRackSize(); + } + + @Override + public int getCount(final ItemStorage storage) + { + return getRack().getCount(storage); + } + + @Override + public int getItemCount(final Predicate predicate) + { + return getRack().getItemCount(predicate); + } + + @Override + public int getFreeSlots() + { + return getRack().getFreeSlots(); + } + + /** + * Gets all items and their count from the storage block. + * + * @return The items and their count + */ + @Override + public Map getAllContent() + { + return getRack().getAllContent(); + } + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + @Override + public int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) + { + return getRack().getCount(stack, ignoreDamageValue, ignoreNBT); + } + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + @Override + public boolean isEmpty() { + return getRack().isEmpty(); + } + + /** + * Get the modifiable ItemHandler for the given storageblock + * + * @return the itemhandler + */ + @Override + public IItemHandlerModifiable getInventory() { + return getRack().getInventory(); + } + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + @Override + public boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage) { + return getRack().hasItemStack(stack, count, ignoreDamage); + } + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + @Override + public boolean hasItemStack(Predicate predicate) { + return getRack().hasItemStack(predicate); + } + + /** + * Sets the block position of the building this storage belongs to + * + * @param pos The position of the building + */ + @Override + public void setBuildingPos(BlockPos pos) { + getRack().setBuildingPos(pos); + } + + private TileEntityRack getRack() { + return (TileEntityRack) targetBlockEntity; + } +} diff --git a/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java deleted file mode 100644 index 2587e9ff177..00000000000 --- a/src/main/java/com/minecolonies/core/tileentities/storagecontainers/RackStorageBlockInterface.java +++ /dev/null @@ -1,94 +0,0 @@ -package com.minecolonies.core.tileentities.storagecontainers; - -import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; -import com.minecolonies.core.tileentities.TileEntityRack; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; - -import java.util.Map; -import java.util.function.Predicate; - -/** - * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) - */ -public class RackStorageBlockInterface implements IStorageBlockInterface -{ - @Override - public boolean automaticallyAddToBuilding() - { - return true; - } - - @Override - public void setInWarehouse(BlockEntity blockEntity, final boolean inWarehouse) - { - getAbstractRack(blockEntity).setInWarehouse(inWarehouse); - } - - @Override - public int getUpgradeLevel(BlockEntity blockEntity) - { - return getAbstractRack(blockEntity).getUpgradeSize(); - } - - @Override - public void increaseUpgradeLevel(BlockEntity blockEntity) - { - getAbstractRack(blockEntity).upgradeRackSize(); - } - - @Override - public int getCount(final BlockEntity blockEntity, final ItemStorage storage) - { - return getAbstractRack(blockEntity).getCount(storage); - } - - @Override - public int getItemCount(final BlockEntity blockEntity, final Predicate predicate) - { - return getAbstractRack(blockEntity).getItemCount(predicate); - } - - @Override - public int getFreeSlots(final BlockEntity blockEntity) - { - return getAbstractRack(blockEntity).getFreeSlots(); - } - - /** - * Gets all items and their count from the storage block. - * - * @param blockEntity the block entity to check - * @return The items and their count - */ - @Override - public Map getAllContent(final BlockEntity blockEntity) - { - return getRack(blockEntity).getAllContent(); - } - - /** - * Gets the matching count for a specific item stack and can ignore NBT and damage as well. - * - * @param blockEntity the block entity to check - * @param stack The stack to check against - * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data - * @return The count of matching items in the storageblock - */ - @Override - public int getCount(final BlockEntity blockEntity, final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) - { - return getAbstractRack(blockEntity).getCount(stack, ignoreDamageValue, ignoreNBT); - } - - private AbstractTileEntityRack getAbstractRack(BlockEntity blockEntity) { - return (AbstractTileEntityRack) blockEntity; - } - - private TileEntityRack getRack(BlockEntity blockEntity) { - return (TileEntityRack) blockEntity; - } -} From ed488f8136162668a7e3e09925633c90430280b0 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sat, 21 Sep 2024 23:41:19 -0600 Subject: [PATCH 05/17] Some cleanup --- .../storageblocks/IStorageBlockInterface.java | 12 +- .../storageblocks/ModStorageBlocks.java | 41 +-- .../registry/StorageBlockEntry.java | 33 +-- .../minecolonies/api/util/InventoryUtils.java | 233 ++++++++++-------- 4 files changed, 172 insertions(+), 147 deletions(-) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java index 86846747468..38861641ad6 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java @@ -41,14 +41,14 @@ public interface IStorageBlockInterface /** * Gets the amount of a particular item contained in the storageblock * - * @param storage The item to check for + * @param storage The item to check for */ int getCount(final ItemStorage storage); /** * Gets the amount of a particular item contained in the storageblock * - * @param predicate The predicate used to select items + * @param predicate The predicate used to select items */ int getItemCount(final Predicate predicate); @@ -69,9 +69,9 @@ public interface IStorageBlockInterface /** * Gets the matching count for a specific item stack and can ignore NBT and damage as well. * - * @param stack The stack to check against + * @param stack The stack to check against * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data + * @param ignoreNBT Whether to ignore nbt data * @return The count of matching items in the storageblock */ int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); @@ -93,8 +93,8 @@ public interface IStorageBlockInterface /** * Return whether the storageblock contains a matching item stack * - * @param stack The item type to compare - * @param count The amount that must be present + * @param stack The item type to compare + * @param count The amount that must be present * @param ignoreDamage Whether the items should have matching damage values * @return Whether the storageblock contains the match */ diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index 94fcba1f2c4..7c54f8d5f3c 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -3,7 +3,6 @@ import com.minecolonies.api.MinecoloniesAPIProxy; import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; -import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.tileentities.TileEntityRack; import com.minecolonies.core.tileentities.storageblocks.AbstractRackStorageBlockInterface; @@ -21,7 +20,6 @@ public final class ModStorageBlocks public static final RegistryObject storageBlockRack; public static final RegistryObject storageBlockAbstractRack; - static { storageBlockRack = DEFERRED_REGISTER.register("rack", @@ -32,29 +30,40 @@ public final class ModStorageBlocks .build()); storageBlockAbstractRack = DEFERRED_REGISTER.register("abstract_rack", - () -> new StorageBlockEntry.Builder() - .setIsStorageBlock(blockEntity -> blockEntity instanceof AbstractTileEntityRack && !(blockEntity instanceof TileEntityRack)) - .setRegistryName(new ResourceLocation(Constants.MOD_ID, "abstract_rack")) - .setStorageInterface(AbstractRackStorageBlockInterface::new) - .build()); + () -> new StorageBlockEntry.Builder() + .setIsStorageBlock(blockEntity -> blockEntity instanceof AbstractTileEntityRack && !(blockEntity instanceof TileEntityRack)) + .setRegistryName(new ResourceLocation(Constants.MOD_ID, "abstract_rack")) + .setStorageInterface(AbstractRackStorageBlockInterface::new) + .build()); + } + /** + * Private constructor so this class can't be instantiated. + */ + private ModStorageBlocks() + { } - public static Optional getStorageBlockInterface(BlockEntity blockEntity) { - if (blockEntity == null) { + /** + * Tries to find a matching BlockInterface for the given BlockEntity + * + * @param blockEntity The block entity to find a matching BlockInterface for. + * @return A StorageBlockInterface for the given BlockEntity if one exists. + */ + public static Optional getStorageBlockInterface(BlockEntity blockEntity) + { + if (blockEntity == null) + { return Optional.empty(); } - for (StorageBlockEntry entry : MinecoloniesAPIProxy.getInstance().getStorageBlockRegistry()) { - if (entry.matches(blockEntity)) { + for (StorageBlockEntry entry : MinecoloniesAPIProxy.getInstance().getStorageBlockRegistry()) + { + if (entry.matches(blockEntity)) + { return Optional.of(entry.getStorageInterface().apply(blockEntity)); } } return Optional.empty(); } - - /** - * Private constructor so this class can't be instantiated. - */ - private ModStorageBlocks() {} } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index 91be066ae80..98352acaad1 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -7,8 +7,7 @@ import java.util.function.Function; import java.util.function.Predicate; -public final class StorageBlockEntry -{ +public final class StorageBlockEntry { /** * The registry identifier for this storage block. */ @@ -28,12 +27,11 @@ public final class StorageBlockEntry /** * Constructor * - * @param registryName The registry name of this entry - * @param isStorageBlock The predicate to determine if a block is this storage block type - * @param storageInterface The interface used to interact with the particular block + * @param registryName The registry name of this entry + * @param isStorageBlock The predicate to determine if a block is this storage block type + * @param storageInterface The interface used to interact with the particular block */ - public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, Function storageInterface) - { + public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, Function storageInterface) { this.registryName = registryName; this.isStorageBlock = isStorageBlock; this.storageInterface = storageInterface; @@ -45,8 +43,7 @@ public StorageBlockEntry(ResourceLocation registryName, Predicate i * @param blockEntity The block entity to check * @return Whether the blockentity matches or not. */ - public boolean matches(final BlockEntity blockEntity) - { + public boolean matches(final BlockEntity blockEntity) { return isStorageBlock.test(blockEntity); } @@ -55,8 +52,7 @@ public boolean matches(final BlockEntity blockEntity) * * @return The interface. */ - public Function getStorageInterface() - { + public Function getStorageInterface() { return storageInterface; } @@ -69,8 +65,7 @@ public ResourceLocation getRegistryName() { return registryName; } - public static class Builder - { + public static class Builder { /** * The registry identifier for this storage block. */ @@ -93,8 +88,7 @@ public static class Builder * @param registryName The new registry name * @return this */ - public Builder setRegistryName(ResourceLocation registryName) - { + public Builder setRegistryName(ResourceLocation registryName) { this.registryName = registryName; return this; } @@ -106,8 +100,7 @@ public Builder setRegistryName(ResourceLocation registryName) * @param isStorageBlock The new predicate * @return this */ - public Builder setIsStorageBlock(Predicate isStorageBlock) - { + public Builder setIsStorageBlock(Predicate isStorageBlock) { this.isStorageBlock = isStorageBlock; return this; } @@ -118,8 +111,7 @@ public Builder setIsStorageBlock(Predicate isStorageBlock) * @param storageInterface The interface * @return this */ - public Builder setStorageInterface(Function storageInterface) - { + public Builder setStorageInterface(Function storageInterface) { this.storageInterface = storageInterface; return this; } @@ -129,8 +121,7 @@ public Builder setStorageInterface(Function * * @return the new StorageBlockEntry */ - public StorageBlockEntry build() - { + public StorageBlockEntry build() { return new StorageBlockEntry(registryName, isStorageBlock, storageInterface); } } diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index ef7accc4f88..0aa075d862a 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -740,27 +740,30 @@ public static int getDurabilityInProvider(@NotNull final ICapabilityProvider pro * @param stack the stack to check. * @return Amount of occurrences of stacks that match the given predicate. */ - public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final ItemStorage stack, final int count) + public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) { int totalCount = 0; final Level world = provider.getColony().getWorld(); for (final BlockPos pos : provider.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) + if (!WorldUtil.isBlockLoaded(world, pos)) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } + continue; + } - totalCount += storageInterface.get().getCount(stack); + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; + } - if (totalCount >= count) - { - return Integer.MAX_VALUE; - } + totalCount += storageInterface.get().getItemCount(stack); + + if (totalCount >= count) + { + return totalCount; } } @@ -768,34 +771,32 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, } /** - * Check if a building has more than a count in stack. Return the count it has if it has less. + * Count the number of items a building has. * * @param provider building to check in. * @param stack the stack to check. - * @return Amount of occurrences of stacks that match the given predicate. + * @return Amount of occurrences of stacks that match the given stack. */ - public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) + public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNull final ItemStorage stack) { int totalCount = 0; final Level world = provider.getColony().getWorld(); for (final BlockPos pos : provider.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) + if (!WorldUtil.isBlockLoaded(world, pos)) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } - - totalCount += storageInterface.get().getItemCount(stack); + continue; + } - if (totalCount >= count) - { - return totalCount; - } + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; } + + totalCount += storageInterface.get().getCount(stack); } return totalCount; @@ -820,35 +821,6 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu return totalCount; } - /** - * Count the number of items a building has. - * - * @param provider building to check in. - * @param stack the stack to check. - * @return Amount of occurrences of stacks that match the given stack. - */ - public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNull final ItemStorage stack) - { - int totalCount = 0; - final Level world = provider.getColony().getWorld(); - - for (final BlockPos pos : provider.getContainers()) - { - if (WorldUtil.isBlockLoaded(world, pos)) - { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } - - totalCount += storageInterface.get().getCount(stack); - } - } - - return totalCount; - } - /** * Calculate the number of empty slots in a given building. * @param ownBuilding the building to check. @@ -861,16 +833,19 @@ public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) for (final BlockPos pos : ownBuilding.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) + if (!WorldUtil.isBlockLoaded(world, pos)) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } + continue; + } - totalCount += storageInterface.get().getFreeSlots(); + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; } + + totalCount += storageInterface.get().getFreeSlots(); } return totalCount; @@ -888,17 +863,21 @@ public static boolean isBuildingFull(final IBuilding ownBuilding) for (final BlockPos pos : ownBuilding.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) + if (!WorldUtil.isBlockLoaded(world, pos)) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } + continue; + } - if (storageInterface.get().getFreeSlots() > 0) { - return false; - } + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; + } + + if (storageInterface.get().getFreeSlots() > 0) + { + return false; } } @@ -919,16 +898,19 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu for (final BlockPos pos : provider.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) + if (!WorldUtil.isBlockLoaded(world, pos)) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } + continue; + } - totalCount += storageInterface.get().getItemCount(predicate); + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; } + + totalCount += storageInterface.get().getItemCount(predicate); } return totalCount; @@ -950,20 +932,23 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide for (final BlockPos pos : provider.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) + if (!WorldUtil.isBlockLoaded(world, pos)) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - continue; - } + continue; + } + + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; + } - for (final Map.Entry entry : storageInterface.get().getAllContent().entrySet()) + for (final Map.Entry entry : storageInterface.get().getAllContent().entrySet()) + { + if (predicate.test(entry.getKey().getItemStack())) { - if (predicate.test(entry.getKey().getItemStack())) - { - allMatching.put(entry.getKey(), allMatching.getOrDefault(entry.getKey(), 0) + entry.getValue()); - } + allMatching.put(entry.getKey(), allMatching.getOrDefault(entry.getKey(), 0) + entry.getValue()); } } } @@ -977,6 +962,30 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide return totalCount; } + /** + * Check if there is enough of a given stack in the provider. + * + * @param entity the provider. + * @param stack the stack to count. + * @param count the count. + * @return true if enough. + */ + public static boolean hasEnoughInProvider(final BlockEntity entity, final ItemStack stack, final int count) + { + if (entity instanceof TileEntityColonyBuilding) + { + return InventoryUtils.hasBuildingEnoughElseCount( ((TileEntityColonyBuilding) entity).getBuilding(), new ItemStorage(stack), stack.getCount()) >= count; + } + + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; + } + + return storageInterface.get().getCount(stack, false, false) >= count; + } + /** * Checks if a player has a block in the {@link ICapabilityProvider}. Checked by {@link #getItemCountInProvider(ICapabilityProvider, Block)} > 0; * @@ -3204,25 +3213,40 @@ private static void updateHeldItemFromServer(final Player player) } /** - * Check if there is enough of a given stack in the provider. - * @param entity the provider. - * @param stack the stack to count. - * @param count the count. - * @return true if enough. + * Check if a building has more than a count in stack. Return the count it has if it has less. + * + * @param provider building to check in. + * @param stack the stack to check. + * @return Amount of occurrences of stacks that match the given predicate. */ - public static boolean hasEnoughInProvider(final BlockEntity entity, final ItemStack stack, final int count) + public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final ItemStorage stack, final int count) { - if (entity instanceof TileEntityColonyBuilding) + int totalCount = 0; + final Level world = provider.getColony().getWorld(); + + for (final BlockPos pos : provider.getContainers()) { - return InventoryUtils.hasBuildingEnoughElseCount( ((TileEntityColonyBuilding) entity).getBuilding(), new ItemStorage(stack), stack.getCount()) >= count; - } + if (!WorldUtil.isBlockLoaded(world, pos)) + { + continue; + } - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { - return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; + final BlockEntity entity = world.getBlockEntity(pos); + Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); + if (storageInterface.isEmpty()) + { + continue; + } + + totalCount += storageInterface.get().getCount(stack); + + if (totalCount >= count) + { + return Integer.MAX_VALUE; + } } - return storageInterface.get().getCount(stack, false, false) >= count; + return totalCount; } public static List getBuildingInventory(final IBuilding building) @@ -3235,7 +3259,8 @@ public static List getBuildingInventory(final IBuilding building) { final BlockEntity entity = world.getBlockEntity(pos); Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (storageInterface.isEmpty()) + { continue; } From 04e44ef2de03afed27bb32b4f13eb3efc9a266f7 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sat, 21 Sep 2024 23:47:50 -0600 Subject: [PATCH 06/17] Removed debug logging --- src/main/java/com/minecolonies/api/util/InventoryUtils.java | 2 +- .../colony/buildings/workerbuildings/BuildingWareHouse.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 0aa075d862a..70583dd1340 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -964,7 +964,7 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide /** * Check if there is enough of a given stack in the provider. - * + * * @param entity the provider. * @param stack the stack to count. * @param count the count. diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 50521879ef1..4b336dfae61 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -11,7 +11,6 @@ import com.minecolonies.api.tileentities.*; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; -import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.core.client.gui.WindowHutMinPlaceholder; import com.minecolonies.core.colony.buildings.AbstractBuilding; @@ -128,8 +127,6 @@ public void registerBlockPosition(@NotNull final Block block, @NotNull final Blo return; } - Log.getLogger().atInfo().log("Adding new block to building: {}", block.getClass()); - blockInterface.get().setInWarehouse(true); int targetLevel = getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade(); while (blockInterface.get().getUpgradeLevel() < targetLevel) { From be50d35f7d602c70f53f65a89a9539cfafb442ca Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 22:18:03 -0600 Subject: [PATCH 07/17] Update the storage blocks to be the containers that buildings keep now --- .../colony/buildings/IBuildingContainer.java | 3 +- .../colony/buildings/views/IBuildingView.java | 5 +- .../AbstractStorageBlockInterface.java | 240 ++++++++++++++++++ .../storageblocks/IStorageBlockInterface.java | 117 --------- .../storageblocks/ModStorageBlocks.java | 34 ++- .../registry/StorageBlockEntry.java | 17 +- .../minecolonies/api/util/InventoryUtils.java | 187 +++++--------- .../client/gui/WindowHutAllInventory.java | 32 ++- .../core/client/gui/WindowsBarracksSpies.java | 11 +- .../colony/buildings/AbstractBuilding.java | 21 +- .../buildings/AbstractBuildingContainer.java | 38 ++- .../buildings/views/AbstractBuildingView.java | 12 +- .../workerbuildings/BuildingWareHouse.java | 32 +-- .../ai/workers/AbstractEntityAIBasic.java | 41 ++- .../service/EntityAIWorkDeliveryman.java | 14 +- .../core/items/ItemResourceScroll.java | 12 +- .../TileEntityColonyBuilding.java | 59 +---- .../tileentities/TileEntityWareHouse.java | 171 ++++++------- .../AbstractRackStorageBlockInterface.java | 151 ----------- .../AbstractStorageBlockInterface.java | 12 - .../ColonyBuildingStorageBlockInterface.java | 50 ++++ .../RackStorageBlockInterface.java | 166 +++++++++--- 22 files changed, 710 insertions(+), 715 deletions(-) create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java delete mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java delete mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java delete mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java create mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java diff --git a/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java b/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java index 11a8ff9d89c..4eba3cb653d 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java @@ -1,6 +1,7 @@ package com.minecolonies.api.colony.buildings; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -56,7 +57,7 @@ public interface IBuildingContainer extends ISchematicProvider, ICapabilityProvi * * @return a copy of the list to avoid currentModification exception. */ - List getContainers(); + List getContainers(); /** * Register a blockState and position. We suppress this warning since this parameter will be used in child classes which override this method. diff --git a/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java b/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java index 863343120a7..cff3b39fadd 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java @@ -9,6 +9,7 @@ import com.minecolonies.api.colony.requestsystem.request.IRequest; import com.minecolonies.api.colony.requestsystem.requester.IRequester; import com.minecolonies.api.colony.requestsystem.token.IToken; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import org.jetbrains.annotations.NotNull; @@ -55,11 +56,11 @@ public interface IBuildingView extends IRequester, IModuleContainerView int getBuildingLevel(); /** - * Get the BlockPos of the Containers. + * Get the storage interfaces of the Containers. * * @return containerList. */ - List getContainerList(); + List getContainerList(); /** * Get the max level of the building. diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java new file mode 100644 index 00000000000..c8800383055 --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java @@ -0,0 +1,240 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.util.WorldUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.items.IItemHandler; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +/** + * The abstract StorageBlockInterface class that all implementations should + * inherit from. + */ +public abstract class AbstractStorageBlockInterface +{ + /** + * The position of the block entity in the world. + */ + protected final BlockPos targetPos; + + /** + * The level that the block entity is located in. + */ + protected final Level level; + + /** + * Constructor + * + * @param targetPos The location of the block + * @param level The world the block is in + */ + public AbstractStorageBlockInterface(final BlockPos targetPos, Level level) + { + this.targetPos = targetPos; + this.level = level; + } + + /** + * Check whether the position is still valid for this storage interface + * + * @return Whether the position is still valid + */ + public abstract boolean isStillValid(); + + /** + * Whether the storageblock should be included in building containers automatically. + * + * @param building The building that is being constructed. + * @return Whether the storageblock should be included in building containers automatically. + */ + public abstract boolean shouldAutomaticallyAdd(final IBuilding building); + + /** + * Sets whether the block is part of a warehouse. + * + * @param inWarehouse Whether it's in a warehouse + */ + public abstract void setInWarehouse(final boolean inWarehouse); + + /** + * Gets the current upgrade level of the storageblock + * + * @return The current level + */ + public abstract int getUpgradeLevel(); + + /** + * Upgrades the size of the storage, if applicable. + */ + public abstract void increaseUpgradeLevel(); + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param storage The item to check for + */ + public abstract int getCount(final ItemStorage storage); + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param predicate The predicate used to select items + */ + public abstract int getItemCount(final Predicate predicate); + + /** + * Return the number of free slots in the container. + * + * @return The free slots + */ + public abstract int getFreeSlots(); + + /** + * Gets all items and their count from the storage block. + * + * @return The items and their count + */ + public abstract Map getAllContent(); + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + public abstract int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + public abstract boolean isEmpty(); + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + public abstract boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + public abstract boolean hasItemStack(final Predicate predicate); + + /** + * Sets the block position of the building this storage belongs to + * + * @param pos The position of the building + */ + public abstract void setBuildingPos(final BlockPos pos); + + /** + * The position of the target storage block. + * + * @return The position. + */ + public BlockPos getPosition() + { + return targetPos; + } + + /** + * Whether the block is currently loaded. + * + * @return Whether it's loaded. + */ + public boolean isLoaded() + { + return WorldUtil.isBlockLoaded(level, targetPos); + } + + /** + * Add an item stack to this storage block. + * + * @param stack The stack to add + * @return Whether the addition was successful + */ + public abstract boolean storeItemStack(@NotNull final ItemStack stack); + + /** + * Get any matching item stacks within the storage block. + * + * @param predicate The predicate to test against + * @return The list of matching item stacks + */ + public abstract List getMatching(@NotNull final Predicate predicate); + + /** + * Attempt to add an itemstack to the storage and return the remaining stack + * + * @param itemStack The stack to attempt to add + * @return The remaining stack after adding whatever can be added + */ + public abstract ItemStack addItemStackWithResult(@Nullable ItemStack itemStack); + + /** + * Force stack to the storage block. + * + * @param itemStack ItemStack to add. + * @param itemStackToKeepPredicate The {@link Predicate} that determines which ItemStacks to keep in the inventory. Return false to replace. + * @return itemStack which has been replaced, null if none has been replaced. + */ + @Nullable + public abstract ItemStack forceAddItemStack( + @NotNull final ItemStack itemStack, + @NotNull final Predicate itemStackToKeepPredicate); + + /** + * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. + * + * @param sourceHandler The {@link IItemHandler} that works as Source. + * @param predicate the predicate for the stack. + * @return true when the swap was successful, false when not. + */ + public abstract boolean transferItemStackToStorageIntoNextBestSlot( + @NotNull final IItemHandler sourceHandler, + final Predicate predicate); + + /** + * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. + * + * @param targetHandler The {@link IItemHandler} that works as receiver. + * @param predicate the predicate for the stack. + * @return true when the swap was successful, false when not. + */ + public abstract boolean transferItemStackFromStorageIntoNextBestSlot( + @NotNull final IItemHandler targetHandler, + final Predicate predicate); + + /** + * Method to swap the ItemStacks from storage to the given target {@link IItemHandler}. + * + * @param targetHandler The {@link IItemHandler} that works as Target. + * @param stackPredicate The type of stack to pickup. + * @param count how much to pick up. + * @return True when the swap was successful, false when not. + */ + public abstract boolean transferItemStackFromStorageIntoNextFreeSlot( + @NotNull final IItemHandler targetHandler, + @NotNull final Predicate stackPredicate, + final int count); +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java deleted file mode 100644 index 38861641ad6..00000000000 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockInterface.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.minecolonies.api.tileentities.storageblocks; - -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.crafting.ItemStorage; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.IItemHandlerModifiable; - -import java.util.Map; -import java.util.function.Predicate; - -public interface IStorageBlockInterface -{ - /** - * Whether the storageblock should be included in building containers automatically. - * - * @param building The building that is being constructed. - * @return Whether the storageblock should be included in building containers automatically. - */ - boolean shouldAutomaticallyAdd(final IBuilding building); - - /** - * Sets whether the block is part of a warehouse. - * - * @param inWarehouse Whether it's in a warehouse - */ - void setInWarehouse(final boolean inWarehouse); - - /** - * Gets the current upgrade level of the storageblock - * - * @return The current level - */ - int getUpgradeLevel(); - - /** - * Upgrades the size of the storage, if applicable. - */ - void increaseUpgradeLevel(); - - /** - * Gets the amount of a particular item contained in the storageblock - * - * @param storage The item to check for - */ - int getCount(final ItemStorage storage); - - /** - * Gets the amount of a particular item contained in the storageblock - * - * @param predicate The predicate used to select items - */ - int getItemCount(final Predicate predicate); - - /** - * Return the number of free slots in the container. - * - * @return The free slots - */ - int getFreeSlots(); - - /** - * Gets all items and their count from the storage block. - * - * @return The items and their count - */ - Map getAllContent(); - - /** - * Gets the matching count for a specific item stack and can ignore NBT and damage as well. - * - * @param stack The stack to check against - * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data - * @return The count of matching items in the storageblock - */ - int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); - - /** - * Whether there are any items in the target storageblock - * - * @return Whether the storageblock is empty - */ - boolean isEmpty(); - - /** - * Get the modifiable ItemHandler for the given storageblock - * - * @return the itemhandler - */ - IItemHandlerModifiable getInventory(); - - /** - * Return whether the storageblock contains a matching item stack - * - * @param stack The item type to compare - * @param count The amount that must be present - * @param ignoreDamage Whether the items should have matching damage values - * @return Whether the storageblock contains the match - */ - boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); - - /** - * Return whether the storageblock contains any items matching the predicate - * - * @param predicate The predicate to check against - * @return Whether the storageblock has any matches - */ - boolean hasItemStack(final Predicate predicate); - - /** - * Sets the block position of the building this storage belongs to - * - * @param pos The position of the building - */ - void setBuildingPos(final BlockPos pos); -} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index 7c54f8d5f3c..4a1f133f951 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -1,39 +1,42 @@ package com.minecolonies.api.tileentities.storageblocks; import com.minecolonies.api.MinecoloniesAPIProxy; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import com.minecolonies.api.util.constant.Constants; +import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.TileEntityRack; -import com.minecolonies.core.tileentities.storageblocks.AbstractRackStorageBlockInterface; +import com.minecolonies.core.tileentities.storageblocks.ColonyBuildingStorageBlockInterface; import com.minecolonies.core.tileentities.storageblocks.RackStorageBlockInterface; +import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.registries.DeferredRegister; import net.minecraftforge.registries.RegistryObject; -import java.util.Optional; +import javax.annotation.Nullable; public final class ModStorageBlocks { public static final DeferredRegister DEFERRED_REGISTER = DeferredRegister.create(new ResourceLocation(Constants.MOD_ID, "storageblocks"), Constants.MOD_ID); public static final RegistryObject storageBlockRack; - public static final RegistryObject storageBlockAbstractRack; + public static final RegistryObject storageBlockColonyBuilding; + static { storageBlockRack = DEFERRED_REGISTER.register("rack", () -> new StorageBlockEntry.Builder() - .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityRack) + .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityRack && !(blockEntity instanceof TileEntityColonyBuilding)) .setRegistryName(new ResourceLocation(Constants.MOD_ID, "rack")) .setStorageInterface(RackStorageBlockInterface::new) .build()); - storageBlockAbstractRack = DEFERRED_REGISTER.register("abstract_rack", + storageBlockColonyBuilding = DEFERRED_REGISTER.register("colony_building", () -> new StorageBlockEntry.Builder() - .setIsStorageBlock(blockEntity -> blockEntity instanceof AbstractTileEntityRack && !(blockEntity instanceof TileEntityRack)) - .setRegistryName(new ResourceLocation(Constants.MOD_ID, "abstract_rack")) - .setStorageInterface(AbstractRackStorageBlockInterface::new) + .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityColonyBuilding) + .setRegistryName(new ResourceLocation(Constants.MOD_ID, "colony_building")) + .setStorageInterface(ColonyBuildingStorageBlockInterface::new) .build()); } /** @@ -46,24 +49,27 @@ private ModStorageBlocks() /** * Tries to find a matching BlockInterface for the given BlockEntity * - * @param blockEntity The block entity to find a matching BlockInterface for. + * @param pos The location of the block in the level + * @param world The level the block is located in * @return A StorageBlockInterface for the given BlockEntity if one exists. */ - public static Optional getStorageBlockInterface(BlockEntity blockEntity) + @Nullable + public static AbstractStorageBlockInterface getStorageBlockInterface(BlockPos pos, Level world) { + BlockEntity blockEntity = world.getBlockEntity(pos); if (blockEntity == null) { - return Optional.empty(); + return null; } for (StorageBlockEntry entry : MinecoloniesAPIProxy.getInstance().getStorageBlockRegistry()) { if (entry.matches(blockEntity)) { - return Optional.of(entry.getStorageInterface().apply(blockEntity)); + return entry.getStorageInterface().apply(pos, world); } } - return Optional.empty(); + return null; } } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index 98352acaad1..f64badda5d0 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -1,12 +1,17 @@ package com.minecolonies.api.tileentities.storageblocks.registry; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; + + public final class StorageBlockEntry { /** * The registry identifier for this storage block. @@ -22,7 +27,7 @@ public final class StorageBlockEntry { /** * The interface that will be used to interact with the particular block. */ - private final Function storageInterface; + private final BiFunction storageInterface; /** * Constructor @@ -31,7 +36,7 @@ public final class StorageBlockEntry { * @param isStorageBlock The predicate to determine if a block is this storage block type * @param storageInterface The interface used to interact with the particular block */ - public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, Function storageInterface) { + public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, BiFunction storageInterface) { this.registryName = registryName; this.isStorageBlock = isStorageBlock; this.storageInterface = storageInterface; @@ -52,7 +57,7 @@ public boolean matches(final BlockEntity blockEntity) { * * @return The interface. */ - public Function getStorageInterface() { + public BiFunction getStorageInterface() { return storageInterface; } @@ -80,7 +85,7 @@ public static class Builder { /** * The interface that will be used to interact with the particular block. */ - private Function storageInterface; + private BiFunction storageInterface; /** * Set the registry name for the StorageBlockEntry being built. @@ -111,7 +116,7 @@ public Builder setIsStorageBlock(Predicate isStorageBlock) { * @param storageInterface The interface * @return this */ - public Builder setStorageInterface(Function storageInterface) { + public Builder setStorageInterface(BiFunction storageInterface) { this.storageInterface = storageInterface; return this; } diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 70583dd1340..5c4bf3b13af 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -6,7 +6,7 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import net.minecraft.core.BlockPos; @@ -743,23 +743,13 @@ public static int getDurabilityInProvider(@NotNull final ICapabilityProvider pro public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) { int totalCount = 0; - final Level world = provider.getColony().getWorld(); - - for (final BlockPos pos : provider.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) - { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } - - totalCount += storageInterface.get().getItemCount(stack); + totalCount += storageInterface.getItemCount(stack); if (totalCount >= count) { @@ -780,23 +770,14 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNull final ItemStorage stack) { int totalCount = 0; - final Level world = provider.getColony().getWorld(); - - for (final BlockPos pos : provider.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) - { - continue; - } - - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - totalCount += storageInterface.get().getCount(stack); + totalCount += storageInterface.getCount(stack); } return totalCount; @@ -829,23 +810,15 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) { int totalCount = 0; - final Level world = ownBuilding.getColony().getWorld(); - for (final BlockPos pos : ownBuilding.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : ownBuilding.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) - { - continue; - } - - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - totalCount += storageInterface.get().getFreeSlots(); + totalCount += storageInterface.getFreeSlots(); } return totalCount; @@ -859,23 +832,14 @@ public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) */ public static boolean isBuildingFull(final IBuilding ownBuilding) { - final Level world = ownBuilding.getColony().getWorld(); - - for (final BlockPos pos : ownBuilding.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : ownBuilding.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) - { - continue; - } - - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - if (storageInterface.get().getFreeSlots() > 0) + if (storageInterface.getFreeSlots() > 0) { return false; } @@ -896,21 +860,14 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu int totalCount = 0; final Level world = provider.getColony().getWorld(); - for (final BlockPos pos : provider.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } - - totalCount += storageInterface.get().getItemCount(predicate); + totalCount += storageInterface.getItemCount(predicate); } return totalCount; @@ -930,21 +887,14 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide final Map allMatching = new HashMap<>(); - for (final BlockPos pos : provider.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } - - for (final Map.Entry entry : storageInterface.get().getAllContent().entrySet()) + for (final Map.Entry entry : storageInterface.getAllContent().entrySet()) { if (predicate.test(entry.getKey().getItemStack())) { @@ -962,42 +912,6 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide return totalCount; } - /** - * Check if there is enough of a given stack in the provider. - * - * @param entity the provider. - * @param stack the stack to count. - * @param count the count. - * @return true if enough. - */ - public static boolean hasEnoughInProvider(final BlockEntity entity, final ItemStack stack, final int count) - { - if (entity instanceof TileEntityColonyBuilding) - { - return InventoryUtils.hasBuildingEnoughElseCount( ((TileEntityColonyBuilding) entity).getBuilding(), new ItemStorage(stack), stack.getCount()) >= count; - } - - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; - } - - return storageInterface.get().getCount(stack, false, false) >= count; - } - - /** - * Checks if a player has a block in the {@link ICapabilityProvider}. Checked by {@link #getItemCountInProvider(ICapabilityProvider, Block)} > 0; - * - * @param Provider {@link ICapabilityProvider} to scan - * @param block Block to count - * @return True when in {@link ICapabilityProvider}, otherwise false - */ - public static boolean hasItemInProvider(@NotNull final ICapabilityProvider Provider, @NotNull final Block block) - { - return hasItemInProvider(Provider, getItemFromBlock(block)); - } - /** * Checks if a player has an item in the {@link ICapabilityProvider}. Checked by {@link #getItemCountInProvider(ICapabilityProvider, Item)} > 0; * @@ -1858,6 +1772,35 @@ public static boolean transferItemStackIntoNextBestSlotInItemHandler(final ItemS return transferItemStackIntoNextBestSlotInItemHandlerWithResult(stack, targetHandler).isEmpty(); } + /** + * Method to swap the ItemStacks from the given source {@link AbstractStorageBlockInterface} to the given target {@link IItemHandler}. Trying to merge existing itemStacks if possible. + * + * @param sourceHandler The {@link IItemHandler} that works as Source. + * @param sourceIndex The index of the slot that is being extracted from. + * @param targetInterface The {@link AbstractStorageBlockInterface} that works as Target. + * @return True when the swap was successful, false when not. + */ + public static boolean transferIntoNextBestSlotInStorageBlock( + @NotNull final IItemHandler sourceHandler, + final int sourceIndex, + @NotNull final AbstractStorageBlockInterface targetInterface) + { + ItemStack sourceStack = sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, true); + + if (ItemStackUtils.isEmpty(sourceStack)) + { + return true; + } + + if (targetInterface.storeItemStack(sourceStack)) + { + sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, false); + return true; + } + return false; + } + + /** * Method to put a given Itemstack in a given target {@link IItemHandler}. Trying to merge existing itemStacks if possible. * @@ -3224,21 +3167,14 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, int totalCount = 0; final Level world = provider.getColony().getWorld(); - for (final BlockPos pos : provider.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!WorldUtil.isBlockLoaded(world, pos)) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } - - totalCount += storageInterface.get().getCount(stack); + totalCount += storageInterface.getCount(stack); if (totalCount >= count) { @@ -3251,23 +3187,16 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, public static List getBuildingInventory(final IBuilding building) { - final Level world = building.getColony().getWorld(); final List allInInv = new ArrayList<>(); - for (final BlockPos pos : building.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : building.getContainers()) { - if (WorldUtil.isBlockLoaded(world, pos)) - { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { + continue; + } - for (final ItemStorage storage : storageInterface.get().getAllContent().keySet()) - { - allInInv.add(storage.getItemStack()); - } + for (final ItemStorage storage : storageInterface.getAllContent().keySet()) + { + allInInv.add(storage.getItemStack()); } } return allInInv; diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java index 91222eadb22..c80e6ea4492 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java @@ -6,7 +6,7 @@ import com.ldtteam.blockui.views.ScrollingList; import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.MessageUtils; import com.minecolonies.api.util.Utils; @@ -117,22 +117,21 @@ private void locate(final Button button) { final int row = stackList.getListElementIndexByPane(button); final ItemStorage storage = allItems.get(row); - final Set containerList = new HashSet<>(building.getContainerList()); - containerList.add(building.getID()); + final Set containerList = new HashSet<>(building.getContainerList()); + containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getID(), building.getColony().getWorld())); HighlightManager.clearHighlightsForKey("inventoryHighlight"); MessageUtils.format(MESSAGE_LOCATING_ITEMS).sendTo(Minecraft.getInstance().player); close(); - for (BlockPos blockPos : containerList) + for (final AbstractStorageBlockInterface storageInterface : containerList) { - final BlockEntity entity = Minecraft.getInstance().level.getBlockEntity(blockPos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isStillValid()) + { continue; } - int count = storageInterface.get().getCount(storage.getItemStack(), storage.ignoreDamageValue(), false); + int count = storageInterface.getCount(storage.getItemStack(), storage.ignoreDamageValue(), false); if (count <= 0) { continue; @@ -142,8 +141,8 @@ private void locate(final Button button) // mixing equation: alpha | red part | green part final int color = 0x80000000 | (Mth.clamp((int) (0xff * (2.0f - count / 32.0f)), 0, 255) << 16) | (Mth.clamp((int) (0xff * count / 32.0f), 0, 255) << 8); - HighlightManager.addHighlight("inventoryHighlight" + blockPos, - new TimedBoxRenderData(blockPos) + HighlightManager.addHighlight("inventoryHighlight" + storageInterface.getPosition(), + new TimedBoxRenderData(storageInterface.getPosition()) .setDuration(Duration.ofSeconds(60)) .addText("" + count) .setColor(color)); @@ -199,21 +198,20 @@ private void setSortFlag() */ private void updateResources() { - final Set containerList = new HashSet<>(building.getContainerList()); + final Set containerList = new HashSet<>(building.getContainerList()); final Map storedItems = new HashMap<>(); final Level world = building.getColony().getWorld(); - containerList.add(building.getPosition()); + containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getPosition(), world)); - for (final BlockPos blockPos : containerList) + for (final AbstractStorageBlockInterface storageInterface : containerList) { - final BlockEntity entity = world.getBlockEntity(blockPos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isStillValid()) + { continue; } - final Map storage = storageInterface.get().getAllContent(); + final Map storage = storageInterface.getAllContent(); for (final Map.Entry entry : storage.entrySet()) { diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java index 111b40fff6c..6e38bb9b891 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java @@ -3,7 +3,7 @@ import com.ldtteam.blockui.controls.*; import com.ldtteam.blockui.views.BOWindow; import com.minecolonies.api.colony.buildings.views.IBuildingView; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.InventoryUtils; import com.minecolonies.api.util.constant.Constants; @@ -71,10 +71,15 @@ public WindowsBarracksSpies(final IBuildingView buildingView, final BlockPos bui findPaneOfTypeByID(SPIES_BUTTON_ICON, ItemIcon.class).setItem(Items.GOLD_INGOT.getDefaultInstance()); findPaneOfTypeByID(GOLD_COST_LABEL, Text.class).setText(Component.literal("x5")); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingView.getColony().getWorld().getBlockEntity(buildingPos)); final IItemHandler playerInv = new InvWrapper(Minecraft.getInstance().player.getInventory()); int goldCount = InventoryUtils.getItemCountInItemHandler(playerInv, Items.GOLD_INGOT); - goldCount += storageInterface.map(iStorageBlockInterface -> iStorageBlockInterface.getItemCount(stack -> stack.is(Items.GOLD_INGOT))).orElse(0); + + + AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingPos, buildingView.getColony().getWorld()); + if (storageInterface != null) + { + goldCount += storageInterface.getItemCount(stack -> stack.is(Items.GOLD_INGOT)); + } if (!buildingView.getColony().isRaiding() || goldCount < GOLD_COST || buildingView.getColony().areSpiesEnabled()) { diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java index 91428fe992b..9da634ba988 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java @@ -37,6 +37,7 @@ import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.api.util.constant.TypeConstants; @@ -710,9 +711,9 @@ public void serializeToView(@NotNull final FriendlyByteBuf buf, final boolean fu } buf.writeNbt(StandardFactoryController.getInstance().serialize(getId())); buf.writeInt(containerList.size()); - for (BlockPos blockPos : containerList) + for (final AbstractStorageBlockInterface storageInterface : containerList) { - buf.writeBlockPos(blockPos); + buf.writeBlockPos(storageInterface.getPosition()); } buf.writeNbt(requestSystemCompound); @@ -1237,12 +1238,10 @@ public ItemStack forceTransferStack(final ItemStack stack, final Level world) { if (getTileEntity() == null) { - for (final BlockPos pos : containerList) + for (final AbstractStorageBlockInterface storageInterface : containerList) { - final BlockEntity tempTileEntity = world.getBlockEntity(pos); - if (tempTileEntity instanceof ChestBlockEntity && !InventoryUtils.isProviderFull(tempTileEntity)) - { - return forceItemStackToProvider(tempTileEntity, stack); + if (storageInterface.getFreeSlots() != 0) { + return forceItemStackToStorageBlock(storageInterface, stack); } } } @@ -1262,6 +1261,14 @@ private ItemStack forceItemStackToProvider(@NotNull final ICapabilityProvider pr (ItemStack stack) -> EntityAIWorkDeliveryman.workerRequiresItem(this, stack, localAlreadyKept) != stack.getCount()); } + @Nullable + private ItemStack forceItemStackToStorageBlock(@NotNull final AbstractStorageBlockInterface storageInterface, @NotNull final ItemStack itemStack) + { + final List localAlreadyKept = new ArrayList<>(); + return storageInterface.forceAddItemStack(itemStack, + (ItemStack stack) -> EntityAIWorkDeliveryman.workerRequiresItem(this, stack, localAlreadyKept) != stack.getCount()); + } + //------------------------- Ending Required Tools/Item handling -------------------------// //------------------------- !START! RequestSystem handling for minecolonies buildings -------------------------// diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java index 3235ba5af1d..74a6eb5ca6a 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java @@ -6,7 +6,7 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.buildings.IBuildingContainer; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import net.minecraft.core.BlockPos; @@ -43,7 +43,7 @@ public abstract class AbstractBuildingContainer extends AbstractSchematicProvide /** * A list which contains the position of all containers which belong to the worker building. */ - protected final Set containerList = new HashSet<>(); + protected final Set containerList = new HashSet<>(); /** * List of items the worker should keep. With the quantity and if he should keep it in the inventory as well. @@ -80,7 +80,7 @@ public void deserializeNBT(final CompoundTag compound) for (int i = 0; i < containerTagList.size(); ++i) { final CompoundTag containerCompound = containerTagList.getCompound(i); - containerList.add(NbtUtils.readBlockPos(containerCompound)); + addContainerPosition(NbtUtils.readBlockPos(containerCompound)); } if (compound.contains(TAG_PRIO)) { @@ -102,9 +102,9 @@ public CompoundTag serializeNBT() final CompoundTag compound = super.serializeNBT(); @NotNull final ListTag containerTagList = new ListTag(); - for (@NotNull final BlockPos pos : containerList) + for (@NotNull final AbstractStorageBlockInterface storageInterface : containerList) { - containerTagList.add(NbtUtils.writeBlockPos(pos)); + containerTagList.add(NbtUtils.writeBlockPos(storageInterface.getPosition())); } compound.put(TAG_CONTAINERS, containerTagList); compound.putInt(TAG_PRIO, this.unscaledPickUpPriority); @@ -127,20 +127,31 @@ public void alterPickUpPriority(final int value) @Override public void addContainerPosition(@NotNull final BlockPos pos) { - containerList.add(pos); + AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); + if (storageInterface != null) + { + containerList.add(ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld())); + } } @Override public void removeContainerPosition(final BlockPos pos) { - containerList.remove(pos); + List toRemove = new ArrayList<>(); + for (final AbstractStorageBlockInterface storageInterface : containerList) { + if (storageInterface.getPosition().equals(pos)) { + toRemove.add(storageInterface); + } + } + + toRemove.forEach(containerList::remove); } @Override - public List getContainers() + public List getContainers() { - final List list = new ArrayList<>(containerList);; - list.add(this.getPosition()); + final List list = new ArrayList<>(containerList);; + list.add(ModStorageBlocks.getStorageBlockInterface(getPosition(), getColony().getWorld())); return list; } @@ -171,13 +182,12 @@ public void registerBlockPosition(@NotNull final Block block, @NotNull final Blo } else { - BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); + if (storageInterface == null) { return; } addContainerPosition(pos); - storageInterface.get().setBuildingPos(this.getID()); + storageInterface.setBuildingPos(this.getID()); } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java b/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java index 52e719e378a..6fa40c1e479 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java @@ -15,6 +15,8 @@ import com.minecolonies.api.colony.requestsystem.manager.IRequestManager; import com.minecolonies.api.colony.requestsystem.request.IRequest; import com.minecolonies.api.colony.requestsystem.token.IToken; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.core.Network; @@ -134,7 +136,7 @@ public abstract class AbstractBuildingView implements IBuildingView * The BlockPos list of all Containers */ - private List containerlist = new ArrayList<>(); + private List containerlist = new ArrayList<>(); /** * If building is deconstructed. @@ -343,7 +345,7 @@ public int getClaimRadius() * Returns the Container List */ @Override - public List getContainerList() + public List getContainerList() { return new ArrayList<>(containerlist); } @@ -428,7 +430,11 @@ public void deserialize(@NotNull final FriendlyByteBuf buf) final int racks = buf.readInt(); for (int i = 0; i < racks; i++) { - containerlist.add(buf.readBlockPos()); + AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(buf.readBlockPos(), getColony().getWorld()); + if (storageInterface != null) + { + containerlist.add(storageInterface); + } } loadRequestSystemFromNBT(buf.readNbt()); isDeconstructed = buf.readBoolean(); diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 4b336dfae61..953d45bed5a 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -9,7 +9,7 @@ import com.minecolonies.api.colony.buildings.workerbuildings.IWareHouse; import com.minecolonies.api.colony.requestsystem.resolver.IRequestResolver; import com.minecolonies.api.tileentities.*; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.core.client.gui.WindowHutMinPlaceholder; @@ -66,15 +66,9 @@ public BuildingWareHouse(final IColony c, final BlockPos l) public void requestRepair(final BlockPos builder) { //To ensure that the storageblocks are all set to in the warehouse when repaired. - for (final BlockPos pos : containerList) + for (final AbstractStorageBlockInterface storageInterface : containerList) { - if (getColony().getWorld() == null) { - continue; - } - - final BlockEntity entity = getColony().getWorld().getBlockEntity(pos); - Optional blockInterface = ModStorageBlocks.getStorageBlockInterface(entity); - blockInterface.ifPresent(i -> i.setInWarehouse(true)); + storageInterface.setInWarehouse(true); } super.requestRepair(builder); @@ -120,17 +114,16 @@ public int getMaxBuildingLevel() @Override public void registerBlockPosition(@NotNull final Block block, @NotNull final BlockPos pos, @NotNull final Level world) { - BlockEntity entity = world.getBlockEntity(pos); - Optional blockInterface = ModStorageBlocks.getStorageBlockInterface(entity); + AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, world); - if (blockInterface.isEmpty() || !blockInterface.get().shouldAutomaticallyAdd(this)) { + if (storageInterface == null || !storageInterface.shouldAutomaticallyAdd(this)) { return; } - blockInterface.get().setInWarehouse(true); + storageInterface.setInWarehouse(true); int targetLevel = getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade(); - while (blockInterface.get().getUpgradeLevel() < targetLevel) { - blockInterface.get().increaseUpgradeLevel(); + while (storageInterface.getUpgradeLevel() < targetLevel) { + storageInterface.increaseUpgradeLevel(); } super.registerBlockPosition(block, pos, world); @@ -167,14 +160,9 @@ public void upgradeContainers(final Level world) { if (getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade() < MAX_STORAGE_UPGRADE) { - for (final BlockPos pos : getContainers()) + for (final AbstractStorageBlockInterface storageInterface : getContainers()) { - BlockEntity entity = world.getBlockEntity(pos); - if (entity instanceof TileEntityColonyBuilding) { - continue; - } - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - storageInterface.ifPresent(IStorageBlockInterface::increaseUpgradeLevel); + storageInterface.increaseUpgradeLevel(); } getFirstModuleOccurance(WarehouseModule.class).incrementStorageUpgrade(); } diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java index 831e93bfa82..3e1fc48fdf1 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java @@ -25,7 +25,7 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.inventory.InventoryCitizen; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.TypeConstants; @@ -792,20 +792,18 @@ protected final boolean walkToBuilding() */ public boolean checkAndTransferFromHut(@Nullable final ItemStack is) { - for (final BlockPos pos : building.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : building.getContainers()) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isStillValid()) + { continue; } - if (storageInterface.get().hasItemStack(is, 1, false)) + if (storageInterface.hasItemStack(is, 1, false)) { - InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler( - storageInterface.get().getInventory(), - (stack) -> ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack), - getInventory()); + storageInterface.transferItemStackFromStorageIntoNextBestSlot( + getInventory(), + stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack)); return true; } } @@ -1033,31 +1031,32 @@ public boolean retrieveToolInHut(final EquipmentTypeEntry toolType, final int mi if (building != null) { final Predicate toolPredicate = stack -> ItemStackUtils.hasEquipmentLevel(stack, toolType, minimalLevel, building.getMaxEquipmentLevel()); - for (final BlockPos pos : building.getContainers()) + for (final AbstractStorageBlockInterface storageInterface : building.getContainers()) { - final BlockEntity entity = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isPresent()) { + if (storageInterface.isStillValid()) { if (ModEquipmentTypes.none.get().equals(toolType)) { return false; } - if (storageInterface.get().hasItemStack(toolPredicate)) + if (storageInterface.hasItemStack(toolPredicate)) { - if (InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(storageInterface.get().getInventory(), - toolPredicate, - worker.getInventoryCitizen())) + if (storageInterface.transferItemStackFromStorageIntoNextBestSlot(worker.getInventoryCitizen(), + toolPredicate)) { return true; } } } - else if (entity instanceof ChestBlockEntity) + else { - if (retrieveToolInTileEntity(building.getTileEntity(), toolType, minimalLevel, building.getMaxEquipmentLevel())) + BlockEntity entity = world.getBlockEntity(storageInterface.getPosition()); + if (entity instanceof ChestBlockEntity) { - return true; + if (retrieveToolInTileEntity(building.getTileEntity(), toolType, minimalLevel, building.getMaxEquipmentLevel())) + { + return true; + } } } } diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java index 42d957f6424..cd0d8d42030 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java @@ -13,7 +13,7 @@ import com.minecolonies.api.entity.ai.statemachine.states.IAIState; import com.minecolonies.api.entity.citizen.VisibleCitizenStatus; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.api.util.InventoryUtils; @@ -567,17 +567,17 @@ public boolean gatherIfInTileEntity(final BlockEntity entity, final ItemStack is return false; } - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(entity.getBlockPos(), entity.getLevel()); + if (storageInterface == null) + { return false; } - if (storageInterface.get().getCount(new ItemStorage(is)) >= is.getCount()) + if (storageInterface.getCount(new ItemStorage(is)) >= is.getCount()) { - return InventoryUtils.transferItemStackIntoNextFreeSlotFromItemHandler(storageInterface.get().getInventory(), + return storageInterface.transferItemStackFromStorageIntoNextFreeSlot(worker.getInventoryCitizen(), stack -> !ItemStackUtils.isEmpty(stack) && ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack, true, true), - is.getCount(), - worker.getInventoryCitizen()); + is.getCount()); } return false; diff --git a/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java b/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java index 6baba511186..56db4cf3770 100755 --- a/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java +++ b/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java @@ -5,7 +5,7 @@ import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.colony.workorders.IWorkOrderView; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.MessageUtils; @@ -203,14 +203,14 @@ private static ItemResourceScroll.WarehouseSnapshot gatherWarehouseSnapshot( final BuildingResourcesModuleView resourcesModule = buildingView.getModuleViewByType(BuildingResourcesModuleView.class); final Map items = new HashMap<>(); - for (final BlockPos container : warehouse.getContainerList()) + for (final AbstractStorageBlockInterface storageInterface : warehouse.getContainerList()) { - final BlockEntity blockEntity = warehouse.getColony().getWorld().getBlockEntity(container); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(blockEntity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isStillValid()) + { continue; } - storageInterface.get().getAllContent().forEach((item, amount) -> { + + storageInterface.getAllContent().forEach((item, amount) -> { final int hashCode = item.getItemStack().hasTag() ? item.getItemStack().getTag().hashCode() : 0; final String key = item.getItemStack().getDescriptionId() + "-" + hashCode; if (!resourcesModule.getResources().containsKey(key)) diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java index 6cdbfde9745..ca4b0d6dcec 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java @@ -18,7 +18,7 @@ import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.ITickable; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.ItemStackUtils; @@ -221,23 +221,16 @@ public BlockPos getPositionOfChestWithItemStack(@NotNull final Predicate storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) + if (storageInterface.hasItemStack(notEmptyPredicate)) { - continue; - } - - if (storageInterface.get().hasItemStack(notEmptyPredicate)) - { - return pos; + return storageInterface.getPosition(); } } } @@ -573,48 +566,6 @@ public void updateBlockState() // Do nothing } - @NotNull - @Override - public LazyOptional getCapability(@NotNull final Capability capability, @Nullable final Direction side) - { - if (!remove && capability == ForgeCapabilities.ITEM_HANDLER && getBuilding() != null) - { - if (combinedInv == null) - { - //Add additional containers - final Set handlers = new LinkedHashSet<>(); - final Level world = colony.getWorld(); - if (world != null) - { - for (final BlockPos pos : building.getContainers()) - { - if (!WorldUtil.isBlockLoaded(world, pos) || pos.equals(this.worldPosition)) - { - continue; - } - - final BlockEntity te = world.getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(te); - if (storageInterface.isPresent()) - { - handlers.add(storageInterface.get().getInventory()); - storageInterface.get().setBuildingPos(this.getBlockPos()); - } - else - { - building.removeContainerPosition(pos); - } - } - } - handlers.add(this.getInventory()); - - combinedInv = LazyOptional.of(() -> new CombinedItemHandler(building.getSchematicName(), handlers.toArray(new IItemHandlerModifiable[0]))); - } - return (LazyOptional) combinedInv; - } - return super.getCapability(capability, side); - } - @Nullable @Override public AbstractContainerMenu createMenu(final int id, @NotNull final Inventory inv, @NotNull final Player player) diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java index 0297b8a9928..db1b6e140b5 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java @@ -3,12 +3,10 @@ import com.minecolonies.api.inventory.InventoryCitizen; import com.minecolonies.api.tileentities.AbstractTileEntityWareHouse; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; -import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.api.util.*; import com.minecolonies.core.colony.buildings.modules.BuildingModules; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; import org.jetbrains.annotations.NotNull; @@ -16,13 +14,11 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import static com.minecolonies.api.util.constant.Constants.TICKS_FIVE_MIN; import static com.minecolonies.api.util.constant.TranslationConstants.*; import static com.minecolonies.core.colony.buildings.workerbuildings.BuildingWareHouse.MAX_STORAGE_UPGRADE; -import net.minecraftforge.common.capabilities.ForgeCapabilities; /** * Class which handles the tileEntity of our colony warehouse. @@ -46,24 +42,18 @@ public boolean hasMatchingItemStackInWarehouse(@NotNull final Predicate storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); if (storageInterface.isEmpty()) { continue; } - if (storageInterface.get().isEmpty()) { - continue; - } - - totalCount += storageInterface.get().getItemCount(itemStackSelectionPredicate); + totalCount += storageInterface.getItemCount(itemStackSelectionPredicate); if (totalCount >= count) { return true; @@ -84,27 +74,22 @@ public boolean hasMatchingItemStackInWarehouse(@NotNull final ItemStack itemStac public boolean hasMatchingItemStackInWarehouse(@NotNull final ItemStack itemStack, final int count, final boolean ignoreNBT, final boolean ignoreDamage, final int leftOver) { int totalCountFound = 0 - leftOver; - for (@NotNull final BlockPos pos : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) { - if (WorldUtil.isBlockLoaded(level, pos)) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { - final BlockEntity entity = getLevel().getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } + continue; + } - if (storageInterface.get().isEmpty()) - { - continue; - } + if (storageInterface.isEmpty()) + { + continue; + } - totalCountFound += storageInterface.get().getCount(itemStack, ignoreDamage, ignoreNBT); - if (totalCountFound >= count) - { - return true; - } + totalCountFound += storageInterface.getCount(itemStack, ignoreDamage, ignoreNBT); + if (totalCountFound >= count) + { + return true; } } return false; @@ -124,31 +109,26 @@ public List> getMatchingItemStacksInWarehouse(@NotNul if (getBuilding() != null) { - for (@NotNull final BlockPos pos : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) { - if (WorldUtil.isBlockLoaded(level, pos)) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { - final BlockEntity entity = getLevel().getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) - { - continue; - } + continue; + } - if (storageInterface.get().isEmpty()) - { - continue; - } + if (storageInterface.isEmpty()) + { + continue; + } - if (storageInterface.get().getItemCount(itemStackSelectionPredicate) <= 0) - { - continue; - } + if (storageInterface.getItemCount(itemStackSelectionPredicate) <= 0) + { + continue; + } - for (final ItemStack stack : (InventoryUtils.filterItemHandler(storageInterface.get().getInventory(), itemStackSelectionPredicate))) - { - found.add(new Tuple<>(stack, pos)); - } + for (final ItemStack stack : storageInterface.getMatching(itemStackSelectionPredicate)) + { + found.add(new Tuple<>(stack, storageInterface.getPosition())); } } } @@ -166,7 +146,7 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory continue; } - @Nullable final BlockEntity chest = getBlockStorageForStack(stack); + @Nullable final AbstractStorageBlockInterface chest = getBlockStorageForStack(stack); if (chest == null) { if(level.getGameTime() - lastNotification > TICKS_FIVE_MIN) @@ -192,52 +172,51 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory } final int index = i; - chest.getCapability(ForgeCapabilities.ITEM_HANDLER, null).ifPresent(handler -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(inventoryCitizen, index, handler)); + InventoryUtils.transferIntoNextBestSlotInStorageBlock(inventoryCitizen, index, chest); } } /** * Get a blockstorage for a stack. * @param stack the stack to insert. - * @return the matching blockstorage. + * @return the matching blockstorage interface. */ - public BlockEntity getBlockStorageForStack(final ItemStack stack) + public AbstractStorageBlockInterface getBlockStorageForStack(final ItemStack stack) { - BlockEntity storageBlock = getPositionOfStorageBlockWithItemStack(stack); - if (storageBlock == null) + AbstractStorageBlockInterface storageBlock = getPositionOfStorageBlockWithItemStack(stack); + if (storageBlock != null) { - storageBlock = getPositionOfStorageBlockWithSimilarItemStack(stack); - if (storageBlock == null) - { - storageBlock = searchMostEmptyStorageBlock(); - } + return storageBlock; } - return storageBlock; + + storageBlock = getPositionOfStorageBlockWithSimilarItemStack(stack); + if (storageBlock != null) + { + return storageBlock; + } + + return searchMostEmptyStorageBlock(); } /** * Search the right storageblock for an itemStack. * * @param stack the stack to dump. - * @return the tile entity of the storageblock + * @return the interface of the storageblock */ @Nullable - private BlockEntity getPositionOfStorageBlockWithItemStack(@NotNull final ItemStack stack) + private AbstractStorageBlockInterface getPositionOfStorageBlockWithItemStack(@NotNull final ItemStack stack) { - for (@NotNull final BlockPos pos : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) { - if (!WorldUtil.isBlockLoaded(level, pos)) { - continue; - } - final BlockEntity entity = getLevel().getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + { continue; } - if (storageInterface.get().getFreeSlots() > 0 && storageInterface.get().hasItemStack(stack, 1, true)) + if (storageInterface.getFreeSlots() > 0 && storageInterface.hasItemStack(stack, 1, true)) { - return entity; + return storageInterface; } } @@ -248,29 +227,26 @@ private BlockEntity getPositionOfStorageBlockWithItemStack(@NotNull final ItemSt * Searches a storageblock with a similar item as the incoming stack. * * @param stack the stack. - * @return the entity of the storageblock. + * @return the interface of the storageblock. */ @Nullable - private BlockEntity getPositionOfStorageBlockWithSimilarItemStack(final ItemStack stack) + private AbstractStorageBlockInterface getPositionOfStorageBlockWithSimilarItemStack(final ItemStack stack) { - for (@NotNull final BlockPos pos : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) { - if (!WorldUtil.isBlockLoaded(level, pos)) { - continue; - } - - final BlockEntity entity = getLevel().getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + { continue; } - if (storageInterface.get().getFreeSlots() <= 0) { + if (storageInterface.getFreeSlots() <= 0) + { continue; } - if (storageInterface.get().hasItemStack(stack, 1, true)) { - return entity; + if (storageInterface.hasItemStack(stack, 1, true)) + { + return storageInterface; } } return null; @@ -279,30 +255,29 @@ private BlockEntity getPositionOfStorageBlockWithSimilarItemStack(final ItemStac /** * Search for the chest with the least items in it. * - * @return the tileEntity of this chest. + * @return the interface of this chest. */ @Nullable - private BlockEntity searchMostEmptyStorageBlock() + private AbstractStorageBlockInterface searchMostEmptyStorageBlock() { int freeSlots = 0; - BlockEntity emptiestChest = null; - for (@NotNull final BlockPos pos : getBuilding().getContainers()) + AbstractStorageBlockInterface emptiestChest = null; + for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) { - final BlockEntity entity = getLevel().getBlockEntity(pos); - Optional storageInterface = ModStorageBlocks.getStorageBlockInterface(entity); - if (storageInterface.isEmpty()) { + if (!storageInterface.isStillValid()) + { continue; } - if (storageInterface.get().isEmpty()) { - return entity; + if (storageInterface.isEmpty()) { + return storageInterface; } - final int tempFreeSlots = storageInterface.get().getFreeSlots(); + final int tempFreeSlots = storageInterface.getFreeSlots(); if (tempFreeSlots > freeSlots) { freeSlots = tempFreeSlots; - emptiestChest = entity; + emptiestChest = storageInterface; } } return emptiestChest; diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java deleted file mode 100644 index 3552d6526b5..00000000000 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractRackStorageBlockInterface.java +++ /dev/null @@ -1,151 +0,0 @@ -package com.minecolonies.core.tileentities.storageblocks; - -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.items.IItemHandlerModifiable; - -import java.util.Map; -import java.util.function.Predicate; - -/** - * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) - */ -public class AbstractRackStorageBlockInterface extends AbstractStorageBlockInterface -{ - public AbstractRackStorageBlockInterface(BlockEntity targetBlockEntity) { - super(targetBlockEntity); - - if (!(targetBlockEntity instanceof AbstractTileEntityRack)) { - throw new RuntimeException("Trying to create an AbstractRackStorageBlockInterface with not instance of AbstractTileEntityRack"); - } - } - - @Override - public boolean shouldAutomaticallyAdd(final IBuilding building) - { - return true; - } - - @Override - public void setInWarehouse(final boolean inWarehouse) - { - getRack().setInWarehouse(inWarehouse); - } - - @Override - public int getUpgradeLevel() - { - return getRack().getUpgradeSize(); - } - - @Override - public void increaseUpgradeLevel() - { - getRack().upgradeRackSize(); - } - - @Override - public int getCount(final ItemStorage storage) - { - return getRack().getCount(storage); - } - - @Override - public int getItemCount(final Predicate predicate) - { - return getRack().getItemCount(predicate); - } - - @Override - public int getFreeSlots() - { - return getRack().getFreeSlots(); - } - - /** - * Gets all items and their count from the storage block. - * - * @return The items and their count - */ - @Override - public Map getAllContent() - { - return null; - } - - /** - * Gets the matching count for a specific item stack and can ignore NBT and damage as well. - * - * @param stack The stack to check against - * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data - * @return The count of matching items in the storageblock - */ - @Override - public int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) - { - return getRack().getCount(stack, ignoreDamageValue, ignoreNBT); - } - - /** - * Whether there are any items in the target storageblock - * - * @return Whether the storageblock is empty - */ - @Override - public boolean isEmpty() { - return getRack().isEmpty(); - } - - /** - * Get the modifiable ItemHandler for the given storageblock - * - * @return the itemhandler - */ - @Override - public IItemHandlerModifiable getInventory() { - return getRack().getInventory(); - } - - /** - * Return whether the storageblock contains a matching item stack - * - * @param stack The item type to compare - * @param count The amount that must be present - * @param ignoreDamage Whether the items should have matching damage values - * @return Whether the storageblock contains the match - */ - @Override - public boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage) { - return getRack().hasItemStack(stack, count, ignoreDamage); - } - - /** - * Return whether the storageblock contains any items matching the predicate - * - * @param predicate The predicate to check against - * @return Whether the storageblock has any matches - */ - @Override - public boolean hasItemStack(Predicate predicate) { - return getRack().hasItemStack(predicate); - } - - /** - * Sets the block position of the building this storage belongs to - * - * @param pos The position of the building - */ - @Override - public void setBuildingPos(BlockPos pos) { - getRack().setBuildingPos(pos); - } - - private AbstractTileEntityRack getRack() { - return (AbstractTileEntityRack) targetBlockEntity; - } -} diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java deleted file mode 100644 index 3998894f752..00000000000 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/AbstractStorageBlockInterface.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.minecolonies.core.tileentities.storageblocks; - -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; -import net.minecraft.world.level.block.entity.BlockEntity; - -public abstract class AbstractStorageBlockInterface implements IStorageBlockInterface { - protected final BlockEntity targetBlockEntity; - - public AbstractStorageBlockInterface(BlockEntity targetBlockEntity) { - this.targetBlockEntity = targetBlockEntity; - } -} diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java new file mode 100644 index 00000000000..d9fb737c43a --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java @@ -0,0 +1,50 @@ +package com.minecolonies.core.tileentities.storageblocks; + +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.core.tileentities.TileEntityColonyBuilding; +import com.minecolonies.core.tileentities.TileEntityRack; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; + +/** + * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) + */ +public class ColonyBuildingStorageBlockInterface extends RackStorageBlockInterface +{ + /** + * Constructor + * + * @param pos The position of the target storage block + * @param world The level the storage block is in + */ + public ColonyBuildingStorageBlockInterface(BlockPos pos, Level world) + { + super(pos, world); + + BlockEntity targetBlockEntity = world.getBlockEntity(pos); + + if (!(targetBlockEntity instanceof TileEntityColonyBuilding)) + { + throw new IllegalArgumentException("The block at the target position must be an instance of TileEntityColonyBuilding"); + } + } + + /** + * Increase the level of the storage block. For colony buildings + * this does nothing. + */ + @Override + public void increaseUpgradeLevel() + { + // Do nothing for colony buildings. + } +} diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java index d3ae0ef73c6..acf427fbb88 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java @@ -2,15 +2,21 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.AbstractTileEntityRack; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.util.InventoryUtils; +import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.BlockPos; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.util.Map; +import java.util.*; import java.util.function.Predicate; /** @@ -18,14 +24,24 @@ */ public class RackStorageBlockInterface extends AbstractStorageBlockInterface { - public RackStorageBlockInterface(BlockEntity targetBlockEntity) { - super(targetBlockEntity); + public RackStorageBlockInterface(BlockPos pos, Level world) + { + super(pos, world); - if (!(targetBlockEntity instanceof TileEntityRack)) { - throw new IllegalArgumentException("targetBlockEntity must be an instance of TileEntityRack"); + BlockEntity targetBlockEntity = world.getBlockEntity(pos); + + if (!(targetBlockEntity instanceof TileEntityRack)) + { + throw new IllegalArgumentException("The block at the target position must be an instance of TileEntityRack"); } } + @Override + public boolean isStillValid() + { + return getRack().isPresent(); + } + @Override public boolean shouldAutomaticallyAdd(final IBuilding building) { @@ -35,37 +51,37 @@ public boolean shouldAutomaticallyAdd(final IBuilding building) @Override public void setInWarehouse(final boolean inWarehouse) { - getRack().setInWarehouse(inWarehouse); + getRack().ifPresent(rack -> rack.setInWarehouse(inWarehouse)); } @Override public int getUpgradeLevel() { - return getRack().getUpgradeSize(); + return getRack().map(TileEntityRack::getUpgradeSize).orElse(0); } @Override public void increaseUpgradeLevel() { - getRack().upgradeRackSize(); + getRack().ifPresent(TileEntityRack::upgradeRackSize); } @Override public int getCount(final ItemStorage storage) { - return getRack().getCount(storage); + return getRack().map(rack -> rack.getCount(storage)).orElse(0); } @Override public int getItemCount(final Predicate predicate) { - return getRack().getItemCount(predicate); + return getRack().map(rack -> rack.getItemCount(predicate)).orElse(0); } @Override public int getFreeSlots() { - return getRack().getFreeSlots(); + return getRack().map(TileEntityRack::getFreeSlots).orElse(0); } /** @@ -76,7 +92,7 @@ public int getFreeSlots() @Override public Map getAllContent() { - return getRack().getAllContent(); + return getRack().map(TileEntityRack::getAllContent).orElse(new HashMap<>()); } /** @@ -90,7 +106,7 @@ public Map getAllContent() @Override public int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) { - return getRack().getCount(stack, ignoreDamageValue, ignoreNBT); + return getRack().map(rack -> rack.getCount(stack, ignoreDamageValue, ignoreNBT)).orElse(0); } /** @@ -100,17 +116,7 @@ public int getCount(final ItemStack stack, final boolean ignoreDamageValue, fina */ @Override public boolean isEmpty() { - return getRack().isEmpty(); - } - - /** - * Get the modifiable ItemHandler for the given storageblock - * - * @return the itemhandler - */ - @Override - public IItemHandlerModifiable getInventory() { - return getRack().getInventory(); + return getRack().map(TileEntityRack::isEmpty).orElse(true); } /** @@ -123,7 +129,7 @@ public IItemHandlerModifiable getInventory() { */ @Override public boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage) { - return getRack().hasItemStack(stack, count, ignoreDamage); + return getRack().map(rack -> rack.hasItemStack(stack, count, ignoreDamage)).orElse(false); } /** @@ -134,7 +140,7 @@ public boolean hasItemStack(final ItemStack stack, final int count, final boolea */ @Override public boolean hasItemStack(Predicate predicate) { - return getRack().hasItemStack(predicate); + return getRack().map(rack -> rack.hasItemStack(predicate)).orElse(false); } /** @@ -144,10 +150,108 @@ public boolean hasItemStack(Predicate predicate) { */ @Override public void setBuildingPos(BlockPos pos) { - getRack().setBuildingPos(pos); + getRack().ifPresent(rack -> rack.setBuildingPos(pos)); + } + + /** + * Add an item stack to this storage block. + * + * @param stack The stack to add + * @return Whether the addition was successful + */ + @Override + public boolean storeItemStack(final @NotNull ItemStack stack) + { + return getRack().map(rack -> InventoryUtils.addItemStackToItemHandler(rack.getInventory(), stack)).orElse(false); + } + + /** + * Get any matching item stacks within the storage block. + * + * @param predicate The predicate to test against + * @return The list of matching item stacks + */ + @Override + public List getMatching(final @NotNull Predicate predicate) + { + return getRack().map(rack -> InventoryUtils.filterItemHandler(rack.getInventory(), predicate)).orElse(new ArrayList<>()); + } + + /** + * Attempt to add an itemstack to the storage and return the remaining stack + * + * @param itemStack The stack to attempt to add + * @return The remaining stack after adding whatever can be added + */ + @Override + public ItemStack addItemStackWithResult(@Nullable final ItemStack itemStack) + { + return getRack().map(rack -> InventoryUtils.addItemStackToItemHandlerWithResult(rack.getInventory(), itemStack)).orElse(itemStack); } - private TileEntityRack getRack() { - return (TileEntityRack) targetBlockEntity; + /** + * Force stack to the storage block. + * + * @param itemStack ItemStack to add. + * @param itemStackToKeepPredicate The {@link Predicate} that determines which ItemStacks to keep in the inventory. Return false to replace. + * @return itemStack which has been replaced, null if none has been replaced. + */ + @Override + public @Nullable ItemStack forceAddItemStack(final @NotNull ItemStack itemStack, final @NotNull Predicate itemStackToKeepPredicate) + { + return getRack().map(rack -> InventoryUtils.forceItemStackToItemHandler(rack.getInventory(), itemStack, itemStackToKeepPredicate)).orElse(null); + } + + /** + * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. + * + * @param sourceHandler The {@link IItemHandler} that works as Source. + * @param predicate the predicate for the stack. + * @return true when the swap was successful, false when not. + */ + @Override + public boolean transferItemStackToStorageIntoNextBestSlot(final @NotNull IItemHandler sourceHandler, final Predicate predicate) + { + return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(sourceHandler, predicate, rack.getInventory())).orElse(false); + } + + /** + * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. + * + * @param targetHandler The {@link IItemHandler} that works as receiver. + * @param predicate the predicate for the stack. + * @return true when the swap was successful, false when not. + */ + @Override + public boolean transferItemStackFromStorageIntoNextBestSlot(final @NotNull IItemHandler targetHandler, final Predicate predicate) + { + return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(rack.getInventory(), predicate, targetHandler)).orElse(false); + } + + /** + * Method to swap the ItemStacks from storage to the given target {@link IItemHandler}. + * + * @param targetHandler The {@link IItemHandler} that works as Target. + * @param stackPredicate The type of stack to pickup. + * @param count how much to pick up. + * @return True when the swap was successful, false when not. + */ + @Override + public boolean transferItemStackFromStorageIntoNextFreeSlot(final @NotNull IItemHandler targetHandler, final @NotNull Predicate stackPredicate, final int count) + { + return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextFreeSlotFromItemHandler(rack.getInventory(), stackPredicate, count, targetHandler)).orElse(false); + } + + /** + * Get the target tile entity as the TileEntityRack if it doesn't exist + * + * @return The target TileEntityRack if it exists + */ + private Optional getRack() { + BlockEntity targetBlockEntity = level.getBlockEntity(targetPos); + if (!(targetBlockEntity instanceof TileEntityRack)) { + return Optional.empty(); + } + return Optional.of((TileEntityRack) targetBlockEntity); } } From 89e565df124da302d170f0d7fcfb656674bfda44 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 22:32:58 -0600 Subject: [PATCH 08/17] Cleanup pt 1 --- .../api/MinecoloniesAPIProxy.java | 6 ++- .../AbstractStorageBlockInterface.java | 22 +---------- .../storageblocks/ModStorageBlocks.java | 5 +++ .../minecolonies/api/util/InventoryUtils.java | 38 +++++++++++-------- 4 files changed, 34 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java b/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java index bd88f630941..940ad5d3bb7 100755 --- a/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java +++ b/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java @@ -237,5 +237,9 @@ public IForgeRegistry getEquipmentTypeRegistry() return apiInstance.getEquipmentTypeRegistry(); } - public IForgeRegistry getStorageBlockRegistry() { return apiInstance.getStorageBlockRegistry(); } + @Override + public IForgeRegistry getStorageBlockRegistry() + { + return apiInstance.getStorageBlockRegistry(); + } } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java index c8800383055..a5bb2714dee 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java @@ -6,7 +6,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.items.IItemHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -183,14 +182,6 @@ public boolean isLoaded() */ public abstract List getMatching(@NotNull final Predicate predicate); - /** - * Attempt to add an itemstack to the storage and return the remaining stack - * - * @param itemStack The stack to attempt to add - * @return The remaining stack after adding whatever can be added - */ - public abstract ItemStack addItemStackWithResult(@Nullable ItemStack itemStack); - /** * Force stack to the storage block. * @@ -203,17 +194,6 @@ public abstract ItemStack forceAddItemStack( @NotNull final ItemStack itemStack, @NotNull final Predicate itemStackToKeepPredicate); - /** - * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. - * - * @param sourceHandler The {@link IItemHandler} that works as Source. - * @param predicate the predicate for the stack. - * @return true when the swap was successful, false when not. - */ - public abstract boolean transferItemStackToStorageIntoNextBestSlot( - @NotNull final IItemHandler sourceHandler, - final Predicate predicate); - /** * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. * @@ -230,7 +210,7 @@ public abstract boolean transferItemStackFromStorageIntoNextBestSlot( * * @param targetHandler The {@link IItemHandler} that works as Target. * @param stackPredicate The type of stack to pickup. - * @param count how much to pick up. + * @param count how much to pick up. * @return True when the swap was successful, false when not. */ public abstract boolean transferItemStackFromStorageIntoNextFreeSlot( diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index 4a1f133f951..aed097fdd58 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -16,6 +16,10 @@ import javax.annotation.Nullable; +/** + * Class that is used to manage StorageBlocks including registering them + * and creating new ones based off of block positions. + */ public final class ModStorageBlocks { public static final DeferredRegister DEFERRED_REGISTER = DeferredRegister.create(new ResourceLocation(Constants.MOD_ID, "storageblocks"), Constants.MOD_ID); @@ -39,6 +43,7 @@ public final class ModStorageBlocks .setStorageInterface(ColonyBuildingStorageBlockInterface::new) .build()); } + /** * Private constructor so this class can't be instantiated. */ diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 5c4bf3b13af..3b106ee8e5b 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -7,9 +7,6 @@ import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; -import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; -import com.minecolonies.core.tileentities.TileEntityColonyBuilding; -import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.item.ItemEntity; @@ -20,7 +17,6 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.items.IItemHandler; @@ -740,20 +736,23 @@ public static int getDurabilityInProvider(@NotNull final ICapabilityProvider pro * @param stack the stack to check. * @return Amount of occurrences of stacks that match the given predicate. */ - public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) + public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final ItemStorage stack, final int count) { int totalCount = 0; + final Level world = provider.getColony().getWorld(); + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + { continue; } - totalCount += storageInterface.getItemCount(stack); + totalCount += storageInterface.getCount(stack); if (totalCount >= count) { - return totalCount; + return Integer.MAX_VALUE; } } @@ -912,6 +911,18 @@ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provide return totalCount; } + /** + * Checks if a player has a block in the {@link ICapabilityProvider}. Checked by {@link #getItemCountInProvider(ICapabilityProvider, Block)} > 0; + * + * @param Provider {@link ICapabilityProvider} to scan + * @param block Block to count + * @return True when in {@link ICapabilityProvider}, otherwise false + */ + public static boolean hasItemInProvider(@NotNull final ICapabilityProvider Provider, @NotNull final Block block) + { + return hasItemInProvider(Provider, getItemFromBlock(block)); + } + /** * Checks if a player has an item in the {@link ICapabilityProvider}. Checked by {@link #getItemCountInProvider(ICapabilityProvider, Item)} > 0; * @@ -3162,23 +3173,20 @@ private static void updateHeldItemFromServer(final Player player) * @param stack the stack to check. * @return Amount of occurrences of stacks that match the given predicate. */ - public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final ItemStorage stack, final int count) + public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) { int totalCount = 0; - final Level world = provider.getColony().getWorld(); - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) - { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - totalCount += storageInterface.getCount(stack); + totalCount += storageInterface.getItemCount(stack); if (totalCount >= count) { - return Integer.MAX_VALUE; + return totalCount; } } From 79ac3631406ba5e04887cc97bb2bac9a54f24b2b Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 22:38:35 -0600 Subject: [PATCH 09/17] Cleanup pt 2 --- .../minecolonies/api/util/InventoryUtils.java | 68 ++++++++++--------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 3b106ee8e5b..91792fd798c 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -17,6 +17,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.items.IItemHandler; @@ -760,23 +761,27 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, } /** - * Count the number of items a building has. + * Check if a building has more than a count in stack. Return the count it has if it has less. * * @param provider building to check in. * @param stack the stack to check. - * @return Amount of occurrences of stacks that match the given stack. + * @return Amount of occurrences of stacks that match the given predicate. */ - public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNull final ItemStorage stack) + public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) { int totalCount = 0; for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) - { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { continue; } - totalCount += storageInterface.getCount(stack); + totalCount += storageInterface.getItemCount(stack); + + if (totalCount >= count) + { + return totalCount; + } } return totalCount; @@ -801,6 +806,30 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu return totalCount; } + /** + * Count the number of items a building has. + * + * @param provider building to check in. + * @param stack the stack to check. + * @return Amount of occurrences of stacks that match the given stack. + */ + public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNull final ItemStorage stack) + { + int totalCount = 0; + + for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) + { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + { + continue; + } + + totalCount += storageInterface.getCount(stack); + } + + return totalCount; + } + /** * Calculate the number of empty slots in a given building. * @param ownBuilding the building to check. @@ -3166,33 +3195,6 @@ private static void updateHeldItemFromServer(final Player player) } } - /** - * Check if a building has more than a count in stack. Return the count it has if it has less. - * - * @param provider building to check in. - * @param stack the stack to check. - * @return Amount of occurrences of stacks that match the given predicate. - */ - public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) - { - int totalCount = 0; - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) - { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { - continue; - } - - totalCount += storageInterface.getItemCount(stack); - - if (totalCount >= count) - { - return totalCount; - } - } - - return totalCount; - } - public static List getBuildingInventory(final IBuilding building) { final List allInInv = new ArrayList<>(); From 32189e75b6b29c12fb348891227a44c12b425730 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 22:45:42 -0600 Subject: [PATCH 10/17] Cleanup pt 3 --- .../AbstractStorageBlockInterface.java | 11 ++++ .../minecolonies/api/util/InventoryUtils.java | 52 ++++++++----------- .../tileentities/TileEntityWareHouse.java | 3 +- .../RackStorageBlockInterface.java | 38 +++++--------- 4 files changed, 48 insertions(+), 56 deletions(-) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java index a5bb2714dee..737089a6c59 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java @@ -217,4 +217,15 @@ public abstract boolean transferItemStackFromStorageIntoNextFreeSlot( @NotNull final IItemHandler targetHandler, @NotNull final Predicate stackPredicate, final int count); + + /** + * Method to swap the ItemStacks from the given source {@link IItemHandler} to storage. Trying to merge existing itemStacks if possible. + * + * @param sourceHandler The {@link IItemHandler} that works as Source. + * @param sourceIndex The index of the slot that is being extracted from. + * @return True when the swap was successful, false when not. + */ + public abstract boolean transferFromIndexToStorageIntoNextBestSlot( + @NotNull final IItemHandler sourceHandler, + final int sourceIndex); } diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 91792fd798c..9f1ba6e0e2b 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -7,6 +7,8 @@ import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.core.tileentities.TileEntityColonyBuilding; +import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.item.ItemEntity; @@ -1812,35 +1814,6 @@ public static boolean transferItemStackIntoNextBestSlotInItemHandler(final ItemS return transferItemStackIntoNextBestSlotInItemHandlerWithResult(stack, targetHandler).isEmpty(); } - /** - * Method to swap the ItemStacks from the given source {@link AbstractStorageBlockInterface} to the given target {@link IItemHandler}. Trying to merge existing itemStacks if possible. - * - * @param sourceHandler The {@link IItemHandler} that works as Source. - * @param sourceIndex The index of the slot that is being extracted from. - * @param targetInterface The {@link AbstractStorageBlockInterface} that works as Target. - * @return True when the swap was successful, false when not. - */ - public static boolean transferIntoNextBestSlotInStorageBlock( - @NotNull final IItemHandler sourceHandler, - final int sourceIndex, - @NotNull final AbstractStorageBlockInterface targetInterface) - { - ItemStack sourceStack = sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, true); - - if (ItemStackUtils.isEmpty(sourceStack)) - { - return true; - } - - if (targetInterface.storeItemStack(sourceStack)) - { - sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, false); - return true; - } - return false; - } - - /** * Method to put a given Itemstack in a given target {@link IItemHandler}. Trying to merge existing itemStacks if possible. * @@ -3195,6 +3168,27 @@ private static void updateHeldItemFromServer(final Player player) } } + /** + * Check if there is enough of a given stack in the provider. + * @param entity the provider. + * @param stack the stack to count. + * @param count the count. + * @return true if enough. + */ + public static boolean hasEnoughInProvider(final BlockEntity entity, final ItemStack stack, final int count) + { + if (entity instanceof TileEntityColonyBuilding) + { + return InventoryUtils.hasBuildingEnoughElseCount( ((TileEntityColonyBuilding) entity).getBuilding(), new ItemStorage(stack), stack.getCount()) >= count; + } + else if (entity instanceof TileEntityRack) + { + return ((TileEntityRack) entity).getCount(stack, false, false) >= count; + } + + return getItemCountInProvider(entity, itemStack -> !ItemStackUtils.isEmpty(itemStack) && ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, stack, true, true)) >= count; + } + public static List getBuildingInventory(final IBuilding building) { final List allInInv = new ArrayList<>(); diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java index db1b6e140b5..bbdce244f50 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java @@ -171,8 +171,7 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory return; } - final int index = i; - InventoryUtils.transferIntoNextBestSlotInStorageBlock(inventoryCitizen, index, chest); + chest.transferFromIndexToStorageIntoNextBestSlot(inventoryCitizen, i); } } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java index acf427fbb88..c251a99ea06 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java @@ -177,18 +177,6 @@ public List getMatching(final @NotNull Predicate predicate return getRack().map(rack -> InventoryUtils.filterItemHandler(rack.getInventory(), predicate)).orElse(new ArrayList<>()); } - /** - * Attempt to add an itemstack to the storage and return the remaining stack - * - * @param itemStack The stack to attempt to add - * @return The remaining stack after adding whatever can be added - */ - @Override - public ItemStack addItemStackWithResult(@Nullable final ItemStack itemStack) - { - return getRack().map(rack -> InventoryUtils.addItemStackToItemHandlerWithResult(rack.getInventory(), itemStack)).orElse(itemStack); - } - /** * Force stack to the storage block. * @@ -202,19 +190,6 @@ public ItemStack addItemStackWithResult(@Nullable final ItemStack itemStack) return getRack().map(rack -> InventoryUtils.forceItemStackToItemHandler(rack.getInventory(), itemStack, itemStackToKeepPredicate)).orElse(null); } - /** - * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. - * - * @param sourceHandler The {@link IItemHandler} that works as Source. - * @param predicate the predicate for the stack. - * @return true when the swap was successful, false when not. - */ - @Override - public boolean transferItemStackToStorageIntoNextBestSlot(final @NotNull IItemHandler sourceHandler, final Predicate predicate) - { - return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(sourceHandler, predicate, rack.getInventory())).orElse(false); - } - /** * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. * @@ -242,6 +217,19 @@ public boolean transferItemStackFromStorageIntoNextFreeSlot(final @NotNull IItem return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextFreeSlotFromItemHandler(rack.getInventory(), stackPredicate, count, targetHandler)).orElse(false); } + /** + * Method to swap the ItemStacks from the given source {@link IItemHandler} to storage. Trying to merge existing itemStacks if possible. + * + * @param sourceHandler The {@link IItemHandler} that works as Source. + * @param sourceIndex The index of the slot that is being extracted from. + * @return True when the swap was successful, false when not. + */ + @Override + public boolean transferFromIndexToStorageIntoNextBestSlot(final @NotNull IItemHandler sourceHandler, final int sourceIndex) + { + return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(sourceHandler, sourceIndex, rack.getInventory())).orElse(false); + } + /** * Get the target tile entity as the TileEntityRack if it doesn't exist * From 63c88dc2f14a32b2349f2cc5af691f75e2c97b49 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 22:54:12 -0600 Subject: [PATCH 11/17] Some import cleanups --- .../com/minecolonies/core/client/gui/WindowsBarracksSpies.java | 2 -- .../colony/buildings/workerbuildings/BuildingWareHouse.java | 3 --- .../core/entity/ai/workers/AbstractEntityAIBasic.java | 2 -- .../entity/ai/workers/service/EntityAIWorkDeliveryman.java | 1 - 4 files changed, 8 deletions(-) diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java index 6e38bb9b891..b5883b51d6a 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java @@ -17,8 +17,6 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.wrapper.InvWrapper; -import java.util.Optional; - import static com.minecolonies.api.util.constant.TranslationConstants.DESCRIPTION_BARRACKS_HIRE_SPIES; /** diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 953d45bed5a..9148de814db 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -26,11 +26,8 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.NotNull; -import java.util.Optional; - /** * Class of the warehouse building. */ diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java index 3e1fc48fdf1..90ae7d2c265 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java @@ -26,7 +26,6 @@ import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.inventory.InventoryCitizen; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; -import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.api.util.constant.translation.RequestSystemTranslationConstants; @@ -64,7 +63,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.Optional; import java.util.function.Predicate; import static com.minecolonies.api.colony.requestsystem.requestable.deliveryman.AbstractDeliverymanRequestable.getMaxBuildingPriority; diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java index cd0d8d42030..228834df33e 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java @@ -42,7 +42,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Optional; import java.util.stream.Collectors; import static com.minecolonies.api.entity.ai.statemachine.states.AIWorkerState.*; From 4ff8ac323019586a7689892e130badbb17c1c5e7 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 23:00:49 -0600 Subject: [PATCH 12/17] Added missing javadoc --- .../tileentities/storageblocks/registry/StorageBlockEntry.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index f64badda5d0..66c3d39303e 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -70,6 +70,9 @@ public ResourceLocation getRegistryName() { return registryName; } + /** + * A builder class used to construct StorageBlockEntry objects + */ public static class Builder { /** * The registry identifier for this storage block. From 547823333f75ea7c6c8a48ce8267706c428248b0 Mon Sep 17 00:00:00 2001 From: Max Lees Date: Sun, 22 Sep 2024 23:14:28 -0600 Subject: [PATCH 13/17] Added another javadoc --- .../storageblocks/registry/StorageBlockEntry.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index 66c3d39303e..ae2ad801192 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -7,11 +7,12 @@ import net.minecraft.world.level.block.entity.BlockEntity; import java.util.function.BiFunction; -import java.util.function.Function; import java.util.function.Predicate; - - +/** + * An entry for the StorageBlock registry that allows a way to register + * new storage block types to Minecolonies. + */ public final class StorageBlockEntry { /** * The registry identifier for this storage block. From 41a7a256c1d76b2a22b45f5158e2560bba3447dc Mon Sep 17 00:00:00 2001 From: Max Lees Date: Mon, 30 Sep 2024 12:35:32 -0600 Subject: [PATCH 14/17] Lots broken. Switching to another computer so commiting --- .../api/colony/buildings/IBuilding.java | 13 +- .../colony/buildings/IBuildingContainer.java | 4 +- .../colony/buildings/views/IBuildingView.java | 4 +- .../tileentities/AbstractTileEntityRack.java | 69 ----- .../storageblocks/AbstractStorageBlock.java | 279 ++++++++++++++++++ .../AbstractStorageBlockInterface.java | 231 --------------- .../storageblocks/IStorageBlock.java | 141 +++++++++ .../storageblocks/InsertNotifier.java | 121 ++++++++ .../storageblocks/ModStorageBlocks.java | 10 +- .../registry/StorageBlockEntry.java | 15 +- .../minecolonies/api/util/InventoryUtils.java | 131 ++++++-- .../api/util/constant/NbtTagConstants.java | 3 + .../client/gui/WindowHutAllInventory.java | 18 +- .../core/client/gui/WindowsBarracksSpies.java | 4 +- .../colony/buildings/AbstractBuilding.java | 66 ++--- .../buildings/AbstractBuildingContainer.java | 20 +- .../AbstractBuildingStructureBuilder.java | 12 - .../buildings/views/AbstractBuildingView.java | 9 +- .../workerbuildings/BuildingWareHouse.java | 49 ++- .../ai/workers/AbstractEntityAIBasic.java | 21 +- .../service/EntityAIWorkDeliveryman.java | 11 +- .../core/items/ItemResourceScroll.java | 7 +- .../TileEntityColonyBuilding.java | 15 +- .../core/tileentities/TileEntityRack.java | 14 - .../tileentities/TileEntityWareHouse.java | 46 +-- ...e.java => ColonyBuildingStorageBlock.java} | 14 +- .../storageblocks/RackStorageBlock.java | 157 ++++++++++ .../RackStorageBlockInterface.java | 245 --------------- 28 files changed, 958 insertions(+), 771 deletions(-) create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java delete mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java rename src/main/java/com/minecolonies/core/tileentities/storageblocks/{ColonyBuildingStorageBlockInterface.java => ColonyBuildingStorageBlock.java} (65%) create mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java delete mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java diff --git a/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java b/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java index 66d80b0578c..80fddcd26e0 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java @@ -19,6 +19,7 @@ import com.minecolonies.api.colony.requestsystem.resolver.IRequestResolverProvider; import com.minecolonies.api.colony.requestsystem.token.IToken; import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.Tuple; @@ -37,7 +38,7 @@ import static com.minecolonies.api.util.constant.EquipmentLevelConstants.BASIC_TOOL_LEVEL; import static com.minecolonies.api.util.constant.EquipmentLevelConstants.TOOL_LEVEL_MAXIMUM; -public interface IBuilding extends IBuildingContainer, IModuleContainer, IRequestResolverProvider, IRequester, ISchematicProvider +public interface IBuilding extends IBuildingContainer, IModuleContainer, IRequestResolverProvider, IRequester, ISchematicProvider, InsertNotifier.IInsertListener { /** * Minimal level to ask for wood tools. (WOOD_HUT_LEVEL + 1 == stone) @@ -263,16 +264,6 @@ default int buildingRequiresCertainAmountOfItem(ItemStack stack, List, Tuple> getRequiredItemsAndAmount(); - /** - * Try to transfer a stack to one of the inventories of the building and force the transfer. - * - * @param stack the stack to transfer. - * @param world the world to do it in. - * @return the itemStack which has been replaced or the itemStack which could not be transfered - */ - @Nullable - ItemStack forceTransferStack(ItemStack stack, Level world); - /** * Create a request for a citizen. * diff --git a/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java b/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java index 4eba3cb653d..1f86269f30b 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/IBuildingContainer.java @@ -1,7 +1,7 @@ package com.minecolonies.api.colony.buildings; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; @@ -57,7 +57,7 @@ public interface IBuildingContainer extends ISchematicProvider, ICapabilityProvi * * @return a copy of the list to avoid currentModification exception. */ - List getContainers(); + List getContainers(); /** * Register a blockState and position. We suppress this warning since this parameter will be used in child classes which override this method. diff --git a/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java b/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java index cff3b39fadd..119650a778c 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/views/IBuildingView.java @@ -9,7 +9,7 @@ import com.minecolonies.api.colony.requestsystem.request.IRequest; import com.minecolonies.api.colony.requestsystem.requester.IRequester; import com.minecolonies.api.colony.requestsystem.token.IToken; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import org.jetbrains.annotations.NotNull; @@ -60,7 +60,7 @@ public interface IBuildingView extends IRequester, IModuleContainerView * * @return containerList. */ - List getContainerList(); + List getContainerList(); /** * Get the max level of the building. diff --git a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java index 782a95e9d97..c65bb254e90 100755 --- a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java +++ b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java @@ -23,16 +23,6 @@ public abstract class AbstractTileEntityRack extends BlockEntity implements MenuProvider { - /** - * whether this rack is in a warehouse or not. defaults to not set by the warehouse building upon being built - */ - protected boolean inWarehouse = false; - - /** - * Pos of the owning building. - */ - protected BlockPos buildingPos = BlockPos.ZERO; - /** * The inventory of the tileEntity. */ @@ -114,51 +104,6 @@ public ItemStack insertItem(final int slot, @Nonnull final ItemStack stack, fina */ public abstract ItemStackHandler createInventory(final int slots); - /** - * Update the warehouse if available with the updated stack. - * - * @param stack the incoming stack. - */ - public void updateWarehouseIfAvailable(final ItemStack stack) - { - if (!ItemStackUtils.isEmpty(stack) && level != null && !level.isClientSide) - { - if (inWarehouse || !buildingPos.equals(BlockPos.ZERO)) - { - if (IColonyManager.getInstance().isCoordinateInAnyColony(level, worldPosition)) - { - final IColony colony = IColonyManager.getInstance().getClosestColony(level, worldPosition); - if (colony == null) - { - return; - } - - if (inWarehouse) - { - colony.getRequestManager().onColonyUpdate(request -> - request.getRequest() instanceof IDeliverable && ((IDeliverable) request.getRequest()).matches(stack)); - } - else - { - final IBuilding building = colony.getBuildingManager().getBuilding(buildingPos); - if (building != null) - { - building.overruleNextOpenRequestWithStack(stack); - building.markDirty(); - } - } - } - } - } - } - - /** - * Set the value for inWarehouse - * - * @param isInWarehouse is this rack in a warehouse? - */ - public abstract void setInWarehouse(Boolean isInWarehouse); - /** * Get the amount of free slots in the inventory. This method checks the content list, it is therefore extremely fast. * @@ -215,20 +160,6 @@ public void updateWarehouseIfAvailable(final ItemStack stack) */ public abstract void upgradeRackSize(); - /** - * Set the building pos it belongs to. - * - * @param pos the pos of the building. - */ - public void setBuildingPos(final BlockPos pos) - { - if (level != null && (buildingPos == null || !buildingPos.equals(pos))) - { - setChanged(); - } - this.buildingPos = pos; - } - /** * Get the upgrade size. * diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java new file mode 100644 index 00000000000..831e1400acc --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java @@ -0,0 +1,279 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import com.minecolonies.api.colony.IColony; +import com.minecolonies.api.colony.IColonyManager; +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.colony.buildings.views.IBuildingView; +import com.minecolonies.api.colony.requestsystem.requestable.IDeliverable; +import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.util.BlockPosUtil; +import com.minecolonies.api.util.ItemStackUtils; +import com.minecolonies.api.util.WorldUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.function.Predicate; + +import static com.minecolonies.api.util.constant.NbtTagConstants.*; + +/** + * The abstract StorageBlock class that all implementations should + * inherit from. + */ +public abstract class AbstractStorageBlock +{ + /** + * The position of the block entity in the world. + */ + protected BlockPos targetPos; + + /** + * The level that the block entity is located in. + */ + protected final Level level; + + /** + * The level that the storage block has been upgraded to. + */ + protected int upgradeLevel = 0; + + /** + * The notifier used to let other blocks know when this + * storageblock has items inserted. + */ + protected InsertNotifier insertNotifier; + + /** + * Constructor + * + * @param targetPos The location of the block + * @param level The world the block is in + */ + public AbstractStorageBlock(final BlockPos targetPos, Level level) + { + this.targetPos = targetPos; + this.level = level; + insertNotifier = new InsertNotifier(level); + } + + /** + * Add a new listener for when items are inserted + * to this storage block. + * + * @param listenerPos The position of the listener entity + */ + public void addInsertListener(BlockPos listenerPos) + { + insertNotifier.addInsertListener(listenerPos); + } + + /** + * Gets the current upgrade level of the storageblock + * + * @return The current level + */ + public int getUpgradeLevel() + { + return upgradeLevel; + } + + /** + * Upgrades the size of the storage, if applicable. + */ + public void increaseUpgradeLevel() + { + ++upgradeLevel; + } + + /** + * The position of the target storage block. + * + * @return The position. + */ + public final BlockPos getPosition() + { + return targetPos; + } + + /** + * Whether the block is currently loaded. + * + * @return Whether it's loaded. + */ + public final boolean isLoaded() + { + return WorldUtil.isBlockLoaded(level, targetPos); + } + + /** + * Write this object to NBT. + * + * @return The NBT data for this object. + */ + public CompoundTag serializeNBT() + { + CompoundTag result = new CompoundTag(); + + BlockPosUtil.write(result, TAG_POS, targetPos); + result.put(TAG_INPUT_LISTENER, insertNotifier.serializeToNBT()); + + return result; + } + + /** + * Load block data from NBT data. + * + * @param nbt The NBT data for the block + */ + public void read(final CompoundTag nbt) + { + targetPos = BlockPosUtil.read(nbt, TAG_POS); + insertNotifier.read(nbt.getCompound(TAG_INPUT_LISTENER)); + } + + /** + * Adds the full item stack to the first available slot in + * the storage block. + * + * @return if the full transfer was successful + */ + public boolean insertFullStack(final ItemStack stack, final boolean simulate) + { + final boolean result = insertFullStackImpl(stack, simulate); + + if (result && !simulate) + { + insertNotifier.notifyInsert(targetPos, stack); + } + + return result; + } + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param storage The item to check for + */ + public abstract int getItemCount(final ItemStorage storage); + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param predicate The predicate used to select items + */ + public abstract int getItemCount(final Predicate predicate); + + /** + * Gets the matching count for a specific + * item stack and can ignore NBT and damage as well. + * + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + public abstract int getItemCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); + + /** + * Check whether the position is still valid for this storage interface + * + * @param building The building the block is in + * @return Whether the position is still valid + */ + public abstract boolean isStillValid(final IBuilding building); + + /** + * Check whether the position is still valid for this storage interface + * + * @param building A view of the building the block is in + * @return Whether the position is still valid + */ + public abstract boolean isStillValid(final IBuildingView building); + + /** + * Return the number of free slots in the container. + * + * @return The free slots + */ + public abstract int getFreeSlots(); + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + public abstract boolean isEmpty(); + + /** + * Whether the storage block has 0 completely free slots. + * + * @return True if there are no free slots, false otherwise. + */ + public abstract boolean isFull(); + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + public abstract boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + public abstract boolean hasItemStack(final Predicate predicate); + + /** + * Get any matching item stacks within the storage block. + * + * @param predicate The predicate to test against + * @return The list of matching item stacks + */ + public abstract List getMatching(@NotNull final Predicate predicate); + + /** + * Gets all items and their count from the storage block. + * + * @return The items and their count + */ + public abstract Map getAllContent(); + + /** + * Removes an item stack matching the given predicate from the storage block + * and returns it. + * + * @param predicate The predicate to match + * @param simulate If true, actually remove the item. + * @return The matching item stack, or ItemStack.EMPTY + */ + public abstract ItemStack extractItem(final Predicate predicate, boolean simulate); + + /** + * Removes an item stack matching the given predicate from the storage block + * and returns it. Will only return if the stack has at least minCount stack size. + * + * @param predicate The predicate to match + * @param minCount The minimum count the stack size must be + * @param simulate If true, actually removes the item. + * @return The matching item stack, or ItemStack.EMPTY + */ + public abstract ItemStack extractItem(final Predicate predicate, int minCount, boolean simulate); + + /** + * Adds the full item stack to the first available slot in + * the storage block. + * + * @return if the full transfer was successful + */ + protected abstract boolean insertFullStackImpl(final ItemStack stack, final boolean simulate); +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java deleted file mode 100644 index 737089a6c59..00000000000 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlockInterface.java +++ /dev/null @@ -1,231 +0,0 @@ -package com.minecolonies.api.tileentities.storageblocks; - -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.util.WorldUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraftforge.items.IItemHandler; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; - -/** - * The abstract StorageBlockInterface class that all implementations should - * inherit from. - */ -public abstract class AbstractStorageBlockInterface -{ - /** - * The position of the block entity in the world. - */ - protected final BlockPos targetPos; - - /** - * The level that the block entity is located in. - */ - protected final Level level; - - /** - * Constructor - * - * @param targetPos The location of the block - * @param level The world the block is in - */ - public AbstractStorageBlockInterface(final BlockPos targetPos, Level level) - { - this.targetPos = targetPos; - this.level = level; - } - - /** - * Check whether the position is still valid for this storage interface - * - * @return Whether the position is still valid - */ - public abstract boolean isStillValid(); - - /** - * Whether the storageblock should be included in building containers automatically. - * - * @param building The building that is being constructed. - * @return Whether the storageblock should be included in building containers automatically. - */ - public abstract boolean shouldAutomaticallyAdd(final IBuilding building); - - /** - * Sets whether the block is part of a warehouse. - * - * @param inWarehouse Whether it's in a warehouse - */ - public abstract void setInWarehouse(final boolean inWarehouse); - - /** - * Gets the current upgrade level of the storageblock - * - * @return The current level - */ - public abstract int getUpgradeLevel(); - - /** - * Upgrades the size of the storage, if applicable. - */ - public abstract void increaseUpgradeLevel(); - - /** - * Gets the amount of a particular item contained in the storageblock - * - * @param storage The item to check for - */ - public abstract int getCount(final ItemStorage storage); - - /** - * Gets the amount of a particular item contained in the storageblock - * - * @param predicate The predicate used to select items - */ - public abstract int getItemCount(final Predicate predicate); - - /** - * Return the number of free slots in the container. - * - * @return The free slots - */ - public abstract int getFreeSlots(); - - /** - * Gets all items and their count from the storage block. - * - * @return The items and their count - */ - public abstract Map getAllContent(); - - /** - * Gets the matching count for a specific item stack and can ignore NBT and damage as well. - * - * @param stack The stack to check against - * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data - * @return The count of matching items in the storageblock - */ - public abstract int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); - - /** - * Whether there are any items in the target storageblock - * - * @return Whether the storageblock is empty - */ - public abstract boolean isEmpty(); - - /** - * Return whether the storageblock contains a matching item stack - * - * @param stack The item type to compare - * @param count The amount that must be present - * @param ignoreDamage Whether the items should have matching damage values - * @return Whether the storageblock contains the match - */ - public abstract boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); - - /** - * Return whether the storageblock contains any items matching the predicate - * - * @param predicate The predicate to check against - * @return Whether the storageblock has any matches - */ - public abstract boolean hasItemStack(final Predicate predicate); - - /** - * Sets the block position of the building this storage belongs to - * - * @param pos The position of the building - */ - public abstract void setBuildingPos(final BlockPos pos); - - /** - * The position of the target storage block. - * - * @return The position. - */ - public BlockPos getPosition() - { - return targetPos; - } - - /** - * Whether the block is currently loaded. - * - * @return Whether it's loaded. - */ - public boolean isLoaded() - { - return WorldUtil.isBlockLoaded(level, targetPos); - } - - /** - * Add an item stack to this storage block. - * - * @param stack The stack to add - * @return Whether the addition was successful - */ - public abstract boolean storeItemStack(@NotNull final ItemStack stack); - - /** - * Get any matching item stacks within the storage block. - * - * @param predicate The predicate to test against - * @return The list of matching item stacks - */ - public abstract List getMatching(@NotNull final Predicate predicate); - - /** - * Force stack to the storage block. - * - * @param itemStack ItemStack to add. - * @param itemStackToKeepPredicate The {@link Predicate} that determines which ItemStacks to keep in the inventory. Return false to replace. - * @return itemStack which has been replaced, null if none has been replaced. - */ - @Nullable - public abstract ItemStack forceAddItemStack( - @NotNull final ItemStack itemStack, - @NotNull final Predicate itemStackToKeepPredicate); - - /** - * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. - * - * @param targetHandler The {@link IItemHandler} that works as receiver. - * @param predicate the predicate for the stack. - * @return true when the swap was successful, false when not. - */ - public abstract boolean transferItemStackFromStorageIntoNextBestSlot( - @NotNull final IItemHandler targetHandler, - final Predicate predicate); - - /** - * Method to swap the ItemStacks from storage to the given target {@link IItemHandler}. - * - * @param targetHandler The {@link IItemHandler} that works as Target. - * @param stackPredicate The type of stack to pickup. - * @param count how much to pick up. - * @return True when the swap was successful, false when not. - */ - public abstract boolean transferItemStackFromStorageIntoNextFreeSlot( - @NotNull final IItemHandler targetHandler, - @NotNull final Predicate stackPredicate, - final int count); - - /** - * Method to swap the ItemStacks from the given source {@link IItemHandler} to storage. Trying to merge existing itemStacks if possible. - * - * @param sourceHandler The {@link IItemHandler} that works as Source. - * @param sourceIndex The index of the slot that is being extracted from. - * @return True when the swap was successful, false when not. - */ - public abstract boolean transferFromIndexToStorageIntoNextBestSlot( - @NotNull final IItemHandler sourceHandler, - final int sourceIndex); -} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java new file mode 100644 index 00000000000..d3226817291 --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java @@ -0,0 +1,141 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.colony.buildings.views.IBuildingView; +import com.minecolonies.api.crafting.ItemStorage; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.function.Predicate; + +/** + * An interface used for defining storage blocks. This shouldn't be used + * directly. Use the AbstractStorageBlock instead. + */ +public interface IStorageBlock +{ + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param storage The item to check for + */ + int getItemCount(final ItemStorage storage); + + /** + * Gets the amount of a particular item contained in the storageblock + * + * @param predicate The predicate used to select items + */ + int getItemCount(final Predicate predicate); + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + int getItemCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); + + /** + * Check whether the position is still valid for this storage interface + * + * @param building The building the block is in + * @return Whether the position is still valid + */ + boolean isStillValid(final IBuilding building); + + /** + * Check whether the position is still valid for this storage interface + * + * @param building A view of the building the block is in + * @return Whether the position is still valid + */ + boolean isStillValid(final IBuildingView building); + + /** + * Return the number of free slots in the container. + * + * @return The free slots + */ + int getFreeSlots(); + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + boolean isEmpty(); + + /** + * Whether the storage block has 0 completely free slots. + * + * @return True if there are no free slots, false otherwise. + */ + boolean isFull(); + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + boolean hasItemStack(final Predicate predicate); + + /** + * Get any matching item stacks within the storage block. + * + * @param predicate The predicate to test against + * @return The list of matching item stacks + */ + List getMatching(@NotNull final Predicate predicate); + + /** + * Gets all items and their count from the storage block. + * + * @return The items and their count + */ + Map getAllContent(); + + /** + * Removes an item stack matching the given predicate from the storage block + * and returns it. + * + * @param predicate The predicate to match + * @param simulate If true, actually remove the item. + * @return The matching item stack, or ItemStack.EMPTY + */ + ItemStack extractItem(final Predicate predicate, boolean simulate); + + /** + * Removes an item stack matching the given predicate from the storage block + * and returns it. Will only return if the stack has at least minCount stack size. + * + * @param predicate The predicate to match + * @param minCount The minimum count the stack size must be + * @param simulate If true, actually removes the item. + * @return The matching item stack, or ItemStack.EMPTY + */ + ItemStack extractItem(final Predicate predicate, int minCount, boolean simulate); + + /** + * Adds the full item stack to the first available slot in + * the storage block. + * + * @return if the full transfer was successful + */ + boolean insertFullStackImpl(final ItemStack stack, final boolean simulate); +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java new file mode 100644 index 00000000000..dc455a22941 --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java @@ -0,0 +1,121 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import com.minecolonies.api.util.NBTUtils; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; +import net.minecraft.nbt.Tag; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; + +import java.util.HashSet; +import java.util.Set; + +import static com.minecolonies.api.util.constant.NbtTagConstants.TAG_LISTENER_LOC; + +/** + * This defines a notifier that will inform listeners + * when a stack is inserted to an inventory. + */ +public class InsertNotifier +{ + /** + * The list of positions of BlockEntities that would like + * to be notified when items are inserted into this StorageBlock. + */ + private final Set insertListeners = new HashSet<>(); + /** + * Level that the BlockEntity this InsertNotifier corresponds + * to is located in. + */ + Level level; + + /** + * Constructor + * + * @param level The level the block entity this insert notifier + * is located in. + */ + public InsertNotifier(Level level) + { + this.level = level; + } + + /** + * Add a new listener to be notified on item inserts. + * + * @param pos The position of the listener. Warning: It + * must be on the same level as the storage. + */ + public void addInsertListener(final BlockPos pos) + { + this.insertListeners.add(pos); + } + + /** + * Notify all the listeners that an item was inserted. + * + * @param insertPos The location of the storage where the item was + * inserted. + * @param itemStack The item stack that was inserted. + */ + public void notifyInsert(final BlockPos insertPos, final ItemStack itemStack) + { + if (level == null) + { + return; + } + + for (BlockPos pos : this.insertListeners) + { + BlockEntity entity = level.getBlockEntity(pos); + if (entity instanceof IInsertListener listener) + { + listener.onInsert(insertPos, itemStack); + } + } + } + + /** + * Serialize the InsertNotifier to NBT data. + * + * @return The NBT data. + */ + public CompoundTag serializeToNBT() + { + final CompoundTag tag = new CompoundTag(); + + tag.put(TAG_LISTENER_LOC, insertListeners.stream().map(NbtUtils::writeBlockPos).collect(NBTUtils.toListNBT())); + + return tag; + } + + /** + * Populate teh InsertNotifier from NBT + * + * @param nbt The NBT data. + */ + public void read(CompoundTag nbt) + { + NBTUtils.streamCompound(nbt.getList(TAG_LISTENER_LOC, Tag.TAG_COMPOUND)) + .map(NbtUtils::readBlockPos) + .forEach(insertListeners::add); + } + + /** + * The interface that any listener must implement. + */ + public interface IInsertListener + { + /** + * The function that will be called to notify the listener + * that a new item stack was inserted. + * + * @param insertPos The location of the storage where the item was + * inserted. + * @param itemStack The item stack that was inserted. + */ + void onInsert(BlockPos insertPos, ItemStack itemStack); + } +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index aed097fdd58..9d88f43b65e 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -5,8 +5,8 @@ import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.TileEntityRack; -import com.minecolonies.core.tileentities.storageblocks.ColonyBuildingStorageBlockInterface; -import com.minecolonies.core.tileentities.storageblocks.RackStorageBlockInterface; +import com.minecolonies.core.tileentities.storageblocks.ColonyBuildingStorageBlock; +import com.minecolonies.core.tileentities.storageblocks.RackStorageBlock; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; @@ -33,14 +33,14 @@ public final class ModStorageBlocks () -> new StorageBlockEntry.Builder() .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityRack && !(blockEntity instanceof TileEntityColonyBuilding)) .setRegistryName(new ResourceLocation(Constants.MOD_ID, "rack")) - .setStorageInterface(RackStorageBlockInterface::new) + .setStorageInterface(RackStorageBlock::new) .build()); storageBlockColonyBuilding = DEFERRED_REGISTER.register("colony_building", () -> new StorageBlockEntry.Builder() .setIsStorageBlock(blockEntity -> blockEntity instanceof TileEntityColonyBuilding) .setRegistryName(new ResourceLocation(Constants.MOD_ID, "colony_building")) - .setStorageInterface(ColonyBuildingStorageBlockInterface::new) + .setStorageInterface(ColonyBuildingStorageBlock::new) .build()); } @@ -59,7 +59,7 @@ private ModStorageBlocks() * @return A StorageBlockInterface for the given BlockEntity if one exists. */ @Nullable - public static AbstractStorageBlockInterface getStorageBlockInterface(BlockPos pos, Level world) + public static AbstractStorageBlock getStorageBlockInterface(BlockPos pos, Level world) { BlockEntity blockEntity = world.getBlockEntity(pos); if (blockEntity == null) diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index ae2ad801192..174a233fa29 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -1,6 +1,6 @@ package com.minecolonies.api.tileentities.storageblocks.registry; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; @@ -13,7 +13,8 @@ * An entry for the StorageBlock registry that allows a way to register * new storage block types to Minecolonies. */ -public final class StorageBlockEntry { +public final class StorageBlockEntry +{ /** * The registry identifier for this storage block. */ @@ -28,7 +29,7 @@ public final class StorageBlockEntry { /** * The interface that will be used to interact with the particular block. */ - private final BiFunction storageInterface; + private final BiFunction storageInterface; /** * Constructor @@ -37,7 +38,7 @@ public final class StorageBlockEntry { * @param isStorageBlock The predicate to determine if a block is this storage block type * @param storageInterface The interface used to interact with the particular block */ - public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, BiFunction storageInterface) { + public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, BiFunction storageInterface) { this.registryName = registryName; this.isStorageBlock = isStorageBlock; this.storageInterface = storageInterface; @@ -58,7 +59,7 @@ public boolean matches(final BlockEntity blockEntity) { * * @return The interface. */ - public BiFunction getStorageInterface() { + public BiFunction getStorageInterface() { return storageInterface; } @@ -89,7 +90,7 @@ public static class Builder { /** * The interface that will be used to interact with the particular block. */ - private BiFunction storageInterface; + private BiFunction storageInterface; /** * Set the registry name for the StorageBlockEntry being built. @@ -120,7 +121,7 @@ public Builder setIsStorageBlock(Predicate isStorageBlock) { * @param storageInterface The interface * @return this */ - public Builder setStorageInterface(BiFunction storageInterface) { + public Builder setStorageInterface(BiFunction storageInterface) { this.storageInterface = storageInterface; return this; } diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index 9f1ba6e0e2b..f84c191ec40 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -6,7 +6,8 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlock; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.Direction; @@ -742,16 +743,14 @@ public static int getDurabilityInProvider(@NotNull final ICapabilityProvider pro public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final ItemStorage stack, final int count) { int totalCount = 0; - final Level world = provider.getColony().getWorld(); - - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) + for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { continue; } - totalCount += storageInterface.getCount(stack); + totalCount += storageInterface.getItemCount(stack); if (totalCount >= count) { @@ -772,9 +771,9 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, @NotNull final Predicate stack, final int count) { int totalCount = 0; - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) + for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { continue; } @@ -819,14 +818,14 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu { int totalCount = 0; - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) + for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { continue; } - totalCount += storageInterface.getCount(stack); + totalCount += storageInterface.getItemCount(stack); } return totalCount; @@ -841,9 +840,9 @@ public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) { int totalCount = 0; - for (final AbstractStorageBlockInterface storageInterface : ownBuilding.getContainers()) + for (final AbstractStorageBlock storageInterface : ownBuilding.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(ownBuilding)) { continue; } @@ -862,14 +861,14 @@ public static int countEmptySlotsInBuilding(final IBuilding ownBuilding) */ public static boolean isBuildingFull(final IBuilding ownBuilding) { - for (final AbstractStorageBlockInterface storageInterface : ownBuilding.getContainers()) + for (final AbstractStorageBlock storageInterface : ownBuilding.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(ownBuilding)) { continue; } - if (storageInterface.getFreeSlots() > 0) + if (!storageInterface.isFull()) { return false; } @@ -888,11 +887,10 @@ public static boolean isBuildingFull(final IBuilding ownBuilding) public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNull final Predicate predicate) { int totalCount = 0; - final Level world = provider.getColony().getWorld(); - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) + for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { continue; } @@ -913,13 +911,11 @@ public static int getCountFromBuilding(@NotNull final IBuilding provider, @NotNu */ public static int getCountFromBuildingWithLimit(@NotNull final IBuilding provider, @NotNull final Predicate predicate, final Function limit) { - final Level world = provider.getColony().getWorld(); - final Map allMatching = new HashMap<>(); - for (final AbstractStorageBlockInterface storageInterface : provider.getContainers()) + for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { continue; } @@ -3192,9 +3188,9 @@ else if (entity instanceof TileEntityRack) public static List getBuildingInventory(final IBuilding building) { final List allInInv = new ArrayList<>(); - for (final AbstractStorageBlockInterface storageInterface : building.getContainers()) + for (final AbstractStorageBlock storageInterface : building.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) { + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(building)) { continue; } @@ -3205,4 +3201,89 @@ public static List getBuildingInventory(final IBuilding building) } return allInInv; } + + /** + * Method to transfer an ItemStacks from the storage block to an {@link IItemHandler}. + * + * @param sourceStorage The source of the item stack + * @param predicate the predicate for the stack. + * @param targetHandler The {@link IItemHandler} that works as receiver. + * @return true when the swap was successful, false when not. + */ + public static boolean transferItemStackIntoNextBestSlotInItemHandler( + @NotNull final AbstractStorageBlock sourceStorage, + final Predicate predicate, + @NotNull final IItemHandler targetHandler) + { + ItemStack itemStack = sourceStorage.extractItem(predicate, true); + + if (itemStack.isEmpty()) + { + return false; + } + + if (!InventoryUtils.addItemStackToItemHandler(targetHandler, itemStack)) { + return false; + } + + sourceStorage.extractItem(predicate, false); + return true; + } + + /** + * Method to swap the ItemStacks from storage to the given target {@link IItemHandler}. + * + * @param targetHandler The {@link IItemHandler} that works as Target. + * @param stackPredicate The type of stack to pickup. + * @param count how much to pick up. + * @return True when the swap was successful, false when not. + */ + public static boolean transferItemStackIntoNextFreeSlotInItemHandler( + @NotNull final AbstractStorageBlock sourceStorage, + @NotNull final Predicate stackPredicate, + final int count, + @NotNull final IItemHandler targetHandler) + { + ItemStack itemStack = sourceStorage.extractItem(stackPredicate, count, true); + + if (itemStack.isEmpty()) + { + return false; + } + + if (!InventoryUtils.addItemStackToItemHandler(targetHandler, itemStack)) + { + return false; + } + + sourceStorage.extractItem(stackPredicate, count, false); + return true; + } + + /** + * Method to swap the ItemStacks from the given source {@link IItemHandler} to storage. Trying to merge existing itemStacks if possible. + * + * @param sourceHandler The {@link IItemHandler} that works as Source. + * @param sourceIndex The index of the slot that is being extracted from. + * @return True when the swap was successful, false when not. + */ + public static boolean transferItemStackIntoNextBestSlotInStorage( + @NotNull final IItemHandler sourceHandler, + final int sourceIndex, + @NotNull final AbstractStorageBlock targetStorage) + { + ItemStack sourceStack = sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, true); + + if (ItemStackUtils.isEmpty(sourceStack)) + { + return true; + } + + if (targetStorage.insertFullStack(sourceStack, false)) + { + sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, false); + return true; + } + return false; + } } diff --git a/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java b/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java index 2f2ca0d4bdf..47a9f5558e9 100755 --- a/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java +++ b/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java @@ -736,6 +736,9 @@ public final class NbtTagConstants public static final String TAG_SAW_STORY = "sawstory"; public static final String TAG_RANDOM_KEY = "randkey"; + public static final String TAG_INPUT_LISTENER = "inputlistener"; + public static final String TAG_LISTENER_LOC = "listenerloc"; + /** * Private constructor to hide the implicit one. */ diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java index c80e6ea4492..d6987e68728 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java @@ -6,7 +6,7 @@ import com.ldtteam.blockui.views.ScrollingList; import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.MessageUtils; import com.minecolonies.api.util.Utils; @@ -16,14 +16,12 @@ import com.minecolonies.core.colony.buildings.AbstractBuilding; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; -import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; @@ -117,21 +115,21 @@ private void locate(final Button button) { final int row = stackList.getListElementIndexByPane(button); final ItemStorage storage = allItems.get(row); - final Set containerList = new HashSet<>(building.getContainerList()); + final Set containerList = new HashSet<>(building.getContainerList()); containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getID(), building.getColony().getWorld())); HighlightManager.clearHighlightsForKey("inventoryHighlight"); MessageUtils.format(MESSAGE_LOCATING_ITEMS).sendTo(Minecraft.getInstance().player); close(); - for (final AbstractStorageBlockInterface storageInterface : containerList) + for (final AbstractStorageBlock storageInterface : containerList) { - if (!storageInterface.isStillValid()) + if (!storageInterface.isStillValid(building)) { continue; } - int count = storageInterface.getCount(storage.getItemStack(), storage.ignoreDamageValue(), false); + int count = storageInterface.getItemCount(storage.getItemStack(), storage.ignoreDamageValue(), false); if (count <= 0) { continue; @@ -198,15 +196,15 @@ private void setSortFlag() */ private void updateResources() { - final Set containerList = new HashSet<>(building.getContainerList()); + final Set containerList = new HashSet<>(building.getContainerList()); final Map storedItems = new HashMap<>(); final Level world = building.getColony().getWorld(); containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getPosition(), world)); - for (final AbstractStorageBlockInterface storageInterface : containerList) + for (final AbstractStorageBlock storageInterface : containerList) { - if (!storageInterface.isStillValid()) + if (!storageInterface.isStillValid(building)) { continue; } diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java index b5883b51d6a..08117633495 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java @@ -3,7 +3,7 @@ import com.ldtteam.blockui.controls.*; import com.ldtteam.blockui.views.BOWindow; import com.minecolonies.api.colony.buildings.views.IBuildingView; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.InventoryUtils; import com.minecolonies.api.util.constant.Constants; @@ -73,7 +73,7 @@ public WindowsBarracksSpies(final IBuildingView buildingView, final BlockPos bui int goldCount = InventoryUtils.getItemCountInItemHandler(playerInv, Items.GOLD_INGOT); - AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingPos, buildingView.getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingPos, buildingView.getColony().getWorld()); if (storageInterface != null) { goldCount += storageInterface.getItemCount(stack -> stack.is(Items.GOLD_INGOT)); diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java index 9da634ba988..f59865f0eb3 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java @@ -37,7 +37,7 @@ import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.api.util.constant.TypeConstants; @@ -72,7 +72,6 @@ import net.minecraft.world.level.block.AirBlock; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.entity.ChestBlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.capabilities.ICapabilityProvider; @@ -711,7 +710,7 @@ public void serializeToView(@NotNull final FriendlyByteBuf buf, final boolean fu } buf.writeNbt(StandardFactoryController.getInstance().serialize(getId())); buf.writeInt(containerList.size()); - for (final AbstractStorageBlockInterface storageInterface : containerList) + for (final AbstractStorageBlock storageInterface : containerList) { buf.writeBlockPos(storageInterface.getPosition()); } @@ -1225,50 +1224,6 @@ protected boolean keepFood() return true; } - /** - * Try to transfer a stack to one of the inventories of the building and force the transfer. - * - * @param stack the stack to transfer. - * @param world the world to do it in. - * @return the itemStack which has been replaced or the itemStack which could not be transfered - */ - @Override - @Nullable - public ItemStack forceTransferStack(final ItemStack stack, final Level world) - { - if (getTileEntity() == null) - { - for (final AbstractStorageBlockInterface storageInterface : containerList) - { - if (storageInterface.getFreeSlots() != 0) { - return forceItemStackToStorageBlock(storageInterface, stack); - } - } - } - else - { - return forceItemStackToProvider(getTileEntity(), stack); - } - return stack; - } - - @Nullable - private ItemStack forceItemStackToProvider(@NotNull final ICapabilityProvider provider, @NotNull final ItemStack itemStack) - { - final List localAlreadyKept = new ArrayList<>(); - return InventoryUtils.forceItemStackToProvider(provider, - itemStack, - (ItemStack stack) -> EntityAIWorkDeliveryman.workerRequiresItem(this, stack, localAlreadyKept) != stack.getCount()); - } - - @Nullable - private ItemStack forceItemStackToStorageBlock(@NotNull final AbstractStorageBlockInterface storageInterface, @NotNull final ItemStack itemStack) - { - final List localAlreadyKept = new ArrayList<>(); - return storageInterface.forceAddItemStack(itemStack, - (ItemStack stack) -> EntityAIWorkDeliveryman.workerRequiresItem(this, stack, localAlreadyKept) != stack.getCount()); - } - //------------------------- Ending Required Tools/Item handling -------------------------// //------------------------- !START! RequestSystem handling for minecolonies buildings -------------------------// @@ -2076,4 +2031,21 @@ public Map reservedStacksExcluding(@NotNull final IRequest } //------------------------- !END! RequestSystem handling for minecolonies buildings -------------------------// + + @Override + public void onInsert(final BlockPos insertPos, final ItemStack itemStack) + { + if (ItemStackUtils.isEmpty(itemStack) || colony.getWorld().isClientSide) + { + return; + } + + if (!colony.isCoordInColony(colony.getWorld(), insertPos)) + { + return; + } + + overruleNextOpenRequestWithStack(itemStack); + markDirty(); + } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java index 74a6eb5ca6a..238ab799000 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java @@ -6,7 +6,7 @@ import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.buildings.IBuildingContainer; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import net.minecraft.core.BlockPos; @@ -43,7 +43,7 @@ public abstract class AbstractBuildingContainer extends AbstractSchematicProvide /** * A list which contains the position of all containers which belong to the worker building. */ - protected final Set containerList = new HashSet<>(); + protected final Set containerList = new HashSet<>(); /** * List of items the worker should keep. With the quantity and if he should keep it in the inventory as well. @@ -102,7 +102,7 @@ public CompoundTag serializeNBT() final CompoundTag compound = super.serializeNBT(); @NotNull final ListTag containerTagList = new ListTag(); - for (@NotNull final AbstractStorageBlockInterface storageInterface : containerList) + for (@NotNull final AbstractStorageBlock storageInterface : containerList) { containerTagList.add(NbtUtils.writeBlockPos(storageInterface.getPosition())); } @@ -127,7 +127,7 @@ public void alterPickUpPriority(final int value) @Override public void addContainerPosition(@NotNull final BlockPos pos) { - AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); if (storageInterface != null) { containerList.add(ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld())); @@ -137,8 +137,8 @@ public void addContainerPosition(@NotNull final BlockPos pos) @Override public void removeContainerPosition(final BlockPos pos) { - List toRemove = new ArrayList<>(); - for (final AbstractStorageBlockInterface storageInterface : containerList) { + List toRemove = new ArrayList<>(); + for (final AbstractStorageBlock storageInterface : containerList) { if (storageInterface.getPosition().equals(pos)) { toRemove.add(storageInterface); } @@ -148,9 +148,9 @@ public void removeContainerPosition(final BlockPos pos) } @Override - public List getContainers() + public List getContainers() { - final List list = new ArrayList<>(containerList);; + final List list = new ArrayList<>(containerList);; list.add(ModStorageBlocks.getStorageBlockInterface(getPosition(), getColony().getWorld())); return list; } @@ -182,12 +182,12 @@ public void registerBlockPosition(@NotNull final Block block, @NotNull final Blo } else { - AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); if (storageInterface == null) { return; } addContainerPosition(pos); - storageInterface.setBuildingPos(this.getID()); + storageInterface.addInsertListener(getID()); } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingStructureBuilder.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingStructureBuilder.java index d3d739a0ce7..a9688269399 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingStructureBuilder.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingStructureBuilder.java @@ -185,18 +185,6 @@ public Map, net.minecraft.util.Tuple> get return toKeep; } - @Override - public ItemStack forceTransferStack(final ItemStack stack, final Level world) - { - final ItemStack itemStack = super.forceTransferStack(stack, world); - if (ItemStackUtils.isEmpty(itemStack)) - { - this.markDirty(); - } - - return itemStack; - } - @Override public void deserializeNBT(final CompoundTag compound) { diff --git a/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java b/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java index 6fa40c1e479..7a0d47bc90a 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java @@ -15,7 +15,7 @@ import com.minecolonies.api.colony.requestsystem.manager.IRequestManager; import com.minecolonies.api.colony.requestsystem.request.IRequest; import com.minecolonies.api.colony.requestsystem.token.IToken; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.TypeConstants; @@ -26,7 +26,6 @@ import com.minecolonies.core.network.messages.server.colony.OpenInventoryMessage; import com.minecolonies.core.network.messages.server.colony.building.HutRenameMessage; import it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; @@ -136,7 +135,7 @@ public abstract class AbstractBuildingView implements IBuildingView * The BlockPos list of all Containers */ - private List containerlist = new ArrayList<>(); + private List containerlist = new ArrayList<>(); /** * If building is deconstructed. @@ -345,7 +344,7 @@ public int getClaimRadius() * Returns the Container List */ @Override - public List getContainerList() + public List getContainerList() { return new ArrayList<>(containerlist); } @@ -430,7 +429,7 @@ public void deserialize(@NotNull final FriendlyByteBuf buf) final int racks = buf.readInt(); for (int i = 0; i < racks; i++) { - AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(buf.readBlockPos(), getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(buf.readBlockPos(), getColony().getWorld()); if (storageInterface != null) { containerlist.add(storageInterface); diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 9148de814db..55b3a239813 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -5,12 +5,17 @@ import com.ldtteam.blockui.views.BOWindow; import com.minecolonies.api.colony.ICitizenData; import com.minecolonies.api.colony.IColony; +import com.minecolonies.api.colony.IColonyManager; import com.minecolonies.api.colony.IColonyView; +import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.buildings.workerbuildings.IWareHouse; +import com.minecolonies.api.colony.requestsystem.requestable.IDeliverable; import com.minecolonies.api.colony.requestsystem.resolver.IRequestResolver; import com.minecolonies.api.tileentities.*; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; +import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.core.client.gui.WindowHutMinPlaceholder; import com.minecolonies.core.colony.buildings.AbstractBuilding; @@ -24,6 +29,7 @@ import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.TileEntityWareHouse; import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import org.jetbrains.annotations.NotNull; @@ -63,9 +69,9 @@ public BuildingWareHouse(final IColony c, final BlockPos l) public void requestRepair(final BlockPos builder) { //To ensure that the storageblocks are all set to in the warehouse when repaired. - for (final AbstractStorageBlockInterface storageInterface : containerList) + for (final AbstractStorageBlock storageInterface : containerList) { - storageInterface.setInWarehouse(true); + storageInterface.addInsertListener(builder); } super.requestRepair(builder); @@ -111,15 +117,17 @@ public int getMaxBuildingLevel() @Override public void registerBlockPosition(@NotNull final Block block, @NotNull final BlockPos pos, @NotNull final Level world) { - AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, world); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, world); - if (storageInterface == null || !storageInterface.shouldAutomaticallyAdd(this)) { + if (storageInterface == null) + { return; } - storageInterface.setInWarehouse(true); + storageInterface.addInsertListener(pos); int targetLevel = getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade(); - while (storageInterface.getUpgradeLevel() < targetLevel) { + while (storageInterface.getUpgradeLevel() < targetLevel) + { storageInterface.increaseUpgradeLevel(); } @@ -157,7 +165,7 @@ public void upgradeContainers(final Level world) { if (getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade() < MAX_STORAGE_UPGRADE) { - for (final AbstractStorageBlockInterface storageInterface : getContainers()) + for (final AbstractStorageBlock storageInterface : getContainers()) { storageInterface.increaseUpgradeLevel(); } @@ -172,6 +180,29 @@ public boolean canBeGathered() return false; } + /** + * The function that will be called to notify the listener + * that a new item stack was inserted. + * + * @param itemStack The item stack that was inserted. + */ + @Override + public void onInsert(final BlockPos insertPos, final ItemStack itemStack) + { + if (ItemStackUtils.isEmpty(itemStack) || colony.getWorld().isClientSide) + { + return; + } + + if (!colony.isCoordInColony(colony.getWorld(), insertPos)) + { + return; + } + + colony.getRequestManager().onColonyUpdate(request -> + request.getRequest() instanceof IDeliverable && ((IDeliverable) request.getRequest()).matches(itemStack)); + } + /** * BuildWarehouse View. */ @@ -195,4 +226,6 @@ public BOWindow getWindow() return new WindowHutMinPlaceholder<>(this); } } + + } diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java index 90ae7d2c265..2f009bf0b6c 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/AbstractEntityAIBasic.java @@ -25,7 +25,7 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.inventory.InventoryCitizen; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.api.util.constant.translation.RequestSystemTranslationConstants; @@ -790,18 +790,18 @@ protected final boolean walkToBuilding() */ public boolean checkAndTransferFromHut(@Nullable final ItemStack is) { - for (final AbstractStorageBlockInterface storageInterface : building.getContainers()) + for (final AbstractStorageBlock storageInterface : building.getContainers()) { - if (!storageInterface.isStillValid()) + if (!storageInterface.isStillValid(building)) { continue; } if (storageInterface.hasItemStack(is, 1, false)) { - storageInterface.transferItemStackFromStorageIntoNextBestSlot( - getInventory(), - stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack)); + InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(storageInterface, + stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack), + getInventory()); return true; } } @@ -1029,9 +1029,9 @@ public boolean retrieveToolInHut(final EquipmentTypeEntry toolType, final int mi if (building != null) { final Predicate toolPredicate = stack -> ItemStackUtils.hasEquipmentLevel(stack, toolType, minimalLevel, building.getMaxEquipmentLevel()); - for (final AbstractStorageBlockInterface storageInterface : building.getContainers()) + for (final AbstractStorageBlock storageInterface : building.getContainers()) { - if (storageInterface.isStillValid()) { + if (storageInterface.isStillValid(building)) { if (ModEquipmentTypes.none.get().equals(toolType)) { return false; @@ -1039,8 +1039,9 @@ public boolean retrieveToolInHut(final EquipmentTypeEntry toolType, final int mi if (storageInterface.hasItemStack(toolPredicate)) { - if (storageInterface.transferItemStackFromStorageIntoNextBestSlot(worker.getInventoryCitizen(), - toolPredicate)) + if (InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(storageInterface, + toolPredicate, + worker.getInventoryCitizen())) { return true; } diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java index 228834df33e..c90fce92ae7 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java @@ -13,7 +13,7 @@ import com.minecolonies.api.entity.ai.statemachine.states.IAIState; import com.minecolonies.api.entity.citizen.VisibleCitizenStatus; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.api.util.InventoryUtils; @@ -566,17 +566,18 @@ public boolean gatherIfInTileEntity(final BlockEntity entity, final ItemStack is return false; } - AbstractStorageBlockInterface storageInterface = ModStorageBlocks.getStorageBlockInterface(entity.getBlockPos(), entity.getLevel()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(entity.getBlockPos(), entity.getLevel()); if (storageInterface == null) { return false; } - if (storageInterface.getCount(new ItemStorage(is)) >= is.getCount()) + if (storageInterface.getItemCount(new ItemStorage(is)) >= is.getCount()) { - return storageInterface.transferItemStackFromStorageIntoNextFreeSlot(worker.getInventoryCitizen(), + return InventoryUtils.transferItemStackIntoNextFreeSlotInItemHandler(storageInterface, stack -> !ItemStackUtils.isEmpty(stack) && ItemStackUtils.compareItemStacksIgnoreStackSize(is, stack, true, true), - is.getCount()); + is.getCount(), + worker.getInventoryCitizen()); } return false; diff --git a/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java b/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java index 56db4cf3770..1a0bfe005f8 100755 --- a/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java +++ b/src/main/java/com/minecolonies/core/items/ItemResourceScroll.java @@ -5,8 +5,7 @@ import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.colony.workorders.IWorkOrderView; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; -import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.MessageUtils; import com.minecolonies.api.util.constant.TranslationConstants; @@ -203,9 +202,9 @@ private static ItemResourceScroll.WarehouseSnapshot gatherWarehouseSnapshot( final BuildingResourcesModuleView resourcesModule = buildingView.getModuleViewByType(BuildingResourcesModuleView.class); final Map items = new HashMap<>(); - for (final AbstractStorageBlockInterface storageInterface : warehouse.getContainerList()) + for (final AbstractStorageBlock storageInterface : warehouse.getContainerList()) { - if (!storageInterface.isStillValid()) + if (!storageInterface.isStillValid(warehouse)) { continue; } diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java index ca4b0d6dcec..d5df3426d90 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityColonyBuilding.java @@ -18,14 +18,11 @@ import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.ITickable; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; -import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.ItemStackUtils; import com.minecolonies.api.util.Log; -import com.minecolonies.api.util.WorldUtil; import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.Connection; import net.minecraft.network.chat.Component; @@ -35,15 +32,10 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Mirror; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandlerModifiable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -221,9 +213,9 @@ public BlockPos getPositionOfChestWithItemStack(@NotNull final Predicate= count) { return true; @@ -109,9 +109,9 @@ public List> getMatchingItemStacksInWarehouse(@NotNul if (getBuilding() != null) { - for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlock storageInterface : getBuilding().getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(getBuilding())) { continue; } @@ -146,7 +146,7 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory continue; } - @Nullable final AbstractStorageBlockInterface chest = getBlockStorageForStack(stack); + @Nullable final AbstractStorageBlock chest = getBlockStorageForStack(stack); if (chest == null) { if(level.getGameTime() - lastNotification > TICKS_FIVE_MIN) @@ -171,7 +171,7 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory return; } - chest.transferFromIndexToStorageIntoNextBestSlot(inventoryCitizen, i); + InventoryUtils.transferItemStackIntoNextBestSlotInStorage(inventoryCitizen, i, chest); } } @@ -180,9 +180,9 @@ public void dumpInventoryIntoWareHouse(@NotNull final InventoryCitizen inventory * @param stack the stack to insert. * @return the matching blockstorage interface. */ - public AbstractStorageBlockInterface getBlockStorageForStack(final ItemStack stack) + public AbstractStorageBlock getBlockStorageForStack(final ItemStack stack) { - AbstractStorageBlockInterface storageBlock = getPositionOfStorageBlockWithItemStack(stack); + AbstractStorageBlock storageBlock = getPositionOfStorageBlockWithItemStack(stack); if (storageBlock != null) { return storageBlock; @@ -204,16 +204,16 @@ public AbstractStorageBlockInterface getBlockStorageForStack(final ItemStack sta * @return the interface of the storageblock */ @Nullable - private AbstractStorageBlockInterface getPositionOfStorageBlockWithItemStack(@NotNull final ItemStack stack) + private AbstractStorageBlock getPositionOfStorageBlockWithItemStack(@NotNull final ItemStack stack) { - for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlock storageInterface : getBuilding().getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(getBuilding())) { continue; } - if (storageInterface.getFreeSlots() > 0 && storageInterface.hasItemStack(stack, 1, true)) + if (!storageInterface.isFull() && storageInterface.hasItemStack(stack, 1, true)) { return storageInterface; } @@ -229,11 +229,11 @@ private AbstractStorageBlockInterface getPositionOfStorageBlockWithItemStack(@No * @return the interface of the storageblock. */ @Nullable - private AbstractStorageBlockInterface getPositionOfStorageBlockWithSimilarItemStack(final ItemStack stack) + private AbstractStorageBlock getPositionOfStorageBlockWithSimilarItemStack(final ItemStack stack) { - for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) + for (@NotNull final AbstractStorageBlock storageInterface : getBuilding().getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid()) + if (!storageInterface.isLoaded() || !storageInterface.isStillValid(getBuilding())) { continue; } @@ -257,13 +257,13 @@ private AbstractStorageBlockInterface getPositionOfStorageBlockWithSimilarItemSt * @return the interface of this chest. */ @Nullable - private AbstractStorageBlockInterface searchMostEmptyStorageBlock() + private AbstractStorageBlock searchMostEmptyStorageBlock() { int freeSlots = 0; - AbstractStorageBlockInterface emptiestChest = null; - for (@NotNull final AbstractStorageBlockInterface storageInterface : getBuilding().getContainers()) + AbstractStorageBlock emptiestChest = null; + for (@NotNull final AbstractStorageBlock storageInterface : getBuilding().getContainers()) { - if (!storageInterface.isStillValid()) + if (!storageInterface.isStillValid(getBuilding())) { continue; } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java similarity index 65% rename from src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java rename to src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java index d9fb737c43a..118e59124b6 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlockInterface.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java @@ -1,24 +1,14 @@ package com.minecolonies.core.tileentities.storageblocks; -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; -import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.function.Predicate; - /** * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) */ -public class ColonyBuildingStorageBlockInterface extends RackStorageBlockInterface +public class ColonyBuildingStorageBlock extends RackStorageBlock { /** * Constructor @@ -26,7 +16,7 @@ public class ColonyBuildingStorageBlockInterface extends RackStorageBlockInterfa * @param pos The position of the target storage block * @param world The level the storage block is in */ - public ColonyBuildingStorageBlockInterface(BlockPos pos, Level world) + public ColonyBuildingStorageBlock(BlockPos pos, Level world) { super(pos, world); diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java new file mode 100644 index 00000000000..b0c6cd12cdf --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java @@ -0,0 +1,157 @@ +package com.minecolonies.core.tileentities.storageblocks; + +import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.util.InventoryUtils; +import com.minecolonies.core.tileentities.TileEntityRack; +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.function.Predicate; + +/** + * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) + */ +public class RackStorageBlock extends AbstractStorageBlock +{ + public RackStorageBlock(BlockPos pos, Level world) + { + super(pos, world); + + BlockEntity targetBlockEntity = world.getBlockEntity(pos); + + if (!(targetBlockEntity instanceof TileEntityRack)) + { + throw new IllegalArgumentException("The block at the target position must be an instance of TileEntityRack"); + } + } + + @Override + public boolean isStillValid(final IBuilding building) + { + return getRack().isPresent(); + } + + @Override + public int getUpgradeLevel() + { + return getRack().map(TileEntityRack::getUpgradeSize).orElse(0); + } + + @Override + public void increaseUpgradeLevel() + { + getRack().ifPresent(TileEntityRack::upgradeRackSize); + } + + @Override + public int getItemCount(final ItemStorage storage) + { + return getRack().map(rack -> rack.getCount(storage)).orElse(0); + } + + @Override + public int getItemCount(final Predicate predicate) + { + return getRack().map(rack -> rack.getItemCount(predicate)).orElse(0); + } + + @Override + public int getFreeSlots() + { + return getRack().map(TileEntityRack::getFreeSlots).orElse(0); + } + + /** + * Gets all items and their count from the storage block. + * + * @return The items and their count + */ + @Override + public Map getAllContent() + { + return getRack().map(TileEntityRack::getAllContent).orElse(new HashMap<>()); + } + + /** + * Gets the matching count for a specific item stack and can ignore NBT and damage as well. + * + * @param stack The stack to check against + * @param ignoreDamageValue Whether to ignore damage + * @param ignoreNBT Whether to ignore nbt data + * @return The count of matching items in the storageblock + */ + @Override + public int getItemCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) + { + return getRack().map(rack -> rack.getCount(stack, ignoreDamageValue, ignoreNBT)).orElse(0); + } + + /** + * Whether there are any items in the target storageblock + * + * @return Whether the storageblock is empty + */ + @Override + public boolean isEmpty() + { + return getRack().map(TileEntityRack::isEmpty).orElse(true); + } + + /** + * Return whether the storageblock contains a matching item stack + * + * @param stack The item type to compare + * @param count The amount that must be present + * @param ignoreDamage Whether the items should have matching damage values + * @return Whether the storageblock contains the match + */ + @Override + public boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage) + { + return getRack().map(rack -> rack.hasItemStack(stack, count, ignoreDamage)).orElse(false); + } + + /** + * Return whether the storageblock contains any items matching the predicate + * + * @param predicate The predicate to check against + * @return Whether the storageblock has any matches + */ + @Override + public boolean hasItemStack(Predicate predicate) + { + return getRack().map(rack -> rack.hasItemStack(predicate)).orElse(false); + } + + /** + * Get any matching item stacks within the storage block. + * + * @param predicate The predicate to test against + * @return The list of matching item stacks + */ + @Override + public List getMatching(final @NotNull Predicate predicate) + { + return getRack().map(rack -> InventoryUtils.filterItemHandler(rack.getInventory(), predicate)).orElse(new ArrayList<>()); + } + + /** + * Get the target tile entity as the TileEntityRack if it doesn't exist + * + * @return The target TileEntityRack if it exists + */ + private Optional getRack() + { + BlockEntity targetBlockEntity = level.getBlockEntity(targetPos); + if (!(targetBlockEntity instanceof TileEntityRack)) { + return Optional.empty(); + } + return Optional.of((TileEntityRack) targetBlockEntity); + } +} diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java deleted file mode 100644 index c251a99ea06..00000000000 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlockInterface.java +++ /dev/null @@ -1,245 +0,0 @@ -package com.minecolonies.core.tileentities.storageblocks; - -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlockInterface; -import com.minecolonies.api.util.InventoryUtils; -import com.minecolonies.api.util.ItemStackUtils; -import com.minecolonies.core.tileentities.TileEntityRack; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.function.Predicate; - -/** - * A StorageBlockInterface that works specifically for TileEntityRacks (not AbstractTileEntityRacks) - */ -public class RackStorageBlockInterface extends AbstractStorageBlockInterface -{ - public RackStorageBlockInterface(BlockPos pos, Level world) - { - super(pos, world); - - BlockEntity targetBlockEntity = world.getBlockEntity(pos); - - if (!(targetBlockEntity instanceof TileEntityRack)) - { - throw new IllegalArgumentException("The block at the target position must be an instance of TileEntityRack"); - } - } - - @Override - public boolean isStillValid() - { - return getRack().isPresent(); - } - - @Override - public boolean shouldAutomaticallyAdd(final IBuilding building) - { - return true; - } - - @Override - public void setInWarehouse(final boolean inWarehouse) - { - getRack().ifPresent(rack -> rack.setInWarehouse(inWarehouse)); - } - - @Override - public int getUpgradeLevel() - { - return getRack().map(TileEntityRack::getUpgradeSize).orElse(0); - } - - @Override - public void increaseUpgradeLevel() - { - getRack().ifPresent(TileEntityRack::upgradeRackSize); - } - - @Override - public int getCount(final ItemStorage storage) - { - return getRack().map(rack -> rack.getCount(storage)).orElse(0); - } - - @Override - public int getItemCount(final Predicate predicate) - { - return getRack().map(rack -> rack.getItemCount(predicate)).orElse(0); - } - - @Override - public int getFreeSlots() - { - return getRack().map(TileEntityRack::getFreeSlots).orElse(0); - } - - /** - * Gets all items and their count from the storage block. - * - * @return The items and their count - */ - @Override - public Map getAllContent() - { - return getRack().map(TileEntityRack::getAllContent).orElse(new HashMap<>()); - } - - /** - * Gets the matching count for a specific item stack and can ignore NBT and damage as well. - * - * @param stack The stack to check against - * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data - * @return The count of matching items in the storageblock - */ - @Override - public int getCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT) - { - return getRack().map(rack -> rack.getCount(stack, ignoreDamageValue, ignoreNBT)).orElse(0); - } - - /** - * Whether there are any items in the target storageblock - * - * @return Whether the storageblock is empty - */ - @Override - public boolean isEmpty() { - return getRack().map(TileEntityRack::isEmpty).orElse(true); - } - - /** - * Return whether the storageblock contains a matching item stack - * - * @param stack The item type to compare - * @param count The amount that must be present - * @param ignoreDamage Whether the items should have matching damage values - * @return Whether the storageblock contains the match - */ - @Override - public boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage) { - return getRack().map(rack -> rack.hasItemStack(stack, count, ignoreDamage)).orElse(false); - } - - /** - * Return whether the storageblock contains any items matching the predicate - * - * @param predicate The predicate to check against - * @return Whether the storageblock has any matches - */ - @Override - public boolean hasItemStack(Predicate predicate) { - return getRack().map(rack -> rack.hasItemStack(predicate)).orElse(false); - } - - /** - * Sets the block position of the building this storage belongs to - * - * @param pos The position of the building - */ - @Override - public void setBuildingPos(BlockPos pos) { - getRack().ifPresent(rack -> rack.setBuildingPos(pos)); - } - - /** - * Add an item stack to this storage block. - * - * @param stack The stack to add - * @return Whether the addition was successful - */ - @Override - public boolean storeItemStack(final @NotNull ItemStack stack) - { - return getRack().map(rack -> InventoryUtils.addItemStackToItemHandler(rack.getInventory(), stack)).orElse(false); - } - - /** - * Get any matching item stacks within the storage block. - * - * @param predicate The predicate to test against - * @return The list of matching item stacks - */ - @Override - public List getMatching(final @NotNull Predicate predicate) - { - return getRack().map(rack -> InventoryUtils.filterItemHandler(rack.getInventory(), predicate)).orElse(new ArrayList<>()); - } - - /** - * Force stack to the storage block. - * - * @param itemStack ItemStack to add. - * @param itemStackToKeepPredicate The {@link Predicate} that determines which ItemStacks to keep in the inventory. Return false to replace. - * @return itemStack which has been replaced, null if none has been replaced. - */ - @Override - public @Nullable ItemStack forceAddItemStack(final @NotNull ItemStack itemStack, final @NotNull Predicate itemStackToKeepPredicate) - { - return getRack().map(rack -> InventoryUtils.forceItemStackToItemHandler(rack.getInventory(), itemStack, itemStackToKeepPredicate)).orElse(null); - } - - /** - * Method to transfer an ItemStacks from the given source {@link IItemHandler} to the Storage Block. - * - * @param targetHandler The {@link IItemHandler} that works as receiver. - * @param predicate the predicate for the stack. - * @return true when the swap was successful, false when not. - */ - @Override - public boolean transferItemStackFromStorageIntoNextBestSlot(final @NotNull IItemHandler targetHandler, final Predicate predicate) - { - return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(rack.getInventory(), predicate, targetHandler)).orElse(false); - } - - /** - * Method to swap the ItemStacks from storage to the given target {@link IItemHandler}. - * - * @param targetHandler The {@link IItemHandler} that works as Target. - * @param stackPredicate The type of stack to pickup. - * @param count how much to pick up. - * @return True when the swap was successful, false when not. - */ - @Override - public boolean transferItemStackFromStorageIntoNextFreeSlot(final @NotNull IItemHandler targetHandler, final @NotNull Predicate stackPredicate, final int count) - { - return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextFreeSlotFromItemHandler(rack.getInventory(), stackPredicate, count, targetHandler)).orElse(false); - } - - /** - * Method to swap the ItemStacks from the given source {@link IItemHandler} to storage. Trying to merge existing itemStacks if possible. - * - * @param sourceHandler The {@link IItemHandler} that works as Source. - * @param sourceIndex The index of the slot that is being extracted from. - * @return True when the swap was successful, false when not. - */ - @Override - public boolean transferFromIndexToStorageIntoNextBestSlot(final @NotNull IItemHandler sourceHandler, final int sourceIndex) - { - return getRack().map(rack -> InventoryUtils.transferItemStackIntoNextBestSlotInItemHandler(sourceHandler, sourceIndex, rack.getInventory())).orElse(false); - } - - /** - * Get the target tile entity as the TileEntityRack if it doesn't exist - * - * @return The target TileEntityRack if it exists - */ - private Optional getRack() { - BlockEntity targetBlockEntity = level.getBlockEntity(targetPos); - if (!(targetBlockEntity instanceof TileEntityRack)) { - return Optional.empty(); - } - return Optional.of((TileEntityRack) targetBlockEntity); - } -} From 6a9c56de38286993e3dbc31e32e0bdd8dc53aed9 Mon Sep 17 00:00:00 2001 From: wmaxlees Date: Mon, 30 Sep 2024 15:47:28 -0600 Subject: [PATCH 15/17] Rough idea. Submitting before switching computers --- .../minecolonies/api/IMinecoloniesAPI.java | 3 + .../api/MinecoloniesAPIProxy.java | 7 ++ .../api/colony/IColonyManager.java | 1 + .../api/colony/buildings/IBuilding.java | 2 +- .../inventory/container/ContainerRack.java | 5 +- .../tileentities/AbstractTileEntityRack.java | 10 +-- .../storageblocks/AbstractStorageBlock.java | 12 +++ .../IStorageBlockNotificationManager.java | 23 ++++++ .../storageblocks/InsertNotifier.java | 25 ++++++ .../apiimp/CommonMinecoloniesAPIImpl.java | 11 ++- .../com/minecolonies/core/MineColonies.java | 6 ++ .../core/colony/ColonyManager.java | 2 + .../colony/buildings/AbstractBuilding.java | 3 +- .../tileentities/TileEntityWareHouse.java | 1 - .../storageblocks/RackStorageBlock.java | 7 ++ .../StorageBlockNotificationManager.java | 82 +++++++++++++++++++ 16 files changed, 187 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java create mode 100644 src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java diff --git a/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java b/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java index b76f95bb137..18bec1744e1 100755 --- a/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java +++ b/src/main/java/com/minecolonies/api/IMinecoloniesAPI.java @@ -27,6 +27,7 @@ import com.minecolonies.api.research.ModResearchCostTypes.ResearchCostType; import com.minecolonies.api.research.effects.registry.ResearchEffectEntry; import com.minecolonies.api.research.registry.ResearchRequirementEntry; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.NewRegistryEvent; @@ -104,4 +105,6 @@ static IMinecoloniesAPI getInstance() IForgeRegistry getEquipmentTypeRegistry(); IForgeRegistry getStorageBlockRegistry(); + + IStorageBlockNotificationManager getStorageBlockNotificationManager(); } diff --git a/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java b/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java index 940ad5d3bb7..a638ad7057a 100755 --- a/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java +++ b/src/main/java/com/minecolonies/api/MinecoloniesAPIProxy.java @@ -27,6 +27,7 @@ import com.minecolonies.api.research.ModResearchCostTypes.ResearchCostType; import com.minecolonies.api.research.effects.registry.ResearchEffectEntry; import com.minecolonies.api.research.registry.ResearchRequirementEntry; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.NewRegistryEvent; @@ -242,4 +243,10 @@ public IForgeRegistry getStorageBlockRegistry() { return apiInstance.getStorageBlockRegistry(); } + + @Override + public IStorageBlockNotificationManager getStorageBlockNotificationManager() + { + return apiInstance.getStorageBlockNotificationManager(); + } } diff --git a/src/main/java/com/minecolonies/api/colony/IColonyManager.java b/src/main/java/com/minecolonies/api/colony/IColonyManager.java index b6b48f13f49..3ea728c7520 100755 --- a/src/main/java/com/minecolonies/api/colony/IColonyManager.java +++ b/src/main/java/com/minecolonies/api/colony/IColonyManager.java @@ -12,6 +12,7 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; import net.minecraftforge.event.TickEvent; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java b/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java index 80fddcd26e0..0244452d869 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java @@ -38,7 +38,7 @@ import static com.minecolonies.api.util.constant.EquipmentLevelConstants.BASIC_TOOL_LEVEL; import static com.minecolonies.api.util.constant.EquipmentLevelConstants.TOOL_LEVEL_MAXIMUM; -public interface IBuilding extends IBuildingContainer, IModuleContainer, IRequestResolverProvider, IRequester, ISchematicProvider, InsertNotifier.IInsertListener +public interface IBuilding extends IBuildingContainer, IModuleContainer, IRequestResolverProvider, IRequester, ISchematicProvider { /** * Minimal level to ask for wood tools. (WOOD_HUT_LEVEL + 1 == stone) diff --git a/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java b/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java index ed3de383f20..5f6a92b8f1e 100755 --- a/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java +++ b/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java @@ -4,6 +4,7 @@ import com.minecolonies.api.blocks.types.RackType; import com.minecolonies.api.inventory.ModContainers; import com.minecolonies.api.tileentities.AbstractTileEntityRack; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.util.ItemStackUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; @@ -227,11 +228,11 @@ protected boolean moveItemStackTo(final ItemStack stack, final int startIndex, f private void updateRacks(final ItemStack stack) { rack.updateItemStorage(); - rack.updateWarehouseIfAvailable(stack); + IStorageBlockNotificationManager.getInstance().notifyInsert(rack.getBlockPos(), stack); if (neighborRack != null) { neighborRack.updateItemStorage(); - neighborRack.updateWarehouseIfAvailable(stack); + IStorageBlockNotificationManager.getInstance().notifyInsert(neighborRack.getBlockPos(), stack); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java index c65bb254e90..70be9fc82e0 100755 --- a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java +++ b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java @@ -1,11 +1,7 @@ package com.minecolonies.api.tileentities; -import com.minecolonies.api.colony.IColony; -import com.minecolonies.api.colony.IColonyManager; -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.colony.requestsystem.requestable.IDeliverable; import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.util.ItemStackUtils; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import net.minecraft.core.BlockPos; import net.minecraft.world.MenuProvider; import net.minecraft.world.item.ItemStack; @@ -80,7 +76,7 @@ public void setStackInSlot(final int slot, final @Nonnull ItemStack stack) { onContentsChanged(slot); } - updateWarehouseIfAvailable(stack); + IStorageBlockNotificationManager.getInstance().notifyInsert(worldPosition, stack); } @Nonnull @@ -90,7 +86,7 @@ public ItemStack insertItem(final int slot, @Nonnull final ItemStack stack, fina final ItemStack result = super.insertItem(slot, stack, simulate); if ((result.isEmpty() || result.getCount() < stack.getCount()) && !simulate) { - updateWarehouseIfAvailable(stack); + IStorageBlockNotificationManager.getInstance().notifyInsert(worldPosition, stack); } return result; } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java index 831e1400acc..9506101af47 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java @@ -71,6 +71,15 @@ public void addInsertListener(BlockPos listenerPos) insertNotifier.addInsertListener(listenerPos); } + /** + * Notify the storage block wrapper that the target entity + * has updated. + */ + public void notifyUpdate() + { + insertNotifier.notifyUpdate(targetPos); + } + /** * Gets the current upgrade level of the storageblock * @@ -153,6 +162,9 @@ public boolean insertFullStack(final ItemStack stack, final boolean simulate) return result; } + + public abstract boolean supportsItemInsertNotification(); + /** * Gets the amount of a particular item contained in the storageblock * diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java new file mode 100644 index 00000000000..99342ad2206 --- /dev/null +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java @@ -0,0 +1,23 @@ +package com.minecolonies.api.tileentities.storageblocks; + +import com.minecolonies.api.IMinecoloniesAPI; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; + +public interface IStorageBlockNotificationManager +{ + public static IStorageBlockNotificationManager getInstance() + { + return IMinecoloniesAPI.getInstance().getStorageBlockNotificationManager(); + } + + void registerNewTarget(final AbstractStorageBlock target, final Level level); + + void addListener(final BlockPos targetPos, final BlockPos listenerPos); + + void notifyInsert(final BlockPos targetPos, final ItemStack insertedStack); + + void notifyUpdate(final BlockPos targetPos); +} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java index dc455a22941..117f4185ded 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java @@ -77,6 +77,23 @@ public void notifyInsert(final BlockPos insertPos, final ItemStack itemStack) } } + public void notifyUpdate(final BlockPos insertPos) + { + if (level == null) + { + return; + } + + for (BlockPos pos : this.insertListeners) + { + BlockEntity entity = level.getBlockEntity(pos); + if (entity instanceof IInsertListener listener) + { + listener.onUpdate(insertPos); + } + } + } + /** * Serialize the InsertNotifier to NBT data. * @@ -117,5 +134,13 @@ public interface IInsertListener * @param itemStack The item stack that was inserted. */ void onInsert(BlockPos insertPos, ItemStack itemStack); + + /** + * The function that will be called to notify the listener + * that any block update has occurred. + * + * @param insertPos The location of the storage where the update occurred. + */ + void onUpdate(BlockPos blockPos); } } diff --git a/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java b/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java index 9e2cd755708..fdc2eb3b168 100755 --- a/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java +++ b/src/main/java/com/minecolonies/apiimp/CommonMinecoloniesAPIImpl.java @@ -29,6 +29,7 @@ import com.minecolonies.api.research.ModResearchCostTypes.ResearchCostType; import com.minecolonies.api.research.effects.registry.ResearchEffectEntry; import com.minecolonies.api.research.registry.ResearchRequirementEntry; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.core.MineColonies; @@ -40,6 +41,7 @@ import com.minecolonies.core.entity.mobs.registry.MobAIRegistry; import com.minecolonies.core.entity.pathfinding.registry.PathNavigateRegistry; import com.minecolonies.core.research.GlobalResearchTree; +import com.minecolonies.core.tileentities.storageblocks.StorageBlockNotificationManager; import com.minecolonies.core.util.FurnaceRecipes; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.registries.IForgeRegistry; @@ -81,7 +83,8 @@ public class CommonMinecoloniesAPIImpl implements IMinecoloniesAPI private IForgeRegistry questDialogueAnswerRegistry; private IForgeRegistry happinessFactorTypeRegistry; private IForgeRegistry happinessFunctionRegistry; - private IForgeRegistry storageBlockRegistry; + private IForgeRegistry storageBlockRegistry; + private IStorageBlockNotificationManager storageBlockNotificationManager = new StorageBlockNotificationManager(); @Override @NotNull @@ -407,5 +410,11 @@ public IForgeRegistry getStorageBlockRegistry() { return storageBlockRegistry; } + + @Override + public IStorageBlockNotificationManager getStorageBlockNotificationManager() + { + return storageBlockNotificationManager; + } } diff --git a/src/main/java/com/minecolonies/core/MineColonies.java b/src/main/java/com/minecolonies/core/MineColonies.java index 5e122b1168a..e21b2286d2a 100755 --- a/src/main/java/com/minecolonies/core/MineColonies.java +++ b/src/main/java/com/minecolonies/core/MineColonies.java @@ -19,6 +19,7 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.loot.ModLootConditions; import com.minecolonies.api.sounds.ModSoundEvents; +import com.minecolonies.api.tileentities.AbstractTileEntityWareHouse; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.Constants; @@ -37,6 +38,8 @@ import com.minecolonies.core.recipes.FoodIngredient; import com.minecolonies.core.recipes.PlantIngredient; import com.minecolonies.core.structures.MineColoniesStructures; +import com.minecolonies.core.tileentities.storageblocks.StorageBlockNotificationManager; + import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.capabilities.Capability; @@ -46,6 +49,7 @@ import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.event.TagsUpdatedEvent; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; +import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; @@ -140,6 +144,8 @@ public MineColonies() SurvivalBlueprintHandlers.registerHandler(new SurvivalHandler()); SurvivalBlueprintHandlers.registerHandler(new SuppliesHandler()); + MinecraftForge.EVENT_BUS.addListener(EventPriority.NORMAL, StorageBlockNotificationManager::handleNeighborUpdate); + logIncompatibilities(); } diff --git a/src/main/java/com/minecolonies/core/colony/ColonyManager.java b/src/main/java/com/minecolonies/core/colony/ColonyManager.java index 073006e0c75..4d8fb2a4d7e 100755 --- a/src/main/java/com/minecolonies/core/colony/ColonyManager.java +++ b/src/main/java/com/minecolonies/core/colony/ColonyManager.java @@ -31,6 +31,8 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; +import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.TickEvent; diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java index f59865f0eb3..51f6f2a1094 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java @@ -38,6 +38,7 @@ import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.Constants; import com.minecolonies.api.util.constant.TypeConstants; @@ -99,7 +100,7 @@ * blocks. */ @SuppressWarnings({"squid:S2390", "PMD.ExcessiveClassLength"}) -public abstract class AbstractBuilding extends AbstractBuildingContainer +public abstract class AbstractBuilding extends AbstractBuildingContainer implements InsertNotifier.IInsertListener { /** * Breeding setting. diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java index dd8d4976488..eca4270358b 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java @@ -33,7 +33,6 @@ public class TileEntityWareHouse extends AbstractTileEntityWareHouse public TileEntityWareHouse(final BlockPos pos, final BlockState state) { super(MinecoloniesTileEntities.WAREHOUSE.get(), pos, state); - inWarehouse = true; } @Override diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java index b0c6cd12cdf..6df38019d29 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java @@ -1,6 +1,7 @@ package com.minecolonies.core.tileentities.storageblocks; import com.minecolonies.api.colony.buildings.IBuilding; +import com.minecolonies.api.colony.buildings.views.IBuildingView; import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.util.InventoryUtils; @@ -154,4 +155,10 @@ private Optional getRack() } return Optional.of((TileEntityRack) targetBlockEntity); } + + @Override + public boolean supportsItemInsertNotification() + { + return true; + } } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java new file mode 100644 index 00000000000..d077dbe073f --- /dev/null +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java @@ -0,0 +1,82 @@ +package com.minecolonies.core.tileentities.storageblocks; + +import java.util.HashMap; +import java.util.Map; + +import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; +import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.event.level.BlockEvent; + +public class StorageBlockNotificationManager implements IStorageBlockNotificationManager +{ + + public static void handleNeighborUpdate(BlockEvent.NeighborNotifyEvent event) + { + BlockEntity entity = event.getLevel().getBlockEntity(event.getPos()); + if (entity == null) + { + return; + } + + IStorageBlockNotificationManager.getInstance().notifyUpdate(event.getPos()); + } + + private Map insertNotifiers = new HashMap<>(); + private Map updateNotifiers = new HashMap<>(); + + @Override + public void addListener(BlockPos targetPos, BlockPos listenerPos) + { + if (insertNotifiers.containsKey(targetPos)) + { + insertNotifiers.get(targetPos).addInsertListener(listenerPos); + } + + if (updateNotifiers.containsKey(targetPos)) + { + updateNotifiers.get(targetPos).addInsertListener(listenerPos); + } + } + + + @Override + public void registerNewTarget(final AbstractStorageBlock target, final Level level) + { + BlockPos targetPos = target.getPosition(); + if (target.supportsItemInsertNotification()) + { + insertNotifiers.put(targetPos, new InsertNotifier(level)); + } + else + { + updateNotifiers.put(targetPos, new InsertNotifier(level)); + } + } + + + @Override + public void notifyInsert(BlockPos targetPos, ItemStack insertedStack) + { + if (insertNotifiers.containsKey(targetPos)) + { + insertNotifiers.get(targetPos).notifyInsert(targetPos, insertedStack); + } + } + + + @Override + public void notifyUpdate(BlockPos targetPos) + { + if (updateNotifiers.containsKey(targetPos)) + { + updateNotifiers.get(targetPos).notifyUpdate(targetPos); + } + } + +} From 657912eaf6024dae4f323ed597bfcedfd06d9614 Mon Sep 17 00:00:00 2001 From: wmaxlees Date: Wed, 2 Oct 2024 14:13:20 -0700 Subject: [PATCH 16/17] Input event notifications now work. Need to clean up request system interactions now --- .../event/StorageBlockStackInsertEvent.java | 38 +++++ .../inventory/container/ContainerRack.java | 6 +- .../tileentities/AbstractTileEntityRack.java | 10 +- .../storageblocks/AbstractStorageBlock.java | 156 ++++++++++++------ .../IStorageBlockNotificationManager.java | 33 +++- .../storageblocks/InsertNotifier.java | 56 +------ .../storageblocks/ModStorageBlocks.java | 14 +- .../registry/StorageBlockEntry.java | 11 +- .../minecolonies/api/util/InventoryUtils.java | 77 +++++++-- .../api/util/constant/NbtTagConstants.java | 3 + .../com/minecolonies/core/MineColonies.java | 7 +- .../client/gui/WindowHutAllInventory.java | 4 +- .../core/client/gui/WindowsBarracksSpies.java | 2 +- .../buildings/AbstractBuildingContainer.java | 50 ++++-- .../buildings/views/AbstractBuildingView.java | 2 +- .../workerbuildings/BuildingWareHouse.java | 16 +- .../service/EntityAIWorkDeliveryman.java | 2 +- .../tileentities/TileEntityWareHouse.java | 12 +- .../ColonyBuildingStorageBlock.java | 7 +- .../storageblocks/RackStorageBlock.java | 141 +++++++++++++++- .../StorageBlockNotificationManager.java | 70 +++----- 21 files changed, 503 insertions(+), 214 deletions(-) create mode 100644 src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java diff --git a/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java b/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java new file mode 100644 index 00000000000..625c8b05d6f --- /dev/null +++ b/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java @@ -0,0 +1,38 @@ +package com.minecolonies.api.colony.event; + +import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.eventbus.api.Event; + +public class StorageBlockStackInsertEvent extends Event +{ + BlockPos storageBlockPos; + + ResourceKey dimension; + + ItemStack stack; + + public StorageBlockStackInsertEvent(ResourceKey dimension, BlockPos pos, ItemStack stack) + { + this.storageBlockPos = pos; + this.dimension = dimension; + this.stack = stack; + } + + public BlockPos getPosition() + { + return storageBlockPos; + } + + public ItemStack getInsertedStack() + { + return stack; + } + + public ResourceKey getDimension() + { + return dimension; + } +} diff --git a/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java b/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java index 5f6a92b8f1e..11ebf75a0f4 100755 --- a/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java +++ b/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java @@ -2,6 +2,7 @@ import com.minecolonies.api.blocks.AbstractBlockMinecoloniesRack; import com.minecolonies.api.blocks.types.RackType; +import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import com.minecolonies.api.inventory.ModContainers; import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; @@ -15,6 +16,7 @@ import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.wrapper.CombinedInvWrapper; @@ -228,11 +230,11 @@ protected boolean moveItemStackTo(final ItemStack stack, final int startIndex, f private void updateRacks(final ItemStack stack) { rack.updateItemStorage(); - IStorageBlockNotificationManager.getInstance().notifyInsert(rack.getBlockPos(), stack); + MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(rack.getLevel().dimension(), rack.getBlockPos(), stack)); if (neighborRack != null) { neighborRack.updateItemStorage(); - IStorageBlockNotificationManager.getInstance().notifyInsert(neighborRack.getBlockPos(), stack); + MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(rack.getLevel().dimension(), rack.getBlockPos(), stack)); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java index 70be9fc82e0..2c56861d76b 100755 --- a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java +++ b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java @@ -1,13 +1,14 @@ package com.minecolonies.api.tileentities; import com.minecolonies.api.crafting.ItemStorage; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; +import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import net.minecraft.core.BlockPos; import net.minecraft.world.MenuProvider; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.ItemStackHandler; import org.jetbrains.annotations.NotNull; @@ -76,7 +77,10 @@ public void setStackInSlot(final int slot, final @Nonnull ItemStack stack) { onContentsChanged(slot); } - IStorageBlockNotificationManager.getInstance().notifyInsert(worldPosition, stack); + if (level != null) + { + MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(level.dimension(), worldPosition, stack)); + } } @Nonnull @@ -86,7 +90,7 @@ public ItemStack insertItem(final int slot, @Nonnull final ItemStack stack, fina final ItemStack result = super.insertItem(slot, stack, simulate); if ((result.isEmpty() || result.getCount() < stack.getCount()) && !simulate) { - IStorageBlockNotificationManager.getInstance().notifyInsert(worldPosition, stack); + MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(level.dimension(), worldPosition, stack)); } return result; } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java index 9506101af47..4f119b0fa2f 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java @@ -1,20 +1,29 @@ package com.minecolonies.api.tileentities.storageblocks; -import com.minecolonies.api.colony.IColony; -import com.minecolonies.api.colony.IColonyManager; import com.minecolonies.api.colony.buildings.IBuilding; import com.minecolonies.api.colony.buildings.views.IBuildingView; -import com.minecolonies.api.colony.requestsystem.requestable.IDeliverable; +import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.util.BlockPosUtil; -import com.minecolonies.api.util.ItemStackUtils; +import com.minecolonies.api.util.Log; import com.minecolonies.api.util.WorldUtil; +import com.minecolonies.core.tileentities.storageblocks.RackStorageBlock; + import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.server.ServerLifecycleHooks; + import org.jetbrains.annotations.NotNull; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.function.Predicate; @@ -32,52 +41,25 @@ public abstract class AbstractStorageBlock protected BlockPos targetPos; /** - * The level that the block entity is located in. + * The dimension that the block entity is located in. */ - protected final Level level; + protected ResourceKey dimension; /** * The level that the storage block has been upgraded to. */ protected int upgradeLevel = 0; - /** - * The notifier used to let other blocks know when this - * storageblock has items inserted. - */ - protected InsertNotifier insertNotifier; - /** * Constructor * * @param targetPos The location of the block * @param level The world the block is in */ - public AbstractStorageBlock(final BlockPos targetPos, Level level) + public AbstractStorageBlock(final BlockPos targetPos, ResourceKey dimension) { this.targetPos = targetPos; - this.level = level; - insertNotifier = new InsertNotifier(level); - } - - /** - * Add a new listener for when items are inserted - * to this storage block. - * - * @param listenerPos The position of the listener entity - */ - public void addInsertListener(BlockPos listenerPos) - { - insertNotifier.addInsertListener(listenerPos); - } - - /** - * Notify the storage block wrapper that the target entity - * has updated. - */ - public void notifyUpdate() - { - insertNotifier.notifyUpdate(targetPos); + this.dimension = dimension; } /** @@ -108,6 +90,11 @@ public final BlockPos getPosition() return targetPos; } + public final ResourceKey getDimension() + { + return dimension; + } + /** * Whether the block is currently loaded. * @@ -115,7 +102,8 @@ public final BlockPos getPosition() */ public final boolean isLoaded() { - return WorldUtil.isBlockLoaded(level, targetPos); + + return WorldUtil.isBlockLoaded(getLevel(), targetPos); } /** @@ -128,7 +116,8 @@ public CompoundTag serializeNBT() CompoundTag result = new CompoundTag(); BlockPosUtil.write(result, TAG_POS, targetPos); - result.put(TAG_INPUT_LISTENER, insertNotifier.serializeToNBT()); + result.putString(TAG_DIMENSION, dimension.location().toString()); + result.putString(TAG_STORAGE_BLOCK_TYPE, getStorageBlockClass().getName()); return result; } @@ -138,31 +127,77 @@ public CompoundTag serializeNBT() * * @param nbt The NBT data for the block */ - public void read(final CompoundTag nbt) + public static AbstractStorageBlock fromNBT(final CompoundTag nbt) { - targetPos = BlockPosUtil.read(nbt, TAG_POS); - insertNotifier.read(nbt.getCompound(TAG_INPUT_LISTENER)); + BlockPos targetPos = BlockPosUtil.read(nbt, TAG_POS); + ResourceKey dimension = ResourceKey.create(Registries.DIMENSION, new ResourceLocation(nbt.getString(TAG_DIMENSION))); + String className = nbt.getString(TAG_STORAGE_BLOCK_TYPE); + + Class clazz = RackStorageBlock.class; + try { + clazz = Class.forName(className).asSubclass(AbstractStorageBlock.class); + } catch (ClassNotFoundException e) { + Log.getLogger().error("Could not find class {}, defaulting to AbstractStorageBlock", className); + } + + try { + Constructor constructor = clazz.getDeclaredConstructor(BlockPos.class, ResourceKey.class); + Log.getLogger().info(constructor); + return constructor.newInstance(targetPos, dimension); + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException e) { + Log.getLogger().error("Failed to initialize StorageBlock at {}: {}", targetPos, e); + + if (e instanceof InvocationTargetException invTargetException) + { + Log.getLogger().error("Underlying exception: {}", invTargetException.getTargetException()); + invTargetException.getTargetException().printStackTrace(); + } + // for (StackTraceElement line : e.getStackTrace()) + // { + // Log.getLogger().info(line.toString()); + // } + } + + return null; } /** * Adds the full item stack to the first available slot in * the storage block. * + * @param stack The ItemStack to insert * @return if the full transfer was successful */ - public boolean insertFullStack(final ItemStack stack, final boolean simulate) + public boolean insertFullStack(final ItemStack stack) { - final boolean result = insertFullStackImpl(stack, simulate); + final boolean result = insertFullStackImpl(stack); - if (result && !simulate) + if (result) { - insertNotifier.notifyInsert(targetPos, stack); + MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(dimension, targetPos, stack)); } return result; } - + /** + * Get the level from the storageblock's dimension + * + * @return The level this storage block is in + */ + protected Level getLevel() + { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + return server.levels.get(dimension); + } + + /** + * Whether the storage block will notify on item inserts or + * whether we need to rely on block updates. + * + * @return if the storage block notifies on item inserts + */ public abstract boolean supportsItemInsertNotification(); /** @@ -272,20 +307,39 @@ public boolean insertFullStack(final ItemStack stack, final boolean simulate) /** * Removes an item stack matching the given predicate from the storage block - * and returns it. Will only return if the stack has at least minCount stack size. + * and returns it. * - * @param predicate The predicate to match - * @param minCount The minimum count the stack size must be - * @param simulate If true, actually removes the item. + * @param itemStack The item stack to remove + * @param count The amount to remove + * @param simulate If true, actually remove the item. * @return The matching item stack, or ItemStack.EMPTY */ - public abstract ItemStack extractItem(final Predicate predicate, int minCount, boolean simulate); + public abstract ItemStack extractItem(final ItemStack itemStack, int count, boolean simulate); + + /** + * Finds the first ItemStack that matches the given predicate and returns it. Return + * null if it doesn't exist. + * + * @param predicate The predicate to test against + * @return The matching stack or else null + */ + public abstract ItemStack findFirstMatch(final Predicate predicate); /** * Adds the full item stack to the first available slot in * the storage block. * + * @param stack The ItemStack to insert * @return if the full transfer was successful */ - protected abstract boolean insertFullStackImpl(final ItemStack stack, final boolean simulate); + protected abstract boolean insertFullStackImpl(final ItemStack stack); + + + /** + * Get the class type of this storage block. Used for serialization and + * deserialization. + * + * @return The class type of this storage block. + */ + public abstract Class getStorageBlockClass(); } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java index 99342ad2206..afa25f753c8 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java @@ -1,23 +1,42 @@ package com.minecolonies.api.tileentities.storageblocks; import com.minecolonies.api.IMinecoloniesAPI; +import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; +/** + * The manager for letting blocks (particularly the Warehouse) when + * storage blocks are updated or items are inserted into them. + */ public interface IStorageBlockNotificationManager { + /** + * Get the singleton instance of the manager. + * + * @return The singleton instance + */ public static IStorageBlockNotificationManager getInstance() { return IMinecoloniesAPI.getInstance().getStorageBlockNotificationManager(); } - void registerNewTarget(final AbstractStorageBlock target, final Level level); + /** + * Register a new listener that wants to hear updates for a storage block + * at a specific position. + * + * @param dimension The dimension of the storage block + * @param targetPos The position of the storage block + * @param listenerPos The position of the listener + */ + void addListener(final ResourceKey dimension, final BlockPos targetPos, final BlockPos listenerPos); - void addListener(final BlockPos targetPos, final BlockPos listenerPos); - - void notifyInsert(final BlockPos targetPos, final ItemStack insertedStack); - - void notifyUpdate(final BlockPos targetPos); + /** + * Called whenever a storage block receives new items. + * + * @param event the data about the insert + */ + void onInsert(StorageBlockStackInsertEvent event); } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java index 117f4185ded..fd9cbe5a25f 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java @@ -1,13 +1,17 @@ package com.minecolonies.api.tileentities.storageblocks; +import com.minecolonies.api.util.Log; import com.minecolonies.api.util.NBTUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.server.ServerLifecycleHooks; import java.util.HashSet; import java.util.Set; @@ -25,22 +29,6 @@ public class InsertNotifier * to be notified when items are inserted into this StorageBlock. */ private final Set insertListeners = new HashSet<>(); - /** - * Level that the BlockEntity this InsertNotifier corresponds - * to is located in. - */ - Level level; - - /** - * Constructor - * - * @param level The level the block entity this insert notifier - * is located in. - */ - public InsertNotifier(Level level) - { - this.level = level; - } /** * Add a new listener to be notified on item inserts. @@ -60,16 +48,15 @@ public void addInsertListener(final BlockPos pos) * inserted. * @param itemStack The item stack that was inserted. */ - public void notifyInsert(final BlockPos insertPos, final ItemStack itemStack) + public void notifyInsert(final ResourceKey dimension, final BlockPos insertPos, final ItemStack itemStack) { - if (level == null) - { - return; - } - + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + Level level = server.getLevel(dimension); + Log.getLogger().info("Got a notifyInsert in InsertNotifier. Sharing event."); for (BlockPos pos : this.insertListeners) { BlockEntity entity = level.getBlockEntity(pos); + Log.getLogger().info("Sharing with {} which is {}", pos, entity); if (entity instanceof IInsertListener listener) { listener.onInsert(insertPos, itemStack); @@ -77,23 +64,6 @@ public void notifyInsert(final BlockPos insertPos, final ItemStack itemStack) } } - public void notifyUpdate(final BlockPos insertPos) - { - if (level == null) - { - return; - } - - for (BlockPos pos : this.insertListeners) - { - BlockEntity entity = level.getBlockEntity(pos); - if (entity instanceof IInsertListener listener) - { - listener.onUpdate(insertPos); - } - } - } - /** * Serialize the InsertNotifier to NBT data. * @@ -134,13 +104,5 @@ public interface IInsertListener * @param itemStack The item stack that was inserted. */ void onInsert(BlockPos insertPos, ItemStack itemStack); - - /** - * The function that will be called to notify the listener - * that any block update has occurred. - * - * @param insertPos The location of the storage where the update occurred. - */ - void onUpdate(BlockPos blockPos); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java index 9d88f43b65e..b2b979bdb68 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/ModStorageBlocks.java @@ -1,5 +1,6 @@ package com.minecolonies.api.tileentities.storageblocks; +import com.ldtteam.blockui.mod.Log; import com.minecolonies.api.MinecoloniesAPIProxy; import com.minecolonies.api.tileentities.storageblocks.registry.StorageBlockEntry; import com.minecolonies.api.util.constant.Constants; @@ -54,14 +55,19 @@ private ModStorageBlocks() /** * Tries to find a matching BlockInterface for the given BlockEntity * + * @param level The level the block is located in * @param pos The location of the block in the level - * @param world The level the block is located in * @return A StorageBlockInterface for the given BlockEntity if one exists. */ @Nullable - public static AbstractStorageBlock getStorageBlockInterface(BlockPos pos, Level world) + public static AbstractStorageBlock getStorageBlockInterface(Level level, BlockPos pos) { - BlockEntity blockEntity = world.getBlockEntity(pos); + if (level.isClientSide) + { + return null; + } + + BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity == null) { return null; @@ -71,7 +77,7 @@ public static AbstractStorageBlock getStorageBlockInterface(BlockPos pos, Level { if (entry.matches(blockEntity)) { - return entry.getStorageInterface().apply(pos, world); + return entry.getStorageInterface().apply(pos, level.dimension()); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java index 174a233fa29..d5614a95410 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/registry/StorageBlockEntry.java @@ -2,6 +2,7 @@ import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -29,7 +30,7 @@ public final class StorageBlockEntry /** * The interface that will be used to interact with the particular block. */ - private final BiFunction storageInterface; + private final BiFunction, AbstractStorageBlock> storageInterface; /** * Constructor @@ -38,7 +39,7 @@ public final class StorageBlockEntry * @param isStorageBlock The predicate to determine if a block is this storage block type * @param storageInterface The interface used to interact with the particular block */ - public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, BiFunction storageInterface) { + public StorageBlockEntry(ResourceLocation registryName, Predicate isStorageBlock, BiFunction, AbstractStorageBlock> storageInterface) { this.registryName = registryName; this.isStorageBlock = isStorageBlock; this.storageInterface = storageInterface; @@ -59,7 +60,7 @@ public boolean matches(final BlockEntity blockEntity) { * * @return The interface. */ - public BiFunction getStorageInterface() { + public BiFunction, AbstractStorageBlock> getStorageInterface() { return storageInterface; } @@ -90,7 +91,7 @@ public static class Builder { /** * The interface that will be used to interact with the particular block. */ - private BiFunction storageInterface; + private BiFunction, AbstractStorageBlock> storageInterface; /** * Set the registry name for the StorageBlockEntry being built. @@ -121,7 +122,7 @@ public Builder setIsStorageBlock(Predicate isStorageBlock) { * @param storageInterface The interface * @return this */ - public Builder setStorageInterface(BiFunction storageInterface) { + public Builder setStorageInterface(BiFunction, AbstractStorageBlock> storageInterface) { this.storageInterface = storageInterface; return this; } diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index f84c191ec40..da559e0c9a9 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -1741,6 +1741,59 @@ public static boolean transferXOfItemStackIntoNextFreeSlotInItemHandler( return false; } + /** + * Swap the ItemStack from the given source {@link AbstractStorageBlock} to the given target {@link IItemHandler}. + * + * @param sourceStorage The {@link AbstractStorageBlock} that works as Source. + * @param sourceIndex The index of the slot that is being extracted from. + * @param count the quantity. + * @param targetHandler The {@link IItemHandler} that works as Target. + * @return True when the swap was successful, false when not. + */ + public static boolean transferXOfItemStackIntoNextFreeSlotInItemHandler( + @NotNull final AbstractStorageBlock sourceStorage, + final ItemStack itemStack, + final int count, + @NotNull final IItemHandler targetHandler) + { + ItemStack sourceStack = sourceStorage.extractItem(itemStack, count, true); + + if (ItemStackUtils.isEmpty(sourceStack)) + { + return true; + } + + boolean success = false; + for (int i = 0; i < targetHandler.getSlots(); i++) + { + sourceStack = targetHandler.insertItem(i, sourceStack, true); + if (ItemStackUtils.isEmpty(sourceStack)) + { + success = true; + break; + } + } + + if (!success) + { + return false; + } + + sourceStack = sourceStorage.extractItem(itemStack, count, false); + + for (int i = 0; i < targetHandler.getSlots(); i++) + { + sourceStack = targetHandler.insertItem(i, sourceStack, false); + if (ItemStackUtils.isEmpty(sourceStack)) + { + return true; + } + } + + sourceStorage.insertFullStack(sourceStack); + return false; + } + /** * Method to swap the ItemStacks from the given source {@link IItemHandler} to the given target {@link IItemHandler}. Trying to merge existing itemStacks if possible. * @@ -3244,20 +3297,24 @@ public static boolean transferItemStackIntoNextFreeSlotInItemHandler( final int count, @NotNull final IItemHandler targetHandler) { - ItemStack itemStack = sourceStorage.extractItem(stackPredicate, count, true); + int totalCount = count; - if (itemStack.isEmpty()) + ItemStack targetStack = sourceStorage.findFirstMatch(stackPredicate); + for (; targetStack != null; targetStack = sourceStorage.findFirstMatch(stackPredicate)) { - return false; - } + final int localCount = Math.min(totalCount, targetStack.getCount()); + if (transferXOfItemStackIntoNextFreeSlotInItemHandler(sourceStorage, targetStack, localCount, targetHandler)) + { + totalCount -= localCount; + } - if (!InventoryUtils.addItemStackToItemHandler(targetHandler, itemStack)) - { - return false; + if (totalCount <= 0) + { + return true; + } } - sourceStorage.extractItem(stackPredicate, count, false); - return true; + return false; } /** @@ -3279,7 +3336,7 @@ public static boolean transferItemStackIntoNextBestSlotInStorage( return true; } - if (targetStorage.insertFullStack(sourceStack, false)) + if (targetStorage.insertFullStack(sourceStack)) { sourceHandler.extractItem(sourceIndex, Integer.MAX_VALUE, false); return true; diff --git a/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java b/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java index 47a9f5558e9..abbfda59509 100755 --- a/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java +++ b/src/main/java/com/minecolonies/api/util/constant/NbtTagConstants.java @@ -739,6 +739,9 @@ public final class NbtTagConstants public static final String TAG_INPUT_LISTENER = "inputlistener"; public static final String TAG_LISTENER_LOC = "listenerloc"; + public static final String TAG_STORAGE_BLOCK_TYPE = "storageblocktype"; + public static final String TAG_STORAGE_BLOCKS = "storageblocks"; + /** * Private constructor to hide the implicit one. */ diff --git a/src/main/java/com/minecolonies/core/MineColonies.java b/src/main/java/com/minecolonies/core/MineColonies.java index e21b2286d2a..f60df2947ec 100755 --- a/src/main/java/com/minecolonies/core/MineColonies.java +++ b/src/main/java/com/minecolonies/core/MineColonies.java @@ -6,6 +6,7 @@ import com.minecolonies.api.advancements.AdvancementTriggers; import com.minecolonies.api.colony.IChunkmanagerCapability; import com.minecolonies.api.colony.IColonyTagCapability; +import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import com.minecolonies.api.configuration.Configuration; import com.minecolonies.api.crafting.CountedIngredient; import com.minecolonies.api.creativetab.ModCreativeTabs; @@ -19,7 +20,7 @@ import com.minecolonies.api.equipment.ModEquipmentTypes; import com.minecolonies.api.loot.ModLootConditions; import com.minecolonies.api.sounds.ModSoundEvents; -import com.minecolonies.api.tileentities.AbstractTileEntityWareHouse; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.Constants; @@ -38,7 +39,6 @@ import com.minecolonies.core.recipes.FoodIngredient; import com.minecolonies.core.recipes.PlantIngredient; import com.minecolonies.core.structures.MineColoniesStructures; -import com.minecolonies.core.tileentities.storageblocks.StorageBlockNotificationManager; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.common.MinecraftForge; @@ -49,7 +49,6 @@ import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.event.TagsUpdatedEvent; import net.minecraftforge.event.entity.EntityAttributeCreationEvent; -import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.DistExecutor; @@ -144,7 +143,7 @@ public MineColonies() SurvivalBlueprintHandlers.registerHandler(new SurvivalHandler()); SurvivalBlueprintHandlers.registerHandler(new SuppliesHandler()); - MinecraftForge.EVENT_BUS.addListener(EventPriority.NORMAL, StorageBlockNotificationManager::handleNeighborUpdate); + MinecraftForge.EVENT_BUS.addListener(IStorageBlockNotificationManager.getInstance()::onInsert); logIncompatibilities(); } diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java index d6987e68728..5e54055c2e2 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowHutAllInventory.java @@ -116,7 +116,7 @@ private void locate(final Button button) final int row = stackList.getListElementIndexByPane(button); final ItemStorage storage = allItems.get(row); final Set containerList = new HashSet<>(building.getContainerList()); - containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getID(), building.getColony().getWorld())); + containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getColony().getWorld(), building.getID())); HighlightManager.clearHighlightsForKey("inventoryHighlight"); MessageUtils.format(MESSAGE_LOCATING_ITEMS).sendTo(Minecraft.getInstance().player); @@ -200,7 +200,7 @@ private void updateResources() final Map storedItems = new HashMap<>(); final Level world = building.getColony().getWorld(); - containerList.add(ModStorageBlocks.getStorageBlockInterface(building.getPosition(), world)); + containerList.add(ModStorageBlocks.getStorageBlockInterface(world, building.getPosition())); for (final AbstractStorageBlock storageInterface : containerList) { diff --git a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java index 08117633495..9d0303f34bf 100755 --- a/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java +++ b/src/main/java/com/minecolonies/core/client/gui/WindowsBarracksSpies.java @@ -73,7 +73,7 @@ public WindowsBarracksSpies(final IBuildingView buildingView, final BlockPos bui int goldCount = InventoryUtils.getItemCountInItemHandler(playerInv, Items.GOLD_INGOT); - AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingPos, buildingView.getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(buildingView.getColony().getWorld(), buildingPos); if (storageInterface != null) { goldCount += storageInterface.getItemCount(stack -> stack.is(Items.GOLD_INGOT)); diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java index 238ab799000..1b0990b4d71 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java @@ -7,14 +7,17 @@ import com.minecolonies.api.colony.buildings.IBuildingContainer; import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; +import com.minecolonies.core.tileentities.storageblocks.RackStorageBlock; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtUtils; import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceKey; import net.minecraft.util.Mth; import net.minecraft.util.Tuple; import net.minecraft.world.item.ItemStack; @@ -76,11 +79,33 @@ public void deserializeNBT(final CompoundTag compound) { super.deserializeNBT(compound); - final ListTag containerTagList = compound.getList(TAG_CONTAINERS, Tag.TAG_COMPOUND); - for (int i = 0; i < containerTagList.size(); ++i) + // Legacy NBT of StorageBlocks + if (compound.contains(TAG_CONTAINERS)) { - final CompoundTag containerCompound = containerTagList.getCompound(i); - addContainerPosition(NbtUtils.readBlockPos(containerCompound)); + final ListTag containerPosList = compound.getList(TAG_CONTAINERS, Tag.TAG_COMPOUND); + for (int i = 0; i < containerPosList.size(); ++i) + { + final CompoundTag containerCompound = containerPosList.getCompound(i); + BlockPos pos = NbtUtils.readBlockPos(containerCompound); + ResourceKey dimension = getColony().getDimension(); + containerList.add(new RackStorageBlock(pos, dimension)); + IStorageBlockNotificationManager.getInstance().addListener(dimension, pos, getPosition()); + } + } + // New NBT of StorageBlocks + else if (compound.contains(TAG_STORAGE_BLOCKS)) + { + final ListTag storageBlockList = compound.getList(TAG_STORAGE_BLOCKS, Tag.TAG_COMPOUND); + for (int i = 0;i < storageBlockList.size(); ++i) + { + final CompoundTag storageBlockCompound = storageBlockList.getCompound(i); + AbstractStorageBlock storageBlock = AbstractStorageBlock.fromNBT(storageBlockCompound); + if (storageBlock != null) + { + containerList.add(storageBlock); + IStorageBlockNotificationManager.getInstance().addListener(storageBlock.getDimension(), storageBlock.getPosition(), getPosition()); + } + } } if (compound.contains(TAG_PRIO)) { @@ -101,12 +126,12 @@ public CompoundTag serializeNBT() { final CompoundTag compound = super.serializeNBT(); - @NotNull final ListTag containerTagList = new ListTag(); + @NotNull final ListTag storageBlockList = new ListTag(); for (@NotNull final AbstractStorageBlock storageInterface : containerList) { - containerTagList.add(NbtUtils.writeBlockPos(storageInterface.getPosition())); + storageBlockList.add(storageInterface.serializeNBT()); } - compound.put(TAG_CONTAINERS, containerTagList); + compound.put(TAG_STORAGE_BLOCKS, storageBlockList); compound.putInt(TAG_PRIO, this.unscaledPickUpPriority); return compound; @@ -127,10 +152,11 @@ public void alterPickUpPriority(final int value) @Override public void addContainerPosition(@NotNull final BlockPos pos) { - AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(getColony().getWorld(), pos); + IStorageBlockNotificationManager.getInstance().addListener(getColony().getWorld().dimension(), pos, getPosition()); if (storageInterface != null) { - containerList.add(ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld())); + containerList.add(storageInterface); } } @@ -151,7 +177,7 @@ public void removeContainerPosition(final BlockPos pos) public List getContainers() { final List list = new ArrayList<>(containerList);; - list.add(ModStorageBlocks.getStorageBlockInterface(getPosition(), getColony().getWorld())); + list.add(ModStorageBlocks.getStorageBlockInterface(getColony().getWorld(), getPosition())); return list; } @@ -182,12 +208,12 @@ public void registerBlockPosition(@NotNull final Block block, @NotNull final Blo } else { - AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(getColony().getWorld(), pos); if (storageInterface == null) { return; } addContainerPosition(pos); - storageInterface.addInsertListener(getID()); + IStorageBlockNotificationManager.getInstance().addListener(getColony().getWorld().dimension(), pos, getPosition()); } } diff --git a/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java b/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java index 7a0d47bc90a..c9c6b2a65d1 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/views/AbstractBuildingView.java @@ -429,7 +429,7 @@ public void deserialize(@NotNull final FriendlyByteBuf buf) final int racks = buf.readInt(); for (int i = 0; i < racks; i++) { - AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(buf.readBlockPos(), getColony().getWorld()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(getColony().getWorld(), buf.readBlockPos()); if (storageInterface != null) { containerlist.add(storageInterface); diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 55b3a239813..69e212d1231 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -13,9 +13,10 @@ import com.minecolonies.api.colony.requestsystem.resolver.IRequestResolver; import com.minecolonies.api.tileentities.*; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; -import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; import com.minecolonies.api.util.ItemStackUtils; +import com.minecolonies.api.util.Log; import com.minecolonies.api.util.constant.TypeConstants; import com.minecolonies.core.client.gui.WindowHutMinPlaceholder; import com.minecolonies.core.colony.buildings.AbstractBuilding; @@ -71,7 +72,7 @@ public void requestRepair(final BlockPos builder) //To ensure that the storageblocks are all set to in the warehouse when repaired. for (final AbstractStorageBlock storageInterface : containerList) { - storageInterface.addInsertListener(builder); + IStorageBlockNotificationManager.getInstance().addListener(getColony().getWorld().dimension(), storageInterface.getPosition(), getPosition()); } super.requestRepair(builder); @@ -117,14 +118,14 @@ public int getMaxBuildingLevel() @Override public void registerBlockPosition(@NotNull final Block block, @NotNull final BlockPos pos, @NotNull final Level world) { - AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(pos, world); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(world, pos); if (storageInterface == null) { return; } - storageInterface.addInsertListener(pos); + IStorageBlockNotificationManager.getInstance().addListener(getColony().getWorld().dimension(), pos, getPosition()); int targetLevel = getFirstModuleOccurance(WarehouseModule.class).getStorageUpgrade(); while (storageInterface.getUpgradeLevel() < targetLevel) { @@ -189,16 +190,21 @@ public boolean canBeGathered() @Override public void onInsert(final BlockPos insertPos, final ItemStack itemStack) { - if (ItemStackUtils.isEmpty(itemStack) || colony.getWorld().isClientSide) + Level level = colony.getWorld(); + Log.getLogger().info("Received insert notification for {} at {}", itemStack.getItem().getDescription().getString(), insertPos); + if (ItemStackUtils.isEmpty(itemStack) || level.isClientSide) { + Log.getLogger().info("Client side, ignoring"); return; } if (!colony.isCoordInColony(colony.getWorld(), insertPos)) { + Log.getLogger().info("Block is not in a colony"); return; } + Log.getLogger().info("Updating requests with item."); colony.getRequestManager().onColonyUpdate(request -> request.getRequest() instanceof IDeliverable && ((IDeliverable) request.getRequest()).matches(itemStack)); } diff --git a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java index c90fce92ae7..691c41ff564 100755 --- a/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java +++ b/src/main/java/com/minecolonies/core/entity/ai/workers/service/EntityAIWorkDeliveryman.java @@ -566,7 +566,7 @@ public boolean gatherIfInTileEntity(final BlockEntity entity, final ItemStack is return false; } - AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(entity.getBlockPos(), entity.getLevel()); + AbstractStorageBlock storageInterface = ModStorageBlocks.getStorageBlockInterface(entity.getLevel(), entity.getBlockPos()); if (storageInterface == null) { return false; diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java index eca4270358b..8a8de9991b1 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java @@ -4,8 +4,11 @@ import com.minecolonies.api.tileentities.AbstractTileEntityWareHouse; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import com.minecolonies.api.util.*; import com.minecolonies.core.colony.buildings.modules.BuildingModules; +import com.minecolonies.core.colony.buildings.workerbuildings.BuildingWareHouse; + import net.minecraft.world.item.ItemStack; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.state.BlockState; @@ -23,7 +26,7 @@ /** * Class which handles the tileEntity of our colony warehouse. */ -public class TileEntityWareHouse extends AbstractTileEntityWareHouse +public class TileEntityWareHouse extends AbstractTileEntityWareHouse implements InsertNotifier.IInsertListener { /** * Time of last sent notifications. @@ -280,4 +283,11 @@ private AbstractStorageBlock searchMostEmptyStorageBlock() } return emptiestChest; } + + @Override + public void onInsert(BlockPos insertPos, ItemStack itemStack) + { + BuildingWareHouse warehouse = (BuildingWareHouse)getBuilding(); + warehouse.onInsert(insertPos, itemStack); + } } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java index 118e59124b6..ec551160661 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/ColonyBuildingStorageBlock.java @@ -2,6 +2,7 @@ import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; @@ -16,11 +17,11 @@ public class ColonyBuildingStorageBlock extends RackStorageBlock * @param pos The position of the target storage block * @param world The level the storage block is in */ - public ColonyBuildingStorageBlock(BlockPos pos, Level world) + public ColonyBuildingStorageBlock(BlockPos pos, ResourceKey dimension) { - super(pos, world); + super(pos, dimension); - BlockEntity targetBlockEntity = world.getBlockEntity(pos); + BlockEntity targetBlockEntity = getLevel().getBlockEntity(pos); if (!(targetBlockEntity instanceof TileEntityColonyBuilding)) { diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java index 6df38019d29..b447b4e4135 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java @@ -5,11 +5,18 @@ import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.util.InventoryUtils; +import com.minecolonies.api.util.ItemStackUtils; +import com.minecolonies.api.util.Log; import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.server.ServerLifecycleHooks; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -20,15 +27,19 @@ */ public class RackStorageBlock extends AbstractStorageBlock { - public RackStorageBlock(BlockPos pos, Level world) + public RackStorageBlock(BlockPos pos, ResourceKey dimension) { - super(pos, world); + super(pos, dimension); - BlockEntity targetBlockEntity = world.getBlockEntity(pos); - - if (!(targetBlockEntity instanceof TileEntityRack)) + Level level = getLevel(); + // Check we're on the server side, otherwise we can't get the block entity + if (level != null) { - throw new IllegalArgumentException("The block at the target position must be an instance of TileEntityRack"); + BlockEntity targetBlockEntity = getLevel().getBlockEntity(pos); + if (!(targetBlockEntity instanceof TileEntityRack)) + { + Log.getLogger().error("The block at {} must be an instance of TileEntityRack, is {}", pos, targetBlockEntity); + } } } @@ -38,6 +49,12 @@ public boolean isStillValid(final IBuilding building) return getRack().isPresent(); } + @Override + public boolean isStillValid(final IBuildingView building) + { + return getRack().isPresent(); + } + @Override public int getUpgradeLevel() { @@ -104,6 +121,12 @@ public boolean isEmpty() return getRack().map(TileEntityRack::isEmpty).orElse(true); } + @Override + public boolean isFull() + { + return getRack().map(TileEntityRack::getFreeSlots).orElse(0) == 0; + } + /** * Return whether the storageblock contains a matching item stack * @@ -149,6 +172,8 @@ public List getMatching(final @NotNull Predicate predicate */ private Optional getRack() { + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + Level level = server.levels.get(dimension); BlockEntity targetBlockEntity = level.getBlockEntity(targetPos); if (!(targetBlockEntity instanceof TileEntityRack)) { return Optional.empty(); @@ -161,4 +186,108 @@ public boolean supportsItemInsertNotification() { return true; } + + @Override + public ItemStack extractItem(Predicate predicate, boolean simulate) + { + return getRack().map(rack -> { + Optional itemHandler = rack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve(); + if (itemHandler.isEmpty()) { + return ItemStack.EMPTY; + } + + for (int i = 0; i < itemHandler.get().getSlots(); ++i) + { + ItemStack stack = itemHandler.get().getStackInSlot(i); + if (stack.isEmpty()) + { + continue; + } + + if (predicate.test(stack)) + { + return itemHandler.get().extractItem(i, stack.getCount(), simulate); + } + } + + return ItemStack.EMPTY; + }).orElse(ItemStack.EMPTY); + } + + @Override + protected boolean insertFullStackImpl(ItemStack stack) + { + return getRack().map(rack -> { + Optional itemHandler = rack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve(); + if (itemHandler.isEmpty()) { + return false; + } + + return InventoryUtils.addItemStackToItemHandler(itemHandler.get(), stack); + }).orElse(false); + + } + + @Override + public ItemStack extractItem(ItemStack itemStack, int count, boolean simulate) + { + return getRack().map(rack -> { + Optional itemHandler = rack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve(); + if (itemHandler.isEmpty()) { + return ItemStack.EMPTY; + } + + final ItemStack workingStack = itemStack.copy(); + int localCount = count; + int tries = 0; + while (tries < count) + { + final int slot = InventoryUtils.findFirstSlotInItemHandlerNotEmptyWith(itemHandler.get(), stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(workingStack, stack)); + if (slot == -1) + { + return ItemStack.EMPTY; + } + + final int removedSize = ItemStackUtils.getSize(itemHandler.get().extractItem(slot, localCount, false)); + + if (removedSize == count) + { + return itemStack; + } + else + { + localCount -= removedSize; + } + tries++; + } + + ItemStack result = itemStack.copy(); + result.setCount(count - localCount); + return result; + }).orElse(ItemStack.EMPTY); + } + + @Override + public ItemStack findFirstMatch(Predicate predicate) + { + return getRack().map(rack -> { + Optional itemHandler = rack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve(); + if (itemHandler.isEmpty()) { + return null; + } + + int slot = InventoryUtils.findFirstSlotInItemHandlerWith(itemHandler.get(), predicate); + if (slot == -1) + { + return null; + } + + return itemHandler.get().getStackInSlot(slot); + }).orElse(null); + } + + @Override + public Class getStorageBlockClass() { + return getClass(); + } } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java index d077dbe073f..ebc37b078dc 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java @@ -3,80 +3,52 @@ import java.util.HashMap; import java.util.Map; -import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.ldtteam.blockui.mod.Log; +import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemStack; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.event.level.BlockEvent; public class StorageBlockNotificationManager implements IStorageBlockNotificationManager { - - public static void handleNeighborUpdate(BlockEvent.NeighborNotifyEvent event) - { - BlockEntity entity = event.getLevel().getBlockEntity(event.getPos()); - if (entity == null) - { - return; - } - - IStorageBlockNotificationManager.getInstance().notifyUpdate(event.getPos()); - } - - private Map insertNotifiers = new HashMap<>(); - private Map updateNotifiers = new HashMap<>(); + private Map, Map> notifiers = new HashMap<>(); @Override - public void addListener(BlockPos targetPos, BlockPos listenerPos) + public void addListener(final ResourceKey dimension, final BlockPos targetPos, final BlockPos listenerPos) { - if (insertNotifiers.containsKey(targetPos)) + if (!notifiers.containsKey(dimension)) { - insertNotifiers.get(targetPos).addInsertListener(listenerPos); + notifiers.put(dimension, new HashMap()); } - if (updateNotifiers.containsKey(targetPos)) + if (!notifiers.get(dimension).containsKey(targetPos)) { - updateNotifiers.get(targetPos).addInsertListener(listenerPos); + notifiers.get(dimension).put(targetPos, new InsertNotifier()); } - } - - @Override - public void registerNewTarget(final AbstractStorageBlock target, final Level level) - { - BlockPos targetPos = target.getPosition(); - if (target.supportsItemInsertNotification()) - { - insertNotifiers.put(targetPos, new InsertNotifier(level)); - } - else - { - updateNotifiers.put(targetPos, new InsertNotifier(level)); - } + notifiers.get(dimension).get(targetPos).addInsertListener(listenerPos); } - @Override - public void notifyInsert(BlockPos targetPos, ItemStack insertedStack) + public void onInsert(StorageBlockStackInsertEvent event) { - if (insertNotifiers.containsKey(targetPos)) + Log.getLogger().info("Received notification: {}", event.getPosition()); + if (!notifiers.containsKey(event.getDimension())) { - insertNotifiers.get(targetPos).notifyInsert(targetPos, insertedStack); + Log.getLogger().info("No dimension."); + return; } - } - - @Override - public void notifyUpdate(BlockPos targetPos) - { - if (updateNotifiers.containsKey(targetPos)) + if (!notifiers.get(event.getDimension()).containsKey(event.getPosition())) { - updateNotifiers.get(targetPos).notifyUpdate(targetPos); + Log.getLogger().info("No listener list."); + return; } + + Log.getLogger().info("Notifying an insert at: {}", event.getPosition()); + notifiers.get(event.getDimension()).get(event.getPosition()).notifyInsert(event.getDimension(), event.getPosition(), event.getInsertedStack()); } - } From 3702564d7ab1eb552d70d036278fb87b98f8d0ed Mon Sep 17 00:00:00 2001 From: wmaxlees Date: Thu, 3 Oct 2024 16:06:32 -0700 Subject: [PATCH 17/17] Fixed some bugs and cleaned up --- .../api/colony/buildings/IBuilding.java | 15 +- .../event/StorageBlockStackInsertEvent.java | 47 +++++- .../inventory/container/ContainerRack.java | 8 +- .../tileentities/AbstractTileEntityRack.java | 8 +- .../storageblocks/AbstractStorageBlock.java | 24 +-- .../storageblocks/IStorageBlock.java | 141 ------------------ .../IStorageBlockNotificationManager.java | 2 +- .../storageblocks/InsertNotifier.java | 44 +----- .../minecolonies/api/util/InventoryUtils.java | 7 +- .../colony/buildings/AbstractBuilding.java | 2 + .../buildings/AbstractBuildingContainer.java | 1 + .../workerbuildings/BuildingWareHouse.java | 4 - .../tileentities/TileEntityWareHouse.java | 11 +- .../storageblocks/RackStorageBlock.java | 43 +++--- .../StorageBlockNotificationManager.java | 20 ++- 15 files changed, 123 insertions(+), 254 deletions(-) delete mode 100644 src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java diff --git a/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java b/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java index 0244452d869..42e896e664d 100755 --- a/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java +++ b/src/main/java/com/minecolonies/api/colony/buildings/IBuilding.java @@ -38,7 +38,7 @@ import static com.minecolonies.api.util.constant.EquipmentLevelConstants.BASIC_TOOL_LEVEL; import static com.minecolonies.api.util.constant.EquipmentLevelConstants.TOOL_LEVEL_MAXIMUM; -public interface IBuilding extends IBuildingContainer, IModuleContainer, IRequestResolverProvider, IRequester, ISchematicProvider +public interface IBuilding extends IBuildingContainer, IModuleContainer, IRequestResolverProvider, IRequester, ISchematicProvider, InsertNotifier.IInsertListener { /** * Minimal level to ask for wood tools. (WOOD_HUT_LEVEL + 1 == stone) @@ -494,4 +494,17 @@ default boolean canAssignCitizens() * @return true if so. */ boolean canEat(final ItemStack stack); + + /** + * Handles when a new item is inserted into a block this building is + * listening to. + * + * @param insertPos The position of the storageblock the item was inserted + * @param itemStack The item that was inserted. + */ + @Override + default void onInsert(BlockPos insertPos, ItemStack itemStack) { + overruleNextOpenRequestWithStack(itemStack); + markDirty(); + } } diff --git a/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java b/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java index 625c8b05d6f..c581aebf325 100644 --- a/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java +++ b/src/main/java/com/minecolonies/api/colony/event/StorageBlockStackInsertEvent.java @@ -6,14 +6,34 @@ import net.minecraft.world.level.Level; import net.minecraftforge.eventbus.api.Event; +/** + * An event used to notify listeners when an inventory + * is updated. + */ public class StorageBlockStackInsertEvent extends Event { - BlockPos storageBlockPos; + /** + * The position of the storage block that was updated. + */ + final BlockPos storageBlockPos; - ResourceKey dimension; + /** + * The dimension that the storage block is located in. + */ + final ResourceKey dimension; - ItemStack stack; + /** + * The stack that was inserted. + */ + final ItemStack stack; + /** + * Constructor. + * + * @param dimension The dimension of the updated storage block + * @param pos The position of the updated storage block + * @param stack The stack that was inserted into the storage block. + */ public StorageBlockStackInsertEvent(ResourceKey dimension, BlockPos pos, ItemStack stack) { this.storageBlockPos = pos; @@ -21,18 +41,39 @@ public StorageBlockStackInsertEvent(ResourceKey dimension, BlockPos pos, this.stack = stack; } + /** + * The storage block position. + * + * @return The storage block position + */ public BlockPos getPosition() { return storageBlockPos; } + /** + * The stack that was inserted into the storage block. + * + * @return The inserted stack. + */ public ItemStack getInsertedStack() { return stack; } + /** + * The dimension of the storage block. + * + * @return The dimension of the storage block. + */ public ResourceKey getDimension() { return dimension; } + + @Override + public String toString() + { + return String.format("StorageBlockStackInsertEvent: %s (%d, %d, %d) -> %s", dimension.location(), storageBlockPos.getX(), storageBlockPos.getY(), storageBlockPos.getZ(), stack.getItem().getDescription().getString()); + } } diff --git a/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java b/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java index 11ebf75a0f4..bca7796e842 100755 --- a/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java +++ b/src/main/java/com/minecolonies/api/inventory/container/ContainerRack.java @@ -7,6 +7,8 @@ import com.minecolonies.api.tileentities.AbstractTileEntityRack; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.util.ItemStackUtils; +import com.minecolonies.api.util.Log; + import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; @@ -230,11 +232,13 @@ protected boolean moveItemStackTo(final ItemStack stack, final int startIndex, f private void updateRacks(final ItemStack stack) { rack.updateItemStorage(); - MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(rack.getLevel().dimension(), rack.getBlockPos(), stack)); + StorageBlockStackInsertEvent insertEvent = new StorageBlockStackInsertEvent(rack.getLevel().dimension(), rack.getBlockPos(), stack); + MinecraftForge.EVENT_BUS.post(insertEvent); if (neighborRack != null) { neighborRack.updateItemStorage(); - MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(rack.getLevel().dimension(), rack.getBlockPos(), stack)); + insertEvent = new StorageBlockStackInsertEvent(neighborRack.getLevel().dimension(), neighborRack.getBlockPos(), stack); + MinecraftForge.EVENT_BUS.post(insertEvent); } } diff --git a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java index 2c56861d76b..e481a53c4ff 100755 --- a/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java +++ b/src/main/java/com/minecolonies/api/tileentities/AbstractTileEntityRack.java @@ -1,6 +1,7 @@ package com.minecolonies.api.tileentities; import com.minecolonies.api.crafting.ItemStorage; +import com.minecolonies.api.util.Log; import com.minecolonies.api.colony.event.StorageBlockStackInsertEvent; import net.minecraft.core.BlockPos; import net.minecraft.world.MenuProvider; @@ -77,9 +78,11 @@ public void setStackInSlot(final int slot, final @Nonnull ItemStack stack) { onContentsChanged(slot); } + if (level != null) { - MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(level.dimension(), worldPosition, stack)); + StorageBlockStackInsertEvent insertEvent = new StorageBlockStackInsertEvent(level.dimension(), worldPosition, stack); + MinecraftForge.EVENT_BUS.post(insertEvent); } } @@ -90,7 +93,8 @@ public ItemStack insertItem(final int slot, @Nonnull final ItemStack stack, fina final ItemStack result = super.insertItem(slot, stack, simulate); if ((result.isEmpty() || result.getCount() < stack.getCount()) && !simulate) { - MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(level.dimension(), worldPosition, stack)); + StorageBlockStackInsertEvent insertEvent = new StorageBlockStackInsertEvent(level.dimension(), worldPosition, stack); + MinecraftForge.EVENT_BUS.post(insertEvent); } return result; } diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java index 4f119b0fa2f..d313d6afeb7 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/AbstractStorageBlock.java @@ -102,7 +102,6 @@ public final ResourceKey getDimension() */ public final boolean isLoaded() { - return WorldUtil.isBlockLoaded(getLevel(), targetPos); } @@ -142,21 +141,10 @@ public static AbstractStorageBlock fromNBT(final CompoundTag nbt) try { Constructor constructor = clazz.getDeclaredConstructor(BlockPos.class, ResourceKey.class); - Log.getLogger().info(constructor); return constructor.newInstance(targetPos, dimension); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { Log.getLogger().error("Failed to initialize StorageBlock at {}: {}", targetPos, e); - - if (e instanceof InvocationTargetException invTargetException) - { - Log.getLogger().error("Underlying exception: {}", invTargetException.getTargetException()); - invTargetException.getTargetException().printStackTrace(); - } - // for (StackTraceElement line : e.getStackTrace()) - // { - // Log.getLogger().info(line.toString()); - // } } return null; @@ -175,7 +163,9 @@ public boolean insertFullStack(final ItemStack stack) if (result) { - MinecraftForge.EVENT_BUS.post(new StorageBlockStackInsertEvent(dimension, targetPos, stack)); + StorageBlockStackInsertEvent insertEvent = new StorageBlockStackInsertEvent(dimension, targetPos, stack); + Log.getLogger().info("AbstractStorageBlock: Sending insert event: {}", insertEvent); + MinecraftForge.EVENT_BUS.post(insertEvent); } return result; @@ -192,14 +182,6 @@ protected Level getLevel() return server.levels.get(dimension); } - /** - * Whether the storage block will notify on item inserts or - * whether we need to rely on block updates. - * - * @return if the storage block notifies on item inserts - */ - public abstract boolean supportsItemInsertNotification(); - /** * Gets the amount of a particular item contained in the storageblock * diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java deleted file mode 100644 index d3226817291..00000000000 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlock.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.minecolonies.api.tileentities.storageblocks; - -import com.minecolonies.api.colony.buildings.IBuilding; -import com.minecolonies.api.colony.buildings.views.IBuildingView; -import com.minecolonies.api.crafting.ItemStorage; -import net.minecraft.world.item.ItemStack; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.Map; -import java.util.function.Predicate; - -/** - * An interface used for defining storage blocks. This shouldn't be used - * directly. Use the AbstractStorageBlock instead. - */ -public interface IStorageBlock -{ - /** - * Gets the amount of a particular item contained in the storageblock - * - * @param storage The item to check for - */ - int getItemCount(final ItemStorage storage); - - /** - * Gets the amount of a particular item contained in the storageblock - * - * @param predicate The predicate used to select items - */ - int getItemCount(final Predicate predicate); - - /** - * Gets the matching count for a specific item stack and can ignore NBT and damage as well. - * - * @param stack The stack to check against - * @param ignoreDamageValue Whether to ignore damage - * @param ignoreNBT Whether to ignore nbt data - * @return The count of matching items in the storageblock - */ - int getItemCount(final ItemStack stack, final boolean ignoreDamageValue, final boolean ignoreNBT); - - /** - * Check whether the position is still valid for this storage interface - * - * @param building The building the block is in - * @return Whether the position is still valid - */ - boolean isStillValid(final IBuilding building); - - /** - * Check whether the position is still valid for this storage interface - * - * @param building A view of the building the block is in - * @return Whether the position is still valid - */ - boolean isStillValid(final IBuildingView building); - - /** - * Return the number of free slots in the container. - * - * @return The free slots - */ - int getFreeSlots(); - - /** - * Whether there are any items in the target storageblock - * - * @return Whether the storageblock is empty - */ - boolean isEmpty(); - - /** - * Whether the storage block has 0 completely free slots. - * - * @return True if there are no free slots, false otherwise. - */ - boolean isFull(); - - /** - * Return whether the storageblock contains a matching item stack - * - * @param stack The item type to compare - * @param count The amount that must be present - * @param ignoreDamage Whether the items should have matching damage values - * @return Whether the storageblock contains the match - */ - boolean hasItemStack(final ItemStack stack, final int count, final boolean ignoreDamage); - - /** - * Return whether the storageblock contains any items matching the predicate - * - * @param predicate The predicate to check against - * @return Whether the storageblock has any matches - */ - boolean hasItemStack(final Predicate predicate); - - /** - * Get any matching item stacks within the storage block. - * - * @param predicate The predicate to test against - * @return The list of matching item stacks - */ - List getMatching(@NotNull final Predicate predicate); - - /** - * Gets all items and their count from the storage block. - * - * @return The items and their count - */ - Map getAllContent(); - - /** - * Removes an item stack matching the given predicate from the storage block - * and returns it. - * - * @param predicate The predicate to match - * @param simulate If true, actually remove the item. - * @return The matching item stack, or ItemStack.EMPTY - */ - ItemStack extractItem(final Predicate predicate, boolean simulate); - - /** - * Removes an item stack matching the given predicate from the storage block - * and returns it. Will only return if the stack has at least minCount stack size. - * - * @param predicate The predicate to match - * @param minCount The minimum count the stack size must be - * @param simulate If true, actually removes the item. - * @return The matching item stack, or ItemStack.EMPTY - */ - ItemStack extractItem(final Predicate predicate, int minCount, boolean simulate); - - /** - * Adds the full item stack to the first available slot in - * the storage block. - * - * @return if the full transfer was successful - */ - boolean insertFullStackImpl(final ItemStack stack, final boolean simulate); -} diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java index afa25f753c8..88db08bcc9c 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/IStorageBlockNotificationManager.java @@ -8,7 +8,7 @@ import net.minecraft.world.level.Level; /** - * The manager for letting blocks (particularly the Warehouse) when + * The manager for letting blocks listen for when * storage blocks are updated or items are inserted into them. */ public interface IStorageBlockNotificationManager diff --git a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java index fd9cbe5a25f..fafb3a0779c 100644 --- a/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java +++ b/src/main/java/com/minecolonies/api/tileentities/storageblocks/InsertNotifier.java @@ -1,22 +1,17 @@ package com.minecolonies.api.tileentities.storageblocks; -import com.minecolonies.api.util.Log; -import com.minecolonies.api.util.NBTUtils; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtUtils; -import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraftforge.server.ServerLifecycleHooks; import java.util.HashSet; import java.util.Set; -import static com.minecolonies.api.util.constant.NbtTagConstants.TAG_LISTENER_LOC; +import com.minecolonies.api.colony.IColonyManager; +import com.minecolonies.api.colony.buildings.IBuilding; /** * This defines a notifier that will inform listeners @@ -52,44 +47,13 @@ public void notifyInsert(final ResourceKey dimension, final BlockPos inse { MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); Level level = server.getLevel(dimension); - Log.getLogger().info("Got a notifyInsert in InsertNotifier. Sharing event."); for (BlockPos pos : this.insertListeners) { - BlockEntity entity = level.getBlockEntity(pos); - Log.getLogger().info("Sharing with {} which is {}", pos, entity); - if (entity instanceof IInsertListener listener) - { - listener.onInsert(insertPos, itemStack); - } + IBuilding building = IColonyManager.getInstance().getBuilding(level, pos); + building.onInsert(insertPos, itemStack); } } - /** - * Serialize the InsertNotifier to NBT data. - * - * @return The NBT data. - */ - public CompoundTag serializeToNBT() - { - final CompoundTag tag = new CompoundTag(); - - tag.put(TAG_LISTENER_LOC, insertListeners.stream().map(NbtUtils::writeBlockPos).collect(NBTUtils.toListNBT())); - - return tag; - } - - /** - * Populate teh InsertNotifier from NBT - * - * @param nbt The NBT data. - */ - public void read(CompoundTag nbt) - { - NBTUtils.streamCompound(nbt.getList(TAG_LISTENER_LOC, Tag.TAG_COMPOUND)) - .map(NbtUtils::readBlockPos) - .forEach(insertListeners::add); - } - /** * The interface that any listener must implement. */ diff --git a/src/main/java/com/minecolonies/api/util/InventoryUtils.java b/src/main/java/com/minecolonies/api/util/InventoryUtils.java index da559e0c9a9..cbba39b36e9 100755 --- a/src/main/java/com/minecolonies/api/util/InventoryUtils.java +++ b/src/main/java/com/minecolonies/api/util/InventoryUtils.java @@ -7,7 +7,6 @@ import com.minecolonies.api.crafting.ItemStorage; import com.minecolonies.api.equipment.registry.EquipmentTypeEntry; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; -import com.minecolonies.api.tileentities.storageblocks.IStorageBlock; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.TileEntityRack; import net.minecraft.core.Direction; @@ -745,7 +744,7 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, int totalCount = 0; for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) + if (storageInterface == null || !storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { continue; } @@ -773,7 +772,8 @@ public static int hasBuildingEnoughElseCount(@NotNull final IBuilding provider, int totalCount = 0; for (final AbstractStorageBlock storageInterface : provider.getContainers()) { - if (!storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) { + if (storageInterface == null || !storageInterface.isLoaded() || !storageInterface.isStillValid(provider)) + { continue; } @@ -1780,6 +1780,7 @@ public static boolean transferXOfItemStackIntoNextFreeSlotInItemHandler( } sourceStack = sourceStorage.extractItem(itemStack, count, false); + Log.getLogger().info("Extracted {} from target storage block.", sourceStack.getItem().getDescription().getString()); for (int i = 0; i < targetHandler.getSlots(); i++) { diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java index 51f6f2a1094..4a3628acd17 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuilding.java @@ -38,6 +38,7 @@ import com.minecolonies.api.tileentities.AbstractTileEntityColonyBuilding; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; +import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import com.minecolonies.api.util.*; import com.minecolonies.api.util.constant.Constants; @@ -167,6 +168,7 @@ protected AbstractBuilding(@NotNull final IColony colony, final BlockPos pos) this.requester = StandardFactoryController.getInstance().getNewInstance(TypeToken.of(BuildingBasedRequester.class), this); setupRsDataStore(); + IStorageBlockNotificationManager.getInstance().addListener(colony.getDimension(), pos, pos); } @Override diff --git a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java index 1b0990b4d71..8b37a24829a 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/AbstractBuildingContainer.java @@ -9,6 +9,7 @@ import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; import com.minecolonies.api.tileentities.storageblocks.IStorageBlockNotificationManager; import com.minecolonies.api.tileentities.storageblocks.ModStorageBlocks; +import com.minecolonies.api.util.Log; import com.minecolonies.core.tileentities.TileEntityColonyBuilding; import com.minecolonies.core.tileentities.storageblocks.RackStorageBlock; import net.minecraft.core.BlockPos; diff --git a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java index 69e212d1231..b3578e543b6 100755 --- a/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java +++ b/src/main/java/com/minecolonies/core/colony/buildings/workerbuildings/BuildingWareHouse.java @@ -191,20 +191,16 @@ public boolean canBeGathered() public void onInsert(final BlockPos insertPos, final ItemStack itemStack) { Level level = colony.getWorld(); - Log.getLogger().info("Received insert notification for {} at {}", itemStack.getItem().getDescription().getString(), insertPos); if (ItemStackUtils.isEmpty(itemStack) || level.isClientSide) { - Log.getLogger().info("Client side, ignoring"); return; } if (!colony.isCoordInColony(colony.getWorld(), insertPos)) { - Log.getLogger().info("Block is not in a colony"); return; } - Log.getLogger().info("Updating requests with item."); colony.getRequestManager().onColonyUpdate(request -> request.getRequest() instanceof IDeliverable && ((IDeliverable) request.getRequest()).matches(itemStack)); } diff --git a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java index 8a8de9991b1..ff99e67a0c2 100755 --- a/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java +++ b/src/main/java/com/minecolonies/core/tileentities/TileEntityWareHouse.java @@ -4,10 +4,8 @@ import com.minecolonies.api.tileentities.AbstractTileEntityWareHouse; import com.minecolonies.api.tileentities.MinecoloniesTileEntities; import com.minecolonies.api.tileentities.storageblocks.AbstractStorageBlock; -import com.minecolonies.api.tileentities.storageblocks.InsertNotifier; import com.minecolonies.api.util.*; import com.minecolonies.core.colony.buildings.modules.BuildingModules; -import com.minecolonies.core.colony.buildings.workerbuildings.BuildingWareHouse; import net.minecraft.world.item.ItemStack; import net.minecraft.core.BlockPos; @@ -26,7 +24,7 @@ /** * Class which handles the tileEntity of our colony warehouse. */ -public class TileEntityWareHouse extends AbstractTileEntityWareHouse implements InsertNotifier.IInsertListener +public class TileEntityWareHouse extends AbstractTileEntityWareHouse { /** * Time of last sent notifications. @@ -283,11 +281,4 @@ private AbstractStorageBlock searchMostEmptyStorageBlock() } return emptiestChest; } - - @Override - public void onInsert(BlockPos insertPos, ItemStack itemStack) - { - BuildingWareHouse warehouse = (BuildingWareHouse)getBuilding(); - warehouse.onInsert(insertPos, itemStack); - } } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java index b447b4e4135..c4ef11bc2b6 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/RackStorageBlock.java @@ -181,15 +181,10 @@ private Optional getRack() return Optional.of((TileEntityRack) targetBlockEntity); } - @Override - public boolean supportsItemInsertNotification() - { - return true; - } - @Override public ItemStack extractItem(Predicate predicate, boolean simulate) { + Log.getLogger().info("RackStorageBlock#extractItem: Extracting predicate {}, simulate {}", predicate, simulate); return getRack().map(rack -> { Optional itemHandler = rack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve(); if (itemHandler.isEmpty()) { @@ -231,38 +226,42 @@ protected boolean insertFullStackImpl(ItemStack stack) @Override public ItemStack extractItem(ItemStack itemStack, int count, boolean simulate) { + Log.getLogger().info("RackStorageBlock#extractItem: Extracting item stack {}, simulate {}", itemStack.getItem().getDescription().getString(), simulate); return getRack().map(rack -> { Optional itemHandler = rack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve(); if (itemHandler.isEmpty()) { return ItemStack.EMPTY; } - final ItemStack workingStack = itemStack.copy(); - int localCount = count; - int tries = 0; - while (tries < count) + int remainingCount = count; + for (int slot = 0; slot < itemHandler.get().getSlots(); ++slot) { - final int slot = InventoryUtils.findFirstSlotInItemHandlerNotEmptyWith(itemHandler.get(), stack -> ItemStackUtils.compareItemStacksIgnoreStackSize(workingStack, stack)); - if (slot == -1) + ItemStack slotStack = itemHandler.get().getStackInSlot(slot); + if (slotStack.isEmpty()) { - return ItemStack.EMPTY; + continue; } - final int removedSize = ItemStackUtils.getSize(itemHandler.get().extractItem(slot, localCount, false)); + if (!ItemStackUtils.compareItemStacksIgnoreStackSize(itemStack, slotStack)) + { + continue; + } - if (removedSize == count) + slotStack = itemHandler.get().extractItem(slot, Math.min(slotStack.getCount(), remainingCount), simulate); + if (slotStack.isEmpty()) { - return itemStack; + continue; } - else + + remainingCount -= slotStack.getCount(); + + if (remainingCount <= 0) { - localCount -= removedSize; + break; } - tries++; } - - ItemStack result = itemStack.copy(); - result.setCount(count - localCount); + + ItemStack result = itemStack.copyWithCount(count - remainingCount); return result; }).orElse(ItemStack.EMPTY); } diff --git a/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java b/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java index ebc37b078dc..141ca6055ad 100644 --- a/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java +++ b/src/main/java/com/minecolonies/core/tileentities/storageblocks/StorageBlockNotificationManager.java @@ -10,7 +10,11 @@ import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.fml.loading.FMLEnvironment; +import net.minecraftforge.server.ServerLifecycleHooks; public class StorageBlockNotificationManager implements IStorageBlockNotificationManager { @@ -35,20 +39,28 @@ public void addListener(final ResourceKey dimension, final BlockPos targe @Override public void onInsert(StorageBlockStackInsertEvent event) { - Log.getLogger().info("Received notification: {}", event.getPosition()); + MinecraftServer server = ServerLifecycleHooks.getCurrentServer(); + Level level = server.levels.get(event.getDimension()); + if (level.isClientSide) + { + return; + } + if (!notifiers.containsKey(event.getDimension())) { - Log.getLogger().info("No dimension."); return; } if (!notifiers.get(event.getDimension()).containsKey(event.getPosition())) { - Log.getLogger().info("No listener list."); return; } - Log.getLogger().info("Notifying an insert at: {}", event.getPosition()); + if (event.getInsertedStack().isEmpty()) + { + return; + } + notifiers.get(event.getDimension()).get(event.getPosition()).notifyInsert(event.getDimension(), event.getPosition(), event.getInsertedStack()); } }