Add hopper insertion support

This commit is contained in:
Bruno Rybársky 2024-05-25 16:49:29 +02:00
parent 621d7514bb
commit a5cd5adb09
6 changed files with 160 additions and 16 deletions

@ -8,7 +8,7 @@ yarn_mappings=1.20.6+build.3
loader_version=0.15.11 loader_version=0.15.11
# Mod Properties # Mod Properties
mod_version=1.7 mod_version=1.8
maven_group=systems.brn maven_group=systems.brn
archives_base_name=Server_storage archives_base_name=Server_storage

@ -2,6 +2,8 @@ package systems.brn.server_storage;
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils; import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
import net.fabricmc.api.ModInitializer; 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.blocks.StorageBlock;
import systems.brn.server_storage.items.StorageBlockItem; 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 MODID = "serverstorage";
public static final String MODELID = "storage"; public static final String MODELID = "storage";
public static StorageBlock STORAGE_BLOCK; public static StorageBlock STORAGE_BLOCK;
public static BlockEntityType<StorageBlockEntity> STORAGE_BLOCK_ENTITY;
@Override @Override
public void onInitialize() public void onInitialize()

@ -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<StorageScreen> 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
}
}

@ -4,11 +4,11 @@ import eu.pb4.polymer.blocks.api.BlockModelType;
import eu.pb4.polymer.blocks.api.PolymerBlockModel; import eu.pb4.polymer.blocks.api.PolymerBlockModel;
import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils; import eu.pb4.polymer.blocks.api.PolymerBlockResourceUtils;
import eu.pb4.polymer.blocks.api.PolymerTexturedBlock; 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.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.minecraft.block.AbstractBlock; import net.minecraft.block.*;
import net.minecraft.block.Block; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.Blocks;
import net.minecraft.component.DataComponentTypes; import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.WrittenBookContentComponent; import net.minecraft.component.type.WrittenBookContentComponent;
import net.minecraft.entity.player.PlayerEntity; 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.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import systems.brn.server_storage.ServerStorage; 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.lib.ConnectedChests;
import systems.brn.server_storage.screens.StorageScreen; import systems.brn.server_storage.screens.StorageScreen;
import java.util.List; 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.getCombinedInventoryFromChests;
import static systems.brn.server_storage.lib.StorageOperations.getConnectedChests; import static systems.brn.server_storage.lib.StorageOperations.getConnectedChests;
import static systems.brn.server_storage.lib.Util.generateBookContent; 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; private final BlockState polymerBlockState;
@ -56,6 +58,13 @@ public class StorageBlock extends Block implements PolymerTexturedBlock {
STORAGE_BLOCK = Registry.register(Registries.BLOCK, modId, STORAGE_BLOCK = Registry.register(Registries.BLOCK, modId,
new StorageBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), BlockModelType.FULL_BLOCK, ServerStorage.MODELID)); new StorageBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), BlockModelType.FULL_BLOCK, ServerStorage.MODELID));
UseBlockCallback.EVENT.register(StorageBlock::onUse); 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) { 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 (block instanceof StorageBlock) {
if (!world.isClient && !player.isSpectator()) { 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); ItemStack book = player.getStackInHand(hand);
ConnectedChests chests = getConnectedChests(world, pos); ConnectedChests chests = getConnectedChests(world, pos);
List<Inventory> inventories = chests.getInventories(); List<Inventory> inventories = chests.getInventories();
@ -79,7 +96,7 @@ public class StorageBlock extends Block implements PolymerTexturedBlock {
false false
)); ));
} else { } else {
new StorageScreen((ServerPlayerEntity) player, pos).open(); return ActionResult.PASS;
} }
} }
return ActionResult.SUCCESS; return ActionResult.SUCCESS;
@ -87,4 +104,9 @@ public class StorageBlock extends Block implements PolymerTexturedBlock {
return ActionResult.PASS; return ActionResult.PASS;
} }
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
return new StorageBlockEntity(pos, state);
}
} }

@ -1,6 +1,7 @@
package systems.brn.server_storage.lib; package systems.brn.server_storage.lib;
import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.HopperBlockEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory; import net.minecraft.inventory.Inventory;
@ -33,7 +34,7 @@ public class StorageOperations {
BlockEntity blockEntity = world.getBlockEntity(pos); BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof Inventory || world.getBlockState(pos).getBlock() instanceof StorageBlock) { 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); inventories.add((Inventory) blockEntity);
} }
@ -48,16 +49,37 @@ public class StorageOperations {
// Iterate over each chest to try and insert the ItemStack // Iterate over each chest to try and insert the ItemStack
for (Inventory chest : inventories) { for (Inventory chest : inventories) {
if(!(chest instanceof HopperBlockEntity)) {
stack = insertStackIntoInventory(chest, stack); stack = insertStackIntoInventory(chest, stack);
if (stack.isEmpty()) { if (stack.isEmpty()) {
return true; return true;
} }
} }
}
// If we still have remaining items, return false // If we still have remaining items, return false
return stack.isEmpty(); return stack.isEmpty();
} }
public static boolean canPutItemStackIntoChests(List<Inventory> 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) { private static ItemStack insertStackIntoInventory(Inventory inventory, ItemStack stack) {
// First, try to merge with existing stacks // First, try to merge with existing stacks
for (int i = 0; i < inventory.size(); i++) { for (int i = 0; i < inventory.size(); i++) {

@ -12,6 +12,7 @@ import net.minecraft.text.Text;
import net.minecraft.util.Formatting; import net.minecraft.util.Formatting;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
import systems.brn.server_storage.lib.ConnectedChests; import systems.brn.server_storage.lib.ConnectedChests;
import systems.brn.server_storage.lib.PagedGui; import systems.brn.server_storage.lib.PagedGui;
@ -30,8 +31,8 @@ public class StorageScreen extends PagedGui {
private String query; private String query;
private boolean sortAlphabetically; private boolean sortAlphabetically;
public StorageScreen(ServerPlayerEntity player, BlockPos pos) { public StorageScreen(ServerPlayerEntity player, BlockPos pos, @Nullable Runnable closeCallback) {
super(player, null); super(player, closeCallback);
this.player = player; this.player = player;
this.pos = pos; this.pos = pos;
this.world = player.getWorld(); this.world = player.getWorld();
@ -40,7 +41,7 @@ public class StorageScreen extends PagedGui {
} }
@Override @Override
protected void updateDisplay() { public void updateDisplay() {
ConnectedChests chests = getConnectedChests(world, this.pos); ConnectedChests chests = getConnectedChests(world, this.pos);
this.inventories = chests.getInventories(); this.inventories = chests.getInventories();
this.inventory = getCombinedInventoryFromChests(inventories, sortAlphabetically); this.inventory = getCombinedInventoryFromChests(inventories, sortAlphabetically);