diff --git a/gradle.properties b/gradle.properties index 1844a99..32bf1a7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ yarn_mappings=1.20.6+build.3 loader_version=0.15.11 # Mod Properties -mod_version=1.7 +mod_version=1.8 maven_group=systems.brn archives_base_name=Server_storage diff --git a/src/main/java/systems/brn/server_storage/ServerStorage.java b/src/main/java/systems/brn/server_storage/ServerStorage.java index f5b412b..001a99c 100644 --- a/src/main/java/systems/brn/server_storage/ServerStorage.java +++ b/src/main/java/systems/brn/server_storage/ServerStorage.java @@ -2,6 +2,8 @@ package systems.brn.server_storage; import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils; import net.fabricmc.api.ModInitializer; +import net.minecraft.block.entity.BlockEntityType; +import systems.brn.server_storage.blockentities.StorageBlockEntity; import systems.brn.server_storage.blocks.StorageBlock; import systems.brn.server_storage.items.StorageBlockItem; @@ -9,6 +11,7 @@ public class ServerStorage implements ModInitializer { public static final String MODID = "serverstorage"; public static final String MODELID = "storage"; public static StorageBlock STORAGE_BLOCK; + public static BlockEntityType STORAGE_BLOCK_ENTITY; @Override public void onInitialize() diff --git a/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java b/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java new file mode 100644 index 0000000..5c2a69a --- /dev/null +++ b/src/main/java/systems/brn/server_storage/blockentities/StorageBlockEntity.java @@ -0,0 +1,96 @@ +package systems.brn.server_storage.blockentities; + +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.SidedInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import systems.brn.server_storage.lib.ConnectedChests; +import systems.brn.server_storage.screens.StorageScreen; + +import java.util.ArrayList; + +import static systems.brn.server_storage.ServerStorage.STORAGE_BLOCK_ENTITY; +import static systems.brn.server_storage.lib.StorageOperations.*; + +public class StorageBlockEntity extends BlockEntity implements Inventory, SidedInventory, Runnable { + + @Override + public void run() { + assert storageScreenToDelete != null; + openStorageScreens.remove(storageScreenToDelete); + } + + public StorageScreen storageScreenToDelete; + + public ArrayList openStorageScreens = new ArrayList<>(); + + public StorageBlockEntity(BlockPos pos, BlockState state) { + super(STORAGE_BLOCK_ENTITY, pos, state); + } + + @Override + public int size() { + return 1; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public ItemStack getStack(int slot) { + return ItemStack.EMPTY; + } + + @Override + public ItemStack removeStack(int slot, int amount) { + return ItemStack.EMPTY; + } + + @Override + public ItemStack removeStack(int slot) { + return ItemStack.EMPTY; + } + + @Override + public void setStack(int slot, ItemStack stack) { + markDirty(); + ConnectedChests chests = getConnectedChests(world, this.pos); + tryPutItemStackIntoChests(chests.getInventories(), stack); + for (StorageScreen screen : openStorageScreens) { + screen.updateDisplay(); + } + } + + @Override + public boolean canPlayerUse(PlayerEntity player) { + return false; + } + + @Override + public void clear() { + // Do nothing, prevent clearing the inventory + } + + // SidedInventory methods + @Override + public int[] getAvailableSlots(Direction side) { + return new int[]{0}; // Allow access to the single slot + } + + @Override + public boolean canInsert(int slot, ItemStack stack, Direction dir) { + ConnectedChests chests = getConnectedChests(world, this.pos); + return canPutItemStackIntoChests(chests.getInventories(), stack); + } + + @Override + public boolean canExtract(int slot, ItemStack stack, Direction dir) { + return false; // Prevent extraction + } +} diff --git a/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java b/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java index 5773dcd..f69fdb0 100644 --- a/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java +++ b/src/main/java/systems/brn/server_storage/blocks/StorageBlock.java @@ -4,11 +4,11 @@ import eu.pb4.polymer.blocks.api.BlockModelType; import eu.pb4.polymer.blocks.api.PolymerBlockModel; import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils; import eu.pb4.polymer.blocks.api.PolymerTexturedBlock; +import eu.pb4.polymer.core.api.block.PolymerBlockUtils; import net.fabricmc.fabric.api.event.player.UseBlockCallback; -import net.minecraft.block.AbstractBlock; -import net.minecraft.block.Block; -import net.minecraft.block.BlockState; -import net.minecraft.block.Blocks; +import net.minecraft.block.*; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityType; import net.minecraft.component.DataComponentTypes; import net.minecraft.component.type.WrittenBookContentComponent; import net.minecraft.entity.player.PlayerEntity; @@ -26,18 +26,20 @@ import net.minecraft.util.Identifier; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; import systems.brn.server_storage.ServerStorage; +import systems.brn.server_storage.blockentities.StorageBlockEntity; import systems.brn.server_storage.lib.ConnectedChests; import systems.brn.server_storage.screens.StorageScreen; import java.util.List; -import static systems.brn.server_storage.ServerStorage.STORAGE_BLOCK; +import static systems.brn.server_storage.ServerStorage.*; import static systems.brn.server_storage.lib.StorageOperations.getCombinedInventoryFromChests; import static systems.brn.server_storage.lib.StorageOperations.getConnectedChests; import static systems.brn.server_storage.lib.Util.generateBookContent; -public class StorageBlock extends Block implements PolymerTexturedBlock { +public class StorageBlock extends Block implements PolymerTexturedBlock, BlockEntityProvider { private final BlockState polymerBlockState; @@ -56,6 +58,13 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { STORAGE_BLOCK = Registry.register(Registries.BLOCK, modId, new StorageBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), BlockModelType.FULL_BLOCK, ServerStorage.MODELID)); UseBlockCallback.EVENT.register(StorageBlock::onUse); + + STORAGE_BLOCK_ENTITY = Registry.register( + Registries.BLOCK_ENTITY_TYPE, + new Identifier(MODID, MODELID), + BlockEntityType.Builder.create(StorageBlockEntity::new, STORAGE_BLOCK).build(null) + ); + PolymerBlockUtils.registerBlockEntity(STORAGE_BLOCK_ENTITY); } private static ActionResult onUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) { @@ -65,7 +74,15 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { if (block instanceof StorageBlock) { if (!world.isClient && !player.isSpectator()) { - if (player.isSneaking() && player.getStackInHand(hand).getItem() == Items.WRITTEN_BOOK) { + if(!player.isSneaking()){ + StorageBlockEntity blockEntity = (StorageBlockEntity) world.getBlockEntity(pos); + assert blockEntity != null; + StorageScreen storageScreen = new StorageScreen((ServerPlayerEntity) player, pos, blockEntity); + storageScreen.open(); + blockEntity.openStorageScreens.add(storageScreen); + + } + else if(player.getStackInHand(hand).getItem() == Items.WRITTEN_BOOK) { ItemStack book = player.getStackInHand(hand); ConnectedChests chests = getConnectedChests(world, pos); List inventories = chests.getInventories(); @@ -79,7 +96,7 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { false )); } else { - new StorageScreen((ServerPlayerEntity) player, pos).open(); + return ActionResult.PASS; } } return ActionResult.SUCCESS; @@ -87,4 +104,9 @@ public class StorageBlock extends Block implements PolymerTexturedBlock { return ActionResult.PASS; } + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new StorageBlockEntity(pos, state); + } } diff --git a/src/main/java/systems/brn/server_storage/lib/StorageOperations.java b/src/main/java/systems/brn/server_storage/lib/StorageOperations.java index a3d8f8a..f0af978 100644 --- a/src/main/java/systems/brn/server_storage/lib/StorageOperations.java +++ b/src/main/java/systems/brn/server_storage/lib/StorageOperations.java @@ -1,6 +1,7 @@ package systems.brn.server_storage.lib; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.HopperBlockEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.inventory.Inventory; @@ -33,7 +34,7 @@ public class StorageOperations { BlockEntity blockEntity = world.getBlockEntity(pos); if (blockEntity instanceof Inventory || world.getBlockState(pos).getBlock() instanceof StorageBlock) { - if (blockEntity instanceof Inventory) { + if (blockEntity instanceof Inventory && !(world.getBlockState(pos).getBlock() instanceof StorageBlock)) { inventories.add((Inventory) blockEntity); } @@ -48,9 +49,11 @@ public class StorageOperations { // Iterate over each chest to try and insert the ItemStack for (Inventory chest : inventories) { - stack = insertStackIntoInventory(chest, stack); - if (stack.isEmpty()) { - return true; + if(!(chest instanceof HopperBlockEntity)) { + stack = insertStackIntoInventory(chest, stack); + if (stack.isEmpty()) { + return true; + } } } @@ -58,6 +61,25 @@ public class StorageOperations { return stack.isEmpty(); } + public static boolean canPutItemStackIntoChests(List inventories, ItemStack stack) { + // Iterate over each chest to check if it's possible to insert the ItemStack + for (Inventory chest : inventories) { + if (!(chest instanceof HopperBlockEntity)) { + // Attempt to insert the ItemStack into the current chest + for (int i = 0; i < chest.size(); i++) { + ItemStack slotStack = chest.getStack(i); + if (slotStack.isEmpty() || canCombine(slotStack, stack)) { + // If the slot is empty or can be combined with the ItemStack, return true + return true; + } + } + } + } + + // If it's not possible to insert into any chest, return false + return false; + } + private static ItemStack insertStackIntoInventory(Inventory inventory, ItemStack stack) { // First, try to merge with existing stacks for (int i = 0; i < inventory.size(); i++) { diff --git a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java index bebf213..a049fa2 100644 --- a/src/main/java/systems/brn/server_storage/screens/StorageScreen.java +++ b/src/main/java/systems/brn/server_storage/screens/StorageScreen.java @@ -12,6 +12,7 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; import systems.brn.server_storage.lib.ConnectedChests; import systems.brn.server_storage.lib.PagedGui; @@ -30,8 +31,8 @@ public class StorageScreen extends PagedGui { private String query; private boolean sortAlphabetically; - public StorageScreen(ServerPlayerEntity player, BlockPos pos) { - super(player, null); + public StorageScreen(ServerPlayerEntity player, BlockPos pos, @Nullable Runnable closeCallback) { + super(player, closeCallback); this.player = player; this.pos = pos; this.world = player.getWorld(); @@ -40,7 +41,7 @@ public class StorageScreen extends PagedGui { } @Override - protected void updateDisplay() { + public void updateDisplay() { ConnectedChests chests = getConnectedChests(world, this.pos); this.inventories = chests.getInventories(); this.inventory = getCombinedInventoryFromChests(inventories, sortAlphabetically);