A bit of an update
							
								
								
									
										
											BIN
										
									
								
								assets/CPU.aseprite
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								assets/Connector.aseprite
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								assets/Drive_Controller.aseprite
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								assets/Inventory_Interface.aseprite
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								assets/Module_PCB.aseprite
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								assets/PCB.aseprite
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -4,11 +4,11 @@ org.gradle.jvmargs=-Xmx1G
 | 
			
		||||
# check these on https://modmuss50.me/fabric.html
 | 
			
		||||
 | 
			
		||||
minecraft_version=1.21
 | 
			
		||||
yarn_mappings=1.21+build.2
 | 
			
		||||
yarn_mappings=1.21+build.7
 | 
			
		||||
loader_version=0.15.11
 | 
			
		||||
 | 
			
		||||
# Fabric API
 | 
			
		||||
fabric_version=0.100.3+1.21
 | 
			
		||||
fabric_version=0.100.4+1.21
 | 
			
		||||
 | 
			
		||||
# Mod Properties
 | 
			
		||||
mod_version=2.6.2
 | 
			
		||||
 
 | 
			
		||||
@@ -6,12 +6,16 @@ import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
 | 
			
		||||
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntityType;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemGroups;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.minecraft.world.GameRules;
 | 
			
		||||
import systems.brn.server_storage.blockentities.HardDriveContainerBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.InventoryInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blocks.BusConnectorBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.HardDriveContainerBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.StorageBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.InventoryInterfaceBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.StorageInterfaceBlock;
 | 
			
		||||
import systems.brn.server_storage.items.HardDriveItem;
 | 
			
		||||
import systems.brn.server_storage.items.SimpleBlockItem;
 | 
			
		||||
import systems.brn.server_storage.items.SimpleItem;
 | 
			
		||||
@@ -20,26 +24,40 @@ import java.util.Arrays;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class ServerStorage implements ModInitializer {
 | 
			
		||||
    public static final List<String> moduleList = Arrays.asList("bus", "configuration", "container", "display", "drive", "filtering", "inventory", "pagination", "pcb", "transport");
 | 
			
		||||
    public static final List<String> tiers = Arrays.asList("iron", "golden", "diamond", "netherite");
 | 
			
		||||
 | 
			
		||||
    public static final String MOD_ID = "serverstorage";
 | 
			
		||||
 | 
			
		||||
    public static final String STORAGE_MODEL_ID = "storage";
 | 
			
		||||
    public static final String HARD_DRIVE_CONTAINER_BLOCK_MODEL_ID = "drive_container";
 | 
			
		||||
    public static final String BUS_CONNECTOR_MODEL_ID = "bus_connector";
 | 
			
		||||
    public static BusConnectorBlock BUS_CONNECTOR_BLOCK;
 | 
			
		||||
 | 
			
		||||
    public static final String HARD_DRIVE_CONTAINER_BLOCK_MODEL_ID = "drive_container";
 | 
			
		||||
    public static BlockEntityType<HardDriveContainerBlockEntity> HARD_DRIVE_CONTAINER_BLOCK_ENTITY;
 | 
			
		||||
    public static HardDriveContainerBlock HARD_DRIVE_CONTAINER_BLOCK;
 | 
			
		||||
 | 
			
		||||
    public static StorageBlock STORAGE_BLOCK;
 | 
			
		||||
    public static BlockEntityType<StorageBlockEntity> STORAGE_BLOCK_ENTITY;
 | 
			
		||||
    public static final String STORAGE_MODEL_ID = "storage";
 | 
			
		||||
    public static StorageInterfaceBlock STORAGE_INTERFACE_BLOCK;
 | 
			
		||||
    public static BlockEntityType<StorageInterfaceBlockEntity> STORAGE_INTERFACE_BLOCK_ENTITY;
 | 
			
		||||
 | 
			
		||||
    public static final String INVENTORY_INTERFACE_BLOCK_MODEL_ID = "inventory_interface";
 | 
			
		||||
    public static InventoryInterfaceBlock INVENTORY_INTERFACE_BLOCK;
 | 
			
		||||
    public static BlockEntityType<InventoryInterfaceBlockEntity> INVENTORY_INTERFACE_BLOCK_ENTITY;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static Item DRIVE_CASING;
 | 
			
		||||
    public static Item CPU;
 | 
			
		||||
    public static Item CPU_SUBSTRATE;
 | 
			
		||||
    public static Item DRIVE_CONTROLLER;
 | 
			
		||||
    public static Item PCB;
 | 
			
		||||
    public static Item PCB_SUBSTRATE;
 | 
			
		||||
    public static List<Item> MODULES;
 | 
			
		||||
    public static List<Item> PLATTERS;
 | 
			
		||||
    public static List<Item> DRIVES;
 | 
			
		||||
    public static List<Item> HEADS;
 | 
			
		||||
 | 
			
		||||
    public static final GameRules.Key<GameRules.BooleanRule> ServerStorage_Crafting_Enable =
 | 
			
		||||
            GameRuleRegistry.register("enableserverstoragecrafting", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(false));
 | 
			
		||||
            GameRuleRegistry.register("enableServerStorageCrafting", GameRules.Category.MISC, GameRuleFactory.createBooleanRule(false));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public static Identifier id(String path) {
 | 
			
		||||
@@ -49,17 +67,34 @@ public class ServerStorage implements ModInitializer {
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onInitialize()
 | 
			
		||||
    {
 | 
			
		||||
        StorageBlock.register();
 | 
			
		||||
        SimpleBlockItem.register(STORAGE_BLOCK);
 | 
			
		||||
        StorageInterfaceBlock.register();
 | 
			
		||||
        SimpleBlockItem.register(STORAGE_INTERFACE_BLOCK);
 | 
			
		||||
 | 
			
		||||
        HardDriveContainerBlock.register();
 | 
			
		||||
        SimpleBlockItem.register(HARD_DRIVE_CONTAINER_BLOCK);
 | 
			
		||||
 | 
			
		||||
        HEADS = SimpleItem.register("head", tiers);
 | 
			
		||||
        PLATTERS = SimpleItem.register("platter", tiers);
 | 
			
		||||
        DRIVE_CASING = SimpleItem.register("drive_casing");
 | 
			
		||||
        BusConnectorBlock.register();
 | 
			
		||||
        SimpleBlockItem.register(BUS_CONNECTOR_BLOCK);
 | 
			
		||||
 | 
			
		||||
        InventoryInterfaceBlock.register();
 | 
			
		||||
        SimpleBlockItem.register(INVENTORY_INTERFACE_BLOCK);
 | 
			
		||||
 | 
			
		||||
        PCB = SimpleItem.register("pcb", ItemGroups.INGREDIENTS);
 | 
			
		||||
        PCB_SUBSTRATE = SimpleItem.register("pcb_substrate", ItemGroups.INGREDIENTS);
 | 
			
		||||
        CPU = SimpleItem.register("cpu", ItemGroups.INGREDIENTS);
 | 
			
		||||
        CPU_SUBSTRATE = SimpleItem.register("cpu_substrate", ItemGroups.INGREDIENTS);
 | 
			
		||||
        DRIVE_CONTROLLER = SimpleItem.register("drive_controller", ItemGroups.INGREDIENTS);
 | 
			
		||||
        DRIVE_CASING = SimpleItem.register("drive_casing", ItemGroups.INGREDIENTS);
 | 
			
		||||
 | 
			
		||||
        MODULES = SimpleItem.register("module", moduleList, false, ItemGroups.INGREDIENTS);
 | 
			
		||||
 | 
			
		||||
        HEADS = SimpleItem.register("head", tiers, ItemGroups.INGREDIENTS);
 | 
			
		||||
        PLATTERS = SimpleItem.register("platter", tiers, ItemGroups.INGREDIENTS);
 | 
			
		||||
 | 
			
		||||
        DRIVES = HardDriveItem.register(tiers);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        PolymerResourcePackUtils.addModAssets(MOD_ID);
 | 
			
		||||
        PolymerResourcePackUtils.markAsRequired();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,13 +11,22 @@ import net.minecraft.screen.ScreenHandler;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.collection.DefaultedList;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import systems.brn.server_storage.items.HardDrive;
 | 
			
		||||
import systems.brn.server_storage.screenhandlers.DriveContainerScreenHandler;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.DRIVES;
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.HARD_DRIVE_CONTAINER_BLOCK_ENTITY;
 | 
			
		||||
 | 
			
		||||
public class HardDriveContainerBlockEntity extends LootableContainerBlockEntity {
 | 
			
		||||
    private DefaultedList<ItemStack> inventory;
 | 
			
		||||
    private static final int INVENTORY_SIZE = 9;
 | 
			
		||||
    public DefaultedList<ItemStack> inventory;
 | 
			
		||||
    public ArrayList<HardDrive> drives = new ArrayList<>();
 | 
			
		||||
    public static final int INVENTORY_SIZE = 5;
 | 
			
		||||
 | 
			
		||||
    private int totalSlots;
 | 
			
		||||
    private int usedSlots;
 | 
			
		||||
    private int availableSlots;
 | 
			
		||||
 | 
			
		||||
    public HardDriveContainerBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        super(HARD_DRIVE_CONTAINER_BLOCK_ENTITY, pos, state);
 | 
			
		||||
@@ -65,4 +74,44 @@ public class HardDriveContainerBlockEntity extends LootableContainerBlockEntity
 | 
			
		||||
            Inventories.writeNbt(nbt, this.inventory, registryLookup);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void commitDrives(){
 | 
			
		||||
        for (int i = 0; i < this.inventory.size(); i++) {
 | 
			
		||||
            for (HardDrive drive: this.drives) {
 | 
			
		||||
                if(drive.getContainerIndex() == i){
 | 
			
		||||
                    this.inventory.set(i, drive.getCommitedStack());
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void indexDrives() {
 | 
			
		||||
        drives = new ArrayList<>();
 | 
			
		||||
        totalSlots = 0;
 | 
			
		||||
        availableSlots = 0;
 | 
			
		||||
        usedSlots = 0;
 | 
			
		||||
        for (int i = 0; i < this.inventory.size(); i++) {
 | 
			
		||||
            ItemStack stack = this.inventory.get(i);
 | 
			
		||||
            if (!stack.isEmpty() && DRIVES.contains(stack.getItem())) {
 | 
			
		||||
                HardDrive drive = new HardDrive(stack, this, i);
 | 
			
		||||
                totalSlots += drive.getMaxItems();
 | 
			
		||||
                availableSlots += drive.getAvailableItems();
 | 
			
		||||
                usedSlots += drive.getUsedItems();
 | 
			
		||||
                drives.add(drive);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getTotalSlots() {
 | 
			
		||||
        return totalSlots;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getUsedSlots() {
 | 
			
		||||
        return usedSlots;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getAvailableSlots() {
 | 
			
		||||
        return availableSlots;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,173 @@
 | 
			
		||||
package systems.brn.server_storage.blockentities;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.registry.RegistryWrapper;
 | 
			
		||||
import net.minecraft.state.property.EnumProperty;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import systems.brn.server_storage.lib.ConnectionType;
 | 
			
		||||
import systems.brn.server_storage.lib.StorageNetwork;
 | 
			
		||||
import systems.brn.server_storage.screens.SettingsScreen;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.INVENTORY_INTERFACE_BLOCK_ENTITY;
 | 
			
		||||
import static systems.brn.server_storage.blocks.ConnectedBlock.getPropertyForDirection;
 | 
			
		||||
import static systems.brn.server_storage.lib.StorageOperations.*;
 | 
			
		||||
 | 
			
		||||
public class InventoryInterfaceBlockEntity extends BlockEntity {
 | 
			
		||||
 | 
			
		||||
    public StorageNetwork network;
 | 
			
		||||
 | 
			
		||||
    public final ArrayList<SettingsScreen> openSettingsScreens = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    public boolean isOutput = false;
 | 
			
		||||
 | 
			
		||||
    public String query = "";
 | 
			
		||||
 | 
			
		||||
    public int tickCounter = 0;
 | 
			
		||||
 | 
			
		||||
    public Direction direction = Direction.NORTH;
 | 
			
		||||
 | 
			
		||||
    public InventoryInterfaceBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        super(INVENTORY_INTERFACE_BLOCK_ENTITY, pos, state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void reindexDrives() {
 | 
			
		||||
        if (this.network != null) {
 | 
			
		||||
            this.network.reindexNetwork(world, this.pos, false, query);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.network = new StorageNetwork(world, this.pos, false, query);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateDisplays() {
 | 
			
		||||
        for (SettingsScreen screen : openSettingsScreens) {
 | 
			
		||||
            screen.updateDisplay();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void nextDirection() {
 | 
			
		||||
        int newId = (direction.getId() + 1) % 6;
 | 
			
		||||
        direction = Direction.byId(newId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Serialize the BlockEntity
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
 | 
			
		||||
        // Save the current value of the number to the nbt
 | 
			
		||||
        nbt.putBoolean("isOutput", isOutput);
 | 
			
		||||
        nbt.putInt("direction", direction.getId());
 | 
			
		||||
        nbt.putInt("tickCounter", tickCounter);
 | 
			
		||||
        nbt.putString("query", query);
 | 
			
		||||
        super.writeNbt(nbt, wrapperLookup);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Deserialize the BlockEntity
 | 
			
		||||
    @Override
 | 
			
		||||
    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
 | 
			
		||||
        super.readNbt(nbt, wrapperLookup);
 | 
			
		||||
        isOutput = nbt.getBoolean("isOutput");
 | 
			
		||||
        direction = Direction.byId(nbt.getInt("direction"));
 | 
			
		||||
        tickCounter = nbt.getInt("tickCounter");
 | 
			
		||||
        query = nbt.getString("query");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static int processIncomingInternal(ItemStack stack, int count, InventoryInterfaceBlockEntity blockEntity, Inventory targetedBlockEntityInventory) {
 | 
			
		||||
        int maxFit = howMuchFits(stack, targetedBlockEntityInventory);
 | 
			
		||||
        int finalCount = Math.min(count, maxFit);
 | 
			
		||||
        ItemStack insertedStack = stack.copy();
 | 
			
		||||
        insertedStack.setCount(finalCount);
 | 
			
		||||
        blockEntity.network.removeItemStack(insertedStack);
 | 
			
		||||
        blockEntity.network.updateDisplays();
 | 
			
		||||
        int remainingToInsert = finalCount;
 | 
			
		||||
        for (int i = 0; i < Math.ceilDivExact(finalCount, stack.getMaxCount()); i++) {
 | 
			
		||||
            ItemStack cappedStack = insertedStack.copy();
 | 
			
		||||
            cappedStack.setCount(Math.min(insertedStack.getMaxCount(), remainingToInsert));
 | 
			
		||||
 | 
			
		||||
            ItemStack remaining = insertStackIntoInventory(targetedBlockEntityInventory, cappedStack.copy());
 | 
			
		||||
            if (!remaining.isEmpty()) {
 | 
			
		||||
                ItemStack reverseStack = stack.copy();
 | 
			
		||||
                reverseStack.setCount(remaining.getCount() + remainingToInsert);
 | 
			
		||||
                blockEntity.network.putItemStackRemainder(reverseStack);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            remainingToInsert -= cappedStack.getCount();
 | 
			
		||||
        }
 | 
			
		||||
        return count - (finalCount - remainingToInsert);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int processIncoming(ItemStack stack, int count) {
 | 
			
		||||
        if (world != null && isOutput && filterItem(stack.getItem(), query)) {
 | 
			
		||||
            BlockPos targetedPos = pos.offset(direction);
 | 
			
		||||
            BlockEntity targetedBlockEntity = world.getBlockEntity(targetedPos);
 | 
			
		||||
            EnumProperty<ConnectionType> connectionType = getPropertyForDirection(direction);
 | 
			
		||||
            BlockState thisState = world.getBlockState(pos);
 | 
			
		||||
            if (targetedBlockEntity instanceof Inventory targetedBlockEntityInventory &&
 | 
			
		||||
                    thisState.contains(connectionType) &&
 | 
			
		||||
                    thisState.get(connectionType) == ConnectionType.INVENTORY) {
 | 
			
		||||
                reindexDrives();
 | 
			
		||||
 | 
			
		||||
                return processIncomingInternal(stack, count, this, targetedBlockEntityInventory);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return count;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static <T extends BlockEntity> void tick(World world, BlockPos blockPos, BlockState state, T t) {
 | 
			
		||||
        InventoryInterfaceBlockEntity blockEntity = (InventoryInterfaceBlockEntity) world.getBlockEntity(blockPos);
 | 
			
		||||
        if (blockEntity != null) {
 | 
			
		||||
            if (blockEntity.tickCounter == 0) {
 | 
			
		||||
                BlockPos targetedPos = blockPos.offset(blockEntity.direction);
 | 
			
		||||
                BlockEntity targetedBlockEntity = world.getBlockEntity(targetedPos);
 | 
			
		||||
                BlockState thisState = world.getBlockState(blockPos);
 | 
			
		||||
                EnumProperty<ConnectionType> connectionType = getPropertyForDirection(blockEntity.direction);
 | 
			
		||||
                if (targetedBlockEntity instanceof Inventory targetedBlockEntityInventory &&
 | 
			
		||||
                        thisState.contains(connectionType) &&
 | 
			
		||||
                        thisState.get(connectionType) == ConnectionType.INVENTORY) {
 | 
			
		||||
                    blockEntity.reindexDrives();
 | 
			
		||||
 | 
			
		||||
                    if (blockEntity.isOutput) {
 | 
			
		||||
                        for (Map.Entry<ItemStack, Integer> entry : blockEntity.network.filteredItemStackMap.entrySet()) {
 | 
			
		||||
                            int leftOver = processIncomingInternal(entry.getKey(), entry.getValue(), blockEntity, targetedBlockEntityInventory);
 | 
			
		||||
                            if (leftOver > 0) {
 | 
			
		||||
                                break;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        Map<ItemStack, Integer> targetedBlockInventoryMap = new HashMap<>();
 | 
			
		||||
                        addInventoryToMap(targetedBlockEntityInventory, targetedBlockInventoryMap);
 | 
			
		||||
                        targetedBlockInventoryMap = sortAndFilterMap(targetedBlockInventoryMap, false, blockEntity.query);
 | 
			
		||||
                        for (Map.Entry<ItemStack, Integer> entry : targetedBlockInventoryMap.entrySet()) {
 | 
			
		||||
                            ItemStack stack = entry.getKey();
 | 
			
		||||
                            int count = entry.getValue();
 | 
			
		||||
                            ItemStack insertingStack = stack.copy();
 | 
			
		||||
                            insertingStack.setCount(count);
 | 
			
		||||
                            if (count > 0) {
 | 
			
		||||
                                int canPutInside = count - blockEntity.network.putItemStackRemainder(insertingStack.copy());
 | 
			
		||||
                                blockEntity.network.updateDisplays();
 | 
			
		||||
                                if (canPutInside > 0) {
 | 
			
		||||
                                    removeFromInventory(targetedBlockEntityInventory, insertingStack.copy(), canPutInside);
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            blockEntity.tickCounter = (blockEntity.tickCounter + 1) % 160;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void doSearch(String query) {
 | 
			
		||||
        this.query = query;
 | 
			
		||||
        reindexDrives();
 | 
			
		||||
        updateDisplays();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,181 +0,0 @@
 | 
			
		||||
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.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.registry.RegistryWrapper;
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
public class StorageBlockEntity extends BlockEntity implements Inventory, SidedInventory {
 | 
			
		||||
 | 
			
		||||
    public void removeScreen(StorageScreen storageScreenToDelete) {
 | 
			
		||||
        openStorageScreens.remove(storageScreenToDelete);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Boolean sortAlphabetically = false;
 | 
			
		||||
    public Boolean allInventories = false;
 | 
			
		||||
    public Boolean autoSuck = false;
 | 
			
		||||
    public String searchString = "";
 | 
			
		||||
    public int page = 0;
 | 
			
		||||
    public ConnectedChests chests;
 | 
			
		||||
 | 
			
		||||
    public ArrayList<StorageScreen> openStorageScreens = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    public StorageBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        super(STORAGE_BLOCK_ENTITY, pos, state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void rescanChests() {
 | 
			
		||||
        this.chests = new ConnectedChests(world, this.pos, sortAlphabetically, searchString, allInventories);
 | 
			
		||||
        if(autoSuck){
 | 
			
		||||
            this.chests.autoSuck();
 | 
			
		||||
        }
 | 
			
		||||
        this.updateDisplays();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int size() {
 | 
			
		||||
        if (chests != null) {
 | 
			
		||||
            this.rescanChests();
 | 
			
		||||
            return chests.inventory.size();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean isEmpty() {
 | 
			
		||||
        if (chests != null) {
 | 
			
		||||
            this.rescanChests();
 | 
			
		||||
            return chests.inventory.isEmpty();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack getStack(int slot) {
 | 
			
		||||
        if (chests != null) {
 | 
			
		||||
            this.rescanChests();
 | 
			
		||||
            return chests.inventory.getStack(slot);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack removeStack(int slot, int amount) {
 | 
			
		||||
        if (chests != null) {
 | 
			
		||||
            ItemStack stackToRemove = chests.inventory.getStack(slot);
 | 
			
		||||
            stackToRemove.setCount(
 | 
			
		||||
                    Math.min(
 | 
			
		||||
                            Math.min(stackToRemove.getCount(), amount), stackToRemove.getMaxCount())
 | 
			
		||||
            );
 | 
			
		||||
            return chests.removeItemStack(stackToRemove);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack removeStack(int slot) {
 | 
			
		||||
        if (chests != null) {
 | 
			
		||||
            ItemStack stackToRemove = chests.inventory.getStack(slot);
 | 
			
		||||
            stackToRemove.setCount(Math.min(stackToRemove.getCount(), stackToRemove.getMaxCount()));
 | 
			
		||||
            return chests.removeItemStack(stackToRemove);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void setStack(int slot, ItemStack stack) {
 | 
			
		||||
        chests.tryPutItemStack(stack);
 | 
			
		||||
        updateDisplays();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateDisplays() {
 | 
			
		||||
        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) {
 | 
			
		||||
        if(this.chests != null) {
 | 
			
		||||
            this.rescanChests();
 | 
			
		||||
            int[] output = new int[chests.inventory.size()];
 | 
			
		||||
            for (int i = 0; i < chests.inventory.size() - 1; i++) {
 | 
			
		||||
                output[i] = i;
 | 
			
		||||
            }
 | 
			
		||||
            return output;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return new int[0];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean canInsert(int slot, ItemStack stack, Direction dir) {
 | 
			
		||||
        rescanChests();
 | 
			
		||||
        return chests.canAddItemStack(stack);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean canExtract(int slot, ItemStack stack, Direction dir) {
 | 
			
		||||
        rescanChests();
 | 
			
		||||
        return chests.canRemove(stack);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Serialize the BlockEntity
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
 | 
			
		||||
        // Save the current value of the number to the nbt
 | 
			
		||||
        nbt.putInt("page", page);
 | 
			
		||||
        nbt.putBoolean("sortAlphabetically", sortAlphabetically);
 | 
			
		||||
        nbt.putString("searchString", searchString);
 | 
			
		||||
        nbt.putBoolean("allInventories", allInventories);
 | 
			
		||||
        nbt.putBoolean("autoSuck", autoSuck);
 | 
			
		||||
 | 
			
		||||
        super.writeNbt(nbt, wrapperLookup);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Deserialize the BlockEntity
 | 
			
		||||
    @Override
 | 
			
		||||
    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
 | 
			
		||||
        super.readNbt(nbt, wrapperLookup);
 | 
			
		||||
 | 
			
		||||
        page = nbt.getInt("page");
 | 
			
		||||
        sortAlphabetically = nbt.getBoolean("sortAlphabetically");
 | 
			
		||||
        searchString = nbt.getString("searchString");
 | 
			
		||||
        allInventories = nbt.getBoolean("allInventories");
 | 
			
		||||
        autoSuck = nbt.getBoolean("autoSuck");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,71 @@
 | 
			
		||||
package systems.brn.server_storage.blockentities;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.nbt.NbtCompound;
 | 
			
		||||
import net.minecraft.registry.RegistryWrapper;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import systems.brn.server_storage.lib.StorageNetwork;
 | 
			
		||||
import systems.brn.server_storage.screens.StorageScreen;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.STORAGE_INTERFACE_BLOCK_ENTITY;
 | 
			
		||||
 | 
			
		||||
public class StorageInterfaceBlockEntity extends BlockEntity {
 | 
			
		||||
 | 
			
		||||
    public void removeScreen(StorageScreen storageScreenToDelete) {
 | 
			
		||||
        openStorageScreens.remove(storageScreenToDelete);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Boolean sortAlphabetically = false;
 | 
			
		||||
    public String searchString = "";
 | 
			
		||||
    public int page = 0;
 | 
			
		||||
    public StorageNetwork network;
 | 
			
		||||
 | 
			
		||||
    public final ArrayList<StorageScreen> openStorageScreens = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
    public StorageInterfaceBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        super(STORAGE_INTERFACE_BLOCK_ENTITY, pos, state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void justReindexDrives() {
 | 
			
		||||
        if (this.network != null) {
 | 
			
		||||
            this.network.reindexNetwork(world, this.pos, sortAlphabetically, searchString);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.network = new StorageNetwork(world, this.pos, sortAlphabetically, searchString);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void reindexDrives() {
 | 
			
		||||
        justReindexDrives();
 | 
			
		||||
        this.network.updateDisplays();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateDisplays() {
 | 
			
		||||
        for (StorageScreen screen : openStorageScreens) {
 | 
			
		||||
            screen.updateDisplay();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Serialize the BlockEntity
 | 
			
		||||
    @Override
 | 
			
		||||
    public void writeNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
 | 
			
		||||
        // Save the current value of the number to the nbt
 | 
			
		||||
        nbt.putInt("page", page);
 | 
			
		||||
        nbt.putBoolean("sortAlphabetically", sortAlphabetically);
 | 
			
		||||
        nbt.putString("searchString", searchString);
 | 
			
		||||
 | 
			
		||||
        super.writeNbt(nbt, wrapperLookup);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Deserialize the BlockEntity
 | 
			
		||||
    @Override
 | 
			
		||||
    public void readNbt(NbtCompound nbt, RegistryWrapper.WrapperLookup wrapperLookup) {
 | 
			
		||||
        super.readNbt(nbt, wrapperLookup);
 | 
			
		||||
 | 
			
		||||
        page = nbt.getInt("page");
 | 
			
		||||
        sortAlphabetically = nbt.getBoolean("sortAlphabetically");
 | 
			
		||||
        searchString = nbt.getString("searchString");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,40 @@
 | 
			
		||||
package systems.brn.server_storage.blocks;
 | 
			
		||||
 | 
			
		||||
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 net.minecraft.block.*;
 | 
			
		||||
import net.minecraft.registry.Registries;
 | 
			
		||||
import net.minecraft.registry.Registry;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.*;
 | 
			
		||||
 | 
			
		||||
public class BusConnectorBlock extends ConnectedBlock implements PolymerTexturedBlock {
 | 
			
		||||
    final Identifier identifier;
 | 
			
		||||
    private final BlockState polymerBlockState;
 | 
			
		||||
 | 
			
		||||
    public BusConnectorBlock(Settings settings, Identifier identifier) {
 | 
			
		||||
        super(settings, Blocks.NOTE_BLOCK);
 | 
			
		||||
        this.identifier = identifier;
 | 
			
		||||
        this.polymerBlockState = PolymerBlockResourceUtils.requestBlock(
 | 
			
		||||
                BlockModelType.FULL_BLOCK,
 | 
			
		||||
                PolymerBlockModel.of(
 | 
			
		||||
                        identifier.withPath("block/" + identifier.getPath())
 | 
			
		||||
                )
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockState getPolymerBlockState(BlockState state) {
 | 
			
		||||
        return this.polymerBlockState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void register() {
 | 
			
		||||
        var modId = id(BUS_CONNECTOR_MODEL_ID);
 | 
			
		||||
        BUS_CONNECTOR_BLOCK = Registry.register(Registries.BLOCK, modId,
 | 
			
		||||
                new BusConnectorBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), modId));
 | 
			
		||||
        BUS_CONNECTOR_BLOCK.setDefaultState();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,90 @@
 | 
			
		||||
package systems.brn.server_storage.blocks;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.polymer.core.api.block.SimplePolymerBlock;
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.entity.LivingEntity;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.state.StateManager;
 | 
			
		||||
import net.minecraft.state.property.EnumProperty;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import systems.brn.server_storage.lib.ConnectionType;
 | 
			
		||||
 | 
			
		||||
public class ConnectedBlock extends SimplePolymerBlock {
 | 
			
		||||
 | 
			
		||||
    public static final EnumProperty<ConnectionType> NORTH = EnumProperty.of("north", ConnectionType.class);
 | 
			
		||||
    public static final EnumProperty<ConnectionType> SOUTH = EnumProperty.of("south", ConnectionType.class);
 | 
			
		||||
    public static final EnumProperty<ConnectionType> WEST = EnumProperty.of("west", ConnectionType.class);
 | 
			
		||||
    public static final EnumProperty<ConnectionType> EAST = EnumProperty.of("east", ConnectionType.class);
 | 
			
		||||
    public static final EnumProperty<ConnectionType> UP = EnumProperty.of("up", ConnectionType.class);
 | 
			
		||||
    public static final EnumProperty<ConnectionType> DOWN = EnumProperty.of("down", ConnectionType.class);
 | 
			
		||||
 | 
			
		||||
    public void setDefaultState() {
 | 
			
		||||
        setDefaultState(getStateManager().getDefaultState()
 | 
			
		||||
                .with(NORTH, ConnectionType.NONE)
 | 
			
		||||
                .with(SOUTH, ConnectionType.NONE)
 | 
			
		||||
                .with(WEST, ConnectionType.NONE)
 | 
			
		||||
                .with(EAST, ConnectionType.NONE)
 | 
			
		||||
                .with(UP, ConnectionType.NONE)
 | 
			
		||||
                .with(DOWN, ConnectionType.NONE));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ConnectedBlock(Settings settings, Block block) {
 | 
			
		||||
        super(settings, block);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onPlaced(World world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
 | 
			
		||||
        super.onPlaced(world, pos, state, placer, itemStack);
 | 
			
		||||
        updateBlockState(world, pos, state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
 | 
			
		||||
        builder.add(NORTH, SOUTH, WEST, EAST, UP, DOWN);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateBlockState(World world, BlockPos pos, BlockState state) {
 | 
			
		||||
        world.setBlockState(pos, updateState(state, world, pos), Block.NOTIFY_LISTENERS);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void neighborUpdate(BlockState state, World world, BlockPos pos, Block block, BlockPos fromPos, boolean notify) {
 | 
			
		||||
        updateBlockState(world, pos, state);
 | 
			
		||||
        super.neighborUpdate(state, world, pos, block, fromPos, notify);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private BlockState updateState(BlockState state, World world, BlockPos pos) {
 | 
			
		||||
        for (Direction direction : Direction.values()) {
 | 
			
		||||
            BlockPos neighborPos = pos.offset(direction);
 | 
			
		||||
            BlockState neighborState = world.getBlockState(neighborPos);
 | 
			
		||||
            boolean isConnectedToBus = neighborState.getBlock() instanceof ConnectedBlock;
 | 
			
		||||
            BlockEntity blockEntity = world.getBlockEntity(neighborPos);
 | 
			
		||||
            boolean isConnectedToInventory = blockEntity instanceof Inventory;
 | 
			
		||||
            ConnectionType connectionType = ConnectionType.NONE;
 | 
			
		||||
            if (isConnectedToBus){
 | 
			
		||||
                connectionType = ConnectionType.BUS;
 | 
			
		||||
            } else if (isConnectedToInventory){
 | 
			
		||||
                connectionType = ConnectionType.INVENTORY;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            state = state.with(getPropertyForDirection(direction), connectionType);
 | 
			
		||||
        }
 | 
			
		||||
        return state;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static EnumProperty<ConnectionType> getPropertyForDirection(Direction direction) {
 | 
			
		||||
        return switch (direction) {
 | 
			
		||||
            case NORTH -> NORTH;
 | 
			
		||||
            case SOUTH -> SOUTH;
 | 
			
		||||
            case WEST -> WEST;
 | 
			
		||||
            case EAST -> EAST;
 | 
			
		||||
            case UP -> UP;
 | 
			
		||||
            case DOWN -> DOWN;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,7 +5,6 @@ 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 eu.pb4.polymer.core.api.block.SimplePolymerBlock;
 | 
			
		||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
 | 
			
		||||
import net.minecraft.block.*;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
@@ -29,7 +28,7 @@ import systems.brn.server_storage.blockentities.HardDriveContainerBlockEntity;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.*;
 | 
			
		||||
 | 
			
		||||
public class HardDriveContainerBlock extends SimplePolymerBlock implements PolymerTexturedBlock, BlockEntityProvider {
 | 
			
		||||
public class HardDriveContainerBlock extends ConnectedBlock implements PolymerTexturedBlock, BlockEntityProvider {
 | 
			
		||||
 | 
			
		||||
    final Identifier identifier;
 | 
			
		||||
    public static final DirectionProperty FACING = FacingBlock.FACING;
 | 
			
		||||
@@ -49,6 +48,7 @@ public class HardDriveContainerBlock extends SimplePolymerBlock implements Polym
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
 | 
			
		||||
        super.appendProperties(builder);
 | 
			
		||||
        builder.add(FACING);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -63,12 +63,14 @@ public class HardDriveContainerBlock extends SimplePolymerBlock implements Polym
 | 
			
		||||
                new HardDriveContainerBlock(Settings.copy(Blocks.WHITE_WOOL), modId));
 | 
			
		||||
        UseBlockCallback.EVENT.register(HardDriveContainerBlock::onUse);
 | 
			
		||||
 | 
			
		||||
        HARD_DRIVE_CONTAINER_BLOCK.setDefaultState();
 | 
			
		||||
 | 
			
		||||
        HARD_DRIVE_CONTAINER_BLOCK_ENTITY = Registry.register(
 | 
			
		||||
                Registries.BLOCK_ENTITY_TYPE,
 | 
			
		||||
                modId,
 | 
			
		||||
                BlockEntityType.Builder.create(HardDriveContainerBlockEntity::new, HARD_DRIVE_CONTAINER_BLOCK).build(null)
 | 
			
		||||
        );
 | 
			
		||||
        PolymerBlockUtils.registerBlockEntity(STORAGE_BLOCK_ENTITY);
 | 
			
		||||
        PolymerBlockUtils.registerBlockEntity(STORAGE_INTERFACE_BLOCK_ENTITY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static ActionResult onUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,179 @@
 | 
			
		||||
package systems.brn.server_storage.blocks;
 | 
			
		||||
 | 
			
		||||
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 eu.pb4.sgui.api.elements.GuiElementBuilder;
 | 
			
		||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
 | 
			
		||||
import net.minecraft.block.*;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntityTicker;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntityType;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.item.ItemPlacementContext;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
import net.minecraft.registry.Registries;
 | 
			
		||||
import net.minecraft.registry.Registry;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.server.world.ServerWorld;
 | 
			
		||||
import net.minecraft.state.StateManager;
 | 
			
		||||
import net.minecraft.state.property.DirectionProperty;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.ActionResult;
 | 
			
		||||
import net.minecraft.util.Formatting;
 | 
			
		||||
import net.minecraft.util.Hand;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import net.minecraft.util.hit.BlockHitResult;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
import systems.brn.server_storage.blockentities.InventoryInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
import systems.brn.server_storage.screens.SearchScreen;
 | 
			
		||||
import systems.brn.server_storage.screens.SettingsScreen;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.*;
 | 
			
		||||
import static systems.brn.server_storage.lib.PagedGui.*;
 | 
			
		||||
 | 
			
		||||
public class InventoryInterfaceBlock extends ConnectedBlock implements PolymerTexturedBlock, BlockEntityProvider {
 | 
			
		||||
    final Identifier identifier;
 | 
			
		||||
    public static final DirectionProperty FACING = FacingBlock.FACING;
 | 
			
		||||
    private final BlockState polymerBlockState;
 | 
			
		||||
 | 
			
		||||
    public InventoryInterfaceBlock(Settings settings, Identifier identifier) {
 | 
			
		||||
        super(settings, Blocks.NOTE_BLOCK);
 | 
			
		||||
        this.identifier = identifier;
 | 
			
		||||
        this.setDefaultState(this.stateManager.getDefaultState().with(FACING, Direction.NORTH));
 | 
			
		||||
        this.polymerBlockState = PolymerBlockResourceUtils.requestBlock(BlockModelType.FULL_BLOCK, PolymerBlockModel.of(identifier.withPath("block/" + identifier.getPath())));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockState getPlacementState(ItemPlacementContext ctx) {
 | 
			
		||||
        return this.getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing().getOpposite());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
 | 
			
		||||
        super.appendProperties(builder);
 | 
			
		||||
        builder.add(FACING);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockState getPolymerBlockState(BlockState state) {
 | 
			
		||||
        return this.polymerBlockState;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void register() {
 | 
			
		||||
        var modId = id(INVENTORY_INTERFACE_BLOCK_MODEL_ID);
 | 
			
		||||
        INVENTORY_INTERFACE_BLOCK = Registry.register(Registries.BLOCK, modId,
 | 
			
		||||
                new InventoryInterfaceBlock(Settings.copy(Blocks.WHITE_WOOL), modId));
 | 
			
		||||
        UseBlockCallback.EVENT.register(InventoryInterfaceBlock::onUse);
 | 
			
		||||
        INVENTORY_INTERFACE_BLOCK.setDefaultState();
 | 
			
		||||
        INVENTORY_INTERFACE_BLOCK_ENTITY = Registry.register(
 | 
			
		||||
                Registries.BLOCK_ENTITY_TYPE,
 | 
			
		||||
                modId,
 | 
			
		||||
                BlockEntityType.Builder.create(InventoryInterfaceBlockEntity::new, INVENTORY_INTERFACE_BLOCK).build(null)
 | 
			
		||||
        );
 | 
			
		||||
        PolymerBlockUtils.registerBlockEntity(INVENTORY_INTERFACE_BLOCK_ENTITY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void loadSettings(SettingsScreen settingsScreen, InventoryInterfaceBlockEntity blockEntity) {
 | 
			
		||||
        settingsScreen.clearSettings();
 | 
			
		||||
        settingsScreen.addSetting(PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(switch (blockEntity.direction) {
 | 
			
		||||
                            case NORTH -> "gui.serverstorage.direction_north";
 | 
			
		||||
                            case SOUTH -> "gui.serverstorage.direction_south";
 | 
			
		||||
                            case WEST -> "gui.serverstorage.direction_west";
 | 
			
		||||
                            case EAST -> "gui.serverstorage.direction_east";
 | 
			
		||||
                            case UP -> "gui.serverstorage.direction_up";
 | 
			
		||||
                            case DOWN -> "gui.serverstorage.direction_down";
 | 
			
		||||
                        }).formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(switch (blockEntity.direction) {
 | 
			
		||||
                            case NORTH -> GUI_SIDE_NORTH;
 | 
			
		||||
                            case SOUTH -> GUI_SIDE_SOUTH;
 | 
			
		||||
                            case WEST -> GUI_SIDE_WEST;
 | 
			
		||||
                            case EAST -> GUI_SIDE_EAST;
 | 
			
		||||
                            case UP -> GUI_SIDE_UP;
 | 
			
		||||
                            case DOWN -> GUI_SIDE_DOWN;
 | 
			
		||||
                        })
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            playClickSound(settingsScreen.getPlayer());
 | 
			
		||||
                            blockEntity.nextDirection();
 | 
			
		||||
                            loadSettings(settingsScreen, blockEntity);
 | 
			
		||||
                            blockEntity.updateDisplays();
 | 
			
		||||
                        })
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        settingsScreen.addSetting(PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(blockEntity.isOutput ? "gui.serverstorage.mode_output" : "gui.serverstorage.mode_input").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(blockEntity.isOutput ? GUI_MODE_OUTPUT : GUI_MODE_INPUT)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            playClickSound(settingsScreen.getPlayer());
 | 
			
		||||
                            blockEntity.isOutput ^= true;
 | 
			
		||||
                            loadSettings(settingsScreen, blockEntity);
 | 
			
		||||
                            blockEntity.updateDisplays();
 | 
			
		||||
                        })
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        String queryNow = blockEntity.query;
 | 
			
		||||
        if (queryNow == null || queryNow.isEmpty() || queryNow.equals("*")) {
 | 
			
		||||
            queryNow = "Filter not set";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        settingsScreen.addSetting(PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.literal(queryNow).formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_QUESTION_MARK)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            SearchScreen searchScreen = new SearchScreen(settingsScreen, "");
 | 
			
		||||
                            playClickSound(settingsScreen.getPlayer());
 | 
			
		||||
                            searchScreen.open();
 | 
			
		||||
                        })
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static ActionResult onUse(PlayerEntity playerEntity, World world, Hand hand, BlockHitResult hitResult) {
 | 
			
		||||
        BlockPos pos = hitResult.getBlockPos();
 | 
			
		||||
        BlockState state = world.getBlockState(pos);
 | 
			
		||||
        Block block = state.getBlock();
 | 
			
		||||
 | 
			
		||||
        if (block instanceof InventoryInterfaceBlock) {
 | 
			
		||||
            BlockEntity tempBlockEntity = world.getBlockEntity(pos);
 | 
			
		||||
            if (tempBlockEntity instanceof InventoryInterfaceBlockEntity blockEntity) {
 | 
			
		||||
                if (!world.isClient && !playerEntity.isSpectator()) {
 | 
			
		||||
                    ServerPlayerEntity player = (ServerPlayerEntity) playerEntity;
 | 
			
		||||
                    if (!player.isSneaking()) {
 | 
			
		||||
                        SettingsScreen settingsScreen = new SettingsScreen(player, blockEntity);
 | 
			
		||||
                        blockEntity.reindexDrives();
 | 
			
		||||
                        loadSettings(settingsScreen, blockEntity);
 | 
			
		||||
                        settingsScreen.updateDisplay();
 | 
			
		||||
                        settingsScreen.open();
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return ActionResult.PASS;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                return ActionResult.SUCCESS;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return ActionResult.PASS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public <T extends BlockEntity> BlockEntityTicker<T> getTicker(World world, BlockState state, BlockEntityType<T> type) {
 | 
			
		||||
        return world instanceof ServerWorld && type == INVENTORY_INTERFACE_BLOCK_ENTITY ? InventoryInterfaceBlockEntity::tick : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        return new InventoryInterfaceBlockEntity(pos, state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -5,7 +5,6 @@ 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 eu.pb4.polymer.core.api.block.SimplePolymerBlock;
 | 
			
		||||
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
 | 
			
		||||
import net.minecraft.block.*;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
@@ -31,7 +30,7 @@ import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.screens.StorageScreen;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
@@ -39,12 +38,12 @@ import java.util.List;
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.*;
 | 
			
		||||
import static systems.brn.server_storage.lib.Util.generateBookContent;
 | 
			
		||||
 | 
			
		||||
public class StorageBlock extends SimplePolymerBlock implements PolymerTexturedBlock, BlockEntityProvider {
 | 
			
		||||
public class StorageInterfaceBlock extends ConnectedBlock implements PolymerTexturedBlock, BlockEntityProvider {
 | 
			
		||||
    final Identifier identifier;
 | 
			
		||||
    public static final DirectionProperty FACING = FacingBlock.FACING;
 | 
			
		||||
    private final BlockState polymerBlockState;
 | 
			
		||||
 | 
			
		||||
    public StorageBlock(Settings settings, Identifier identifier) {
 | 
			
		||||
    public StorageInterfaceBlock(Settings settings, Identifier identifier) {
 | 
			
		||||
        super(settings, Blocks.NOTE_BLOCK);
 | 
			
		||||
        this.identifier = identifier;
 | 
			
		||||
        this.setDefaultState(this.stateManager.getDefaultState().with(FACING, Direction.NORTH));
 | 
			
		||||
@@ -58,6 +57,7 @@ public class StorageBlock extends SimplePolymerBlock implements PolymerTexturedB
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
 | 
			
		||||
        super.appendProperties(builder);
 | 
			
		||||
        builder.add(FACING);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -68,16 +68,16 @@ public class StorageBlock extends SimplePolymerBlock implements PolymerTexturedB
 | 
			
		||||
 | 
			
		||||
    public static void register() {
 | 
			
		||||
        var modId = id(STORAGE_MODEL_ID);
 | 
			
		||||
        STORAGE_BLOCK = Registry.register(Registries.BLOCK, modId,
 | 
			
		||||
                new StorageBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), modId));
 | 
			
		||||
        UseBlockCallback.EVENT.register(StorageBlock::onUse);
 | 
			
		||||
 | 
			
		||||
        STORAGE_BLOCK_ENTITY = Registry.register(
 | 
			
		||||
        STORAGE_INTERFACE_BLOCK = Registry.register(Registries.BLOCK, modId,
 | 
			
		||||
                new StorageInterfaceBlock(AbstractBlock.Settings.copy(Blocks.WHITE_WOOL), modId));
 | 
			
		||||
        UseBlockCallback.EVENT.register(StorageInterfaceBlock::onUse);
 | 
			
		||||
        STORAGE_INTERFACE_BLOCK.setDefaultState();
 | 
			
		||||
        STORAGE_INTERFACE_BLOCK_ENTITY = Registry.register(
 | 
			
		||||
                Registries.BLOCK_ENTITY_TYPE,
 | 
			
		||||
                modId,
 | 
			
		||||
                BlockEntityType.Builder.create(StorageBlockEntity::new, STORAGE_BLOCK).build(null)
 | 
			
		||||
                BlockEntityType.Builder.create(StorageInterfaceBlockEntity::new, STORAGE_INTERFACE_BLOCK).build(null)
 | 
			
		||||
        );
 | 
			
		||||
        PolymerBlockUtils.registerBlockEntity(STORAGE_BLOCK_ENTITY);
 | 
			
		||||
        PolymerBlockUtils.registerBlockEntity(STORAGE_INTERFACE_BLOCK_ENTITY);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static ActionResult onUse(PlayerEntity player, World world, Hand hand, BlockHitResult hitResult) {
 | 
			
		||||
@@ -85,17 +85,18 @@ public class StorageBlock extends SimplePolymerBlock implements PolymerTexturedB
 | 
			
		||||
        BlockState state = world.getBlockState(pos);
 | 
			
		||||
        Block block = state.getBlock();
 | 
			
		||||
 | 
			
		||||
        if (block instanceof StorageBlock) {
 | 
			
		||||
        if (block instanceof StorageInterfaceBlock) {
 | 
			
		||||
            if (!world.isClient && !player.isSpectator()) {
 | 
			
		||||
                if (!player.isSneaking()) {
 | 
			
		||||
                    StorageScreen storageScreen = new StorageScreen((ServerPlayerEntity) player, pos, null);
 | 
			
		||||
                    storageScreen.updateDisplay();
 | 
			
		||||
                    storageScreen.open();
 | 
			
		||||
 | 
			
		||||
                } else if (player.getStackInHand(hand).getItem() == Items.WRITTEN_BOOK) {
 | 
			
		||||
                    ItemStack book = player.getStackInHand(hand);
 | 
			
		||||
                    StorageBlockEntity storageBlockEntity = (StorageBlockEntity) world.getBlockEntity(pos);
 | 
			
		||||
                    assert storageBlockEntity != null;
 | 
			
		||||
                    List<RawFilteredPair<Text>> generatedContent = generateBookContent(storageBlockEntity.chests.inventory);
 | 
			
		||||
                    StorageInterfaceBlockEntity storageInterfaceBlockEntity = (StorageInterfaceBlockEntity) world.getBlockEntity(pos);
 | 
			
		||||
                    assert storageInterfaceBlockEntity != null;
 | 
			
		||||
                    List<RawFilteredPair<Text>> generatedContent = generateBookContent(storageInterfaceBlockEntity.network.itemStackMap);
 | 
			
		||||
                    book.set(DataComponentTypes.WRITTEN_BOOK_CONTENT, new WrittenBookContentComponent(
 | 
			
		||||
                            RawFilteredPair.of("Item Listing"),
 | 
			
		||||
                            player.getGameProfile().getName(),
 | 
			
		||||
@@ -115,6 +116,6 @@ public class StorageBlock extends SimplePolymerBlock implements PolymerTexturedB
 | 
			
		||||
    @Nullable
 | 
			
		||||
    @Override
 | 
			
		||||
    public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
 | 
			
		||||
        return new StorageBlockEntity(pos, state);
 | 
			
		||||
        return new StorageInterfaceBlockEntity(pos, state);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										300
									
								
								src/main/java/systems/brn/server_storage/items/HardDrive.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,300 @@
 | 
			
		||||
package systems.brn.server_storage.items;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.component.DataComponentTypes;
 | 
			
		||||
import net.minecraft.component.type.LoreComponent;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
import net.minecraft.text.Style;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.Formatting;
 | 
			
		||||
import systems.brn.server_storage.blockentities.HardDriveContainerBlockEntity;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.lib.DriveComponents.*;
 | 
			
		||||
import static systems.brn.server_storage.lib.StorageOperations.canCombine;
 | 
			
		||||
 | 
			
		||||
public class HardDrive {
 | 
			
		||||
    private ItemStack driveStack;
 | 
			
		||||
    public final HardDriveContainerBlockEntity blockEntity;
 | 
			
		||||
    private int containerIndex;
 | 
			
		||||
 | 
			
		||||
    private int maxItems;
 | 
			
		||||
    private int usedItems;
 | 
			
		||||
    private int availableItems;
 | 
			
		||||
    private final UUID myUUID;
 | 
			
		||||
    private int tier;
 | 
			
		||||
 | 
			
		||||
    public Map<ItemStack, Integer> items;
 | 
			
		||||
 | 
			
		||||
    public void loadComponents() {
 | 
			
		||||
        Map<ItemStack, Integer> loadedItems = driveStack.getComponents().getOrDefault(ITEMSTACK_MAP, new HashMap<>());
 | 
			
		||||
        if (this.items == null) {
 | 
			
		||||
            this.items = loadedItems;
 | 
			
		||||
        }
 | 
			
		||||
        updateData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void setMaxItems() {
 | 
			
		||||
        String itemName = driveStack.getItem().getRegistryEntry().registryKey().getValue().getPath();
 | 
			
		||||
        switch (itemName) {
 | 
			
		||||
            case "iron_drive":
 | 
			
		||||
                tier = 0;
 | 
			
		||||
                break;
 | 
			
		||||
            case "golden_drive":
 | 
			
		||||
                tier = 1;
 | 
			
		||||
                break;
 | 
			
		||||
            case "diamond_drive":
 | 
			
		||||
                tier = 2;
 | 
			
		||||
                break;
 | 
			
		||||
            case "netherite_drive":
 | 
			
		||||
                tier = 3;
 | 
			
		||||
                break;
 | 
			
		||||
            default:
 | 
			
		||||
                tier = -1;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        maxItems = 0;
 | 
			
		||||
 | 
			
		||||
        if (tier >= 0) {
 | 
			
		||||
            maxItems = (int) Math.pow(2, tier + 8);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateData() {
 | 
			
		||||
        usedItems = 0;
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
 | 
			
		||||
            if (entry.getKey().getItem() == Items.AIR) {
 | 
			
		||||
                items.remove(entry.getKey());
 | 
			
		||||
            } else {
 | 
			
		||||
                usedItems += entry.getValue();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        addLoreInfo();
 | 
			
		||||
        availableItems = maxItems - usedItems;
 | 
			
		||||
        assert maxItems >= usedItems;
 | 
			
		||||
        assert usedItems >= 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void saveComponents() {
 | 
			
		||||
        ItemStack tempStack = driveStack.copy();
 | 
			
		||||
        HashMap<ItemStack, Integer> itemsTemp = new HashMap<>();
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
 | 
			
		||||
            int count = entry.getKey().getCount();
 | 
			
		||||
            if (count > entry.getKey().getMaxCount()) {
 | 
			
		||||
                count = entry.getKey().getMaxCount();
 | 
			
		||||
            }
 | 
			
		||||
            ItemStack limitedStack = entry.getKey().copy();
 | 
			
		||||
            limitedStack.setCount(count);
 | 
			
		||||
            itemsTemp.put(limitedStack, entry.getValue());
 | 
			
		||||
        }
 | 
			
		||||
        tempStack.remove(ITEMSTACK_MAP);
 | 
			
		||||
        tempStack.set(ITEMSTACK_MAP, itemsTemp);
 | 
			
		||||
        driveStack = tempStack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isNotTheSameDrive(ItemStack currentStack) {
 | 
			
		||||
        return currentStack.getItem() != driveStack.getItem() || (currentStack.contains(UUID_COMPONENT) && currentStack.get(UUID_COMPONENT) != myUUID);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack getCommitedStack() {
 | 
			
		||||
        ItemStack tempDriveStack = driveStack.copy();
 | 
			
		||||
        driveStack = ensureUUID(tempDriveStack);
 | 
			
		||||
        loadComponents();
 | 
			
		||||
        updateData();
 | 
			
		||||
        saveComponents();
 | 
			
		||||
        return driveStack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void commitChangesToContainer() {
 | 
			
		||||
        getCommitedStack();
 | 
			
		||||
        ItemStack currentStack = blockEntity.inventory.get(containerIndex);
 | 
			
		||||
        boolean updated = false;
 | 
			
		||||
        if (isNotTheSameDrive(currentStack)) {
 | 
			
		||||
            updateIndex();
 | 
			
		||||
            updated = true;
 | 
			
		||||
        }
 | 
			
		||||
        if (updated && isNotTheSameDrive(currentStack)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        blockEntity.inventory.set(containerIndex, driveStack);
 | 
			
		||||
        blockEntity.markDirty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack removeStackFromInventory(ItemStack stack) {
 | 
			
		||||
        int outCount = 0;
 | 
			
		||||
        ItemStack outStack = stack.copy();
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
 | 
			
		||||
            if (canCombine(entry.getKey(), stack)) {
 | 
			
		||||
                int countInDrive = entry.getValue();
 | 
			
		||||
                int needToRemove = stack.getCount();
 | 
			
		||||
 | 
			
		||||
                if (countInDrive <= needToRemove) {
 | 
			
		||||
                    items.remove(entry.getKey());
 | 
			
		||||
                    needToRemove -= countInDrive;
 | 
			
		||||
                    outCount += needToRemove;
 | 
			
		||||
                } else {
 | 
			
		||||
                    entry.setValue(countInDrive - needToRemove);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        outStack.setCount(outCount);
 | 
			
		||||
        commitChangesToContainer();
 | 
			
		||||
        blockEntity.markDirty();
 | 
			
		||||
        return outStack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack insertStackIntoInventory(ItemStack stack) {
 | 
			
		||||
        // First, try to merge with existing stacks
 | 
			
		||||
        boolean merged = false;
 | 
			
		||||
        if (stack.isEmpty()) {
 | 
			
		||||
            return stack;
 | 
			
		||||
        }
 | 
			
		||||
        int transferAmount = Math.min(stack.getCount(), availableItems);
 | 
			
		||||
        if (transferAmount > 0) {
 | 
			
		||||
            for (Map.Entry<ItemStack, Integer> entry : items.entrySet()) {
 | 
			
		||||
                ItemStack slotStack = entry.getKey();
 | 
			
		||||
                if (canCombine(slotStack, stack)) {
 | 
			
		||||
                    entry.setValue(transferAmount + entry.getValue());
 | 
			
		||||
                    stack.decrement(transferAmount);
 | 
			
		||||
                    merged = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!merged) {
 | 
			
		||||
                ItemStack inStack = stack.copy();
 | 
			
		||||
                inStack.capCount(inStack.getMaxCount());
 | 
			
		||||
                items.put(inStack, transferAmount);
 | 
			
		||||
                stack.decrement(transferAmount);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        commitChangesToContainer();
 | 
			
		||||
        blockEntity.markDirty();
 | 
			
		||||
        if (stack.isEmpty() || stack.getCount() < 1) {
 | 
			
		||||
            return ItemStack.EMPTY;
 | 
			
		||||
        } else {
 | 
			
		||||
            return stack;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void addLoreInfo() {
 | 
			
		||||
        ItemStack tempDriveStack = driveStack.copy();
 | 
			
		||||
 | 
			
		||||
        Formatting availableLineFormatting;
 | 
			
		||||
        Formatting usedLineFormatting;
 | 
			
		||||
 | 
			
		||||
        if (usedItems > maxItems){
 | 
			
		||||
            usedLineFormatting = Formatting.LIGHT_PURPLE;
 | 
			
		||||
        } else if (usedItems == maxItems) {
 | 
			
		||||
            usedLineFormatting = Formatting.RED;
 | 
			
		||||
        } else if (usedItems >= maxItems * 0.8){
 | 
			
		||||
            usedLineFormatting = Formatting.YELLOW;
 | 
			
		||||
        } else if (usedItems >= maxItems * 0.5){
 | 
			
		||||
            usedLineFormatting = Formatting.GOLD;
 | 
			
		||||
        } else {
 | 
			
		||||
            usedLineFormatting = Formatting.GREEN;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (usedItems > maxItems) {
 | 
			
		||||
            availableLineFormatting = Formatting.LIGHT_PURPLE; //how did you do this
 | 
			
		||||
        } else if (usedItems == maxItems) {
 | 
			
		||||
            availableLineFormatting = Formatting.RED; // full
 | 
			
		||||
        } else if (usedItems >= maxItems * 0.9) {
 | 
			
		||||
            availableLineFormatting = Formatting.YELLOW; //90% or more full
 | 
			
		||||
        } else {
 | 
			
		||||
            availableLineFormatting = Formatting.GREEN; //good
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        Formatting totalLineFormatting = switch (tier) {
 | 
			
		||||
            case 0 -> Formatting.DARK_GRAY;
 | 
			
		||||
            case 1 -> Formatting.GOLD;
 | 
			
		||||
            case 2 -> Formatting.AQUA;
 | 
			
		||||
            case 3 -> Formatting.BLACK;
 | 
			
		||||
            default -> Formatting.OBFUSCATED;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        Text usedLine = Text.literal("Used slots: " + usedItems).setStyle(Style.EMPTY.withColor(usedLineFormatting).withItalic(true));
 | 
			
		||||
        Text availableLine = Text.literal("Available slots: " + availableItems).setStyle(Style.EMPTY.withColor(availableLineFormatting).withItalic(true));
 | 
			
		||||
        Text totalLine = Text.literal("Total slots: " + maxItems).setStyle(Style.EMPTY.withColor(totalLineFormatting).withItalic(true));
 | 
			
		||||
 | 
			
		||||
        LoreComponent newLore;
 | 
			
		||||
        List<Text> loreList = new ArrayList<>();
 | 
			
		||||
        loreList.add(availableLine);
 | 
			
		||||
        loreList.add(usedLine);
 | 
			
		||||
        loreList.add(totalLine);
 | 
			
		||||
        newLore = new LoreComponent(loreList);
 | 
			
		||||
 | 
			
		||||
        tempDriveStack.set(DataComponentTypes.LORE, newLore);
 | 
			
		||||
        driveStack = tempDriveStack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void updateIndex() {
 | 
			
		||||
        for (int i = 0; i < blockEntity.inventory.size(); i++) {
 | 
			
		||||
            ItemStack stack = blockEntity.inventory.get(i);
 | 
			
		||||
            UUID foundUUID = stack.getOrDefault(UUID_COMPONENT, null);
 | 
			
		||||
            if (foundUUID != null && foundUUID.equals(myUUID)) {
 | 
			
		||||
                containerIndex = i;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public HardDrive(ItemStack driveStack, HardDriveContainerBlockEntity blockEntity, int containerIndex) {
 | 
			
		||||
        this.driveStack = driveStack;
 | 
			
		||||
        this.blockEntity = blockEntity;
 | 
			
		||||
        this.myUUID = driveStack.get(UUID_COMPONENT);
 | 
			
		||||
        this.containerIndex = containerIndex;
 | 
			
		||||
        setMaxItems();
 | 
			
		||||
        loadComponents();
 | 
			
		||||
        updateData();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getMaxItems() {
 | 
			
		||||
        return maxItems;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getAvailableItems() {
 | 
			
		||||
        return availableItems;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getUsedItems() {
 | 
			
		||||
        return usedItems;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Map<ItemStack, Integer> addToMap(Map<ItemStack, Integer> itemStackMap) {
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> diskEntry : items.entrySet()) {
 | 
			
		||||
            boolean found = false;
 | 
			
		||||
            for (Map.Entry<ItemStack, Integer> mapEntry : itemStackMap.entrySet()) {
 | 
			
		||||
                ItemStack existingStack = mapEntry.getKey();
 | 
			
		||||
                if (ItemStack.areItemsAndComponentsEqual(diskEntry.getKey(), existingStack)) {
 | 
			
		||||
                    int newCount = mapEntry.getValue() + diskEntry.getValue();
 | 
			
		||||
                    itemStackMap.put(existingStack, newCount);
 | 
			
		||||
                    found = true;
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!found) {
 | 
			
		||||
                itemStackMap.put(diskEntry.getKey(), diskEntry.getValue());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return itemStackMap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getContainerIndex() {
 | 
			
		||||
        return containerIndex;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ItemStack ensureUUID(ItemStack driveStack) {
 | 
			
		||||
        if (driveStack.getComponents().contains(UUID_COMPONENT)) {
 | 
			
		||||
            return driveStack;
 | 
			
		||||
        } else {
 | 
			
		||||
            ItemStack tempStack = driveStack.copy();
 | 
			
		||||
            tempStack.set(UUID_COMPONENT, UUID.randomUUID());
 | 
			
		||||
            return tempStack;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -21,18 +21,14 @@ public class HardDriveItem extends SimpleItem {
 | 
			
		||||
 | 
			
		||||
    public static List<Item> register(List<String> tiers){
 | 
			
		||||
        ArrayList<Item> items = new ArrayList<>();
 | 
			
		||||
        int numberItems = 128;
 | 
			
		||||
        for (String tier : tiers) {
 | 
			
		||||
            Identifier identifier = id(tier + "_drive");
 | 
			
		||||
            Item item = Registry.register(Registries.ITEM, identifier, new SimpleItem(new Settings()
 | 
			
		||||
                    .maxCount(1)
 | 
			
		||||
                    .component(DriveComponents.MAX_ITEMS, numberItems)
 | 
			
		||||
                    .component(DriveComponents.USED_ITEMS, 0)
 | 
			
		||||
                    .component(DriveComponents.ITEMSTACK_MAP, new HashMap<>())
 | 
			
		||||
                    , identifier));
 | 
			
		||||
            ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> content.add(item));
 | 
			
		||||
            items.add(item);
 | 
			
		||||
            numberItems *= 2;
 | 
			
		||||
        }
 | 
			
		||||
        return items;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,12 +5,10 @@ import eu.pb4.polymer.core.api.item.SimplePolymerItem;
 | 
			
		||||
import eu.pb4.polymer.resourcepack.api.PolymerModelData;
 | 
			
		||||
import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils;
 | 
			
		||||
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemGroups;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
import net.minecraft.item.*;
 | 
			
		||||
import net.minecraft.registry.Registries;
 | 
			
		||||
import net.minecraft.registry.Registry;
 | 
			
		||||
import net.minecraft.registry.RegistryKey;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.util.Identifier;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
@@ -38,25 +36,35 @@ public class SimpleItem extends SimplePolymerItem implements PolymerItem {
 | 
			
		||||
        return this.polymerModel.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Item register(String name){
 | 
			
		||||
        return register(name, 64);
 | 
			
		||||
    public static Item register(String name, RegistryKey<ItemGroup> group){
 | 
			
		||||
        return register(name, 64, group);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Item register(String name, int maxCount) {
 | 
			
		||||
    public static Item register(String name, int maxCount, RegistryKey<ItemGroup> group) {
 | 
			
		||||
        Identifier identifier = id(name);
 | 
			
		||||
        Item item = Registry.register(Registries.ITEM, identifier, new SimpleItem(new Settings().maxCount(maxCount), identifier));
 | 
			
		||||
        ItemGroupEvents.modifyEntriesEvent(ItemGroups.FUNCTIONAL).register(content -> content.add(item));
 | 
			
		||||
        ItemGroupEvents.modifyEntriesEvent(group).register(content -> content.add(item));
 | 
			
		||||
        return item;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<Item> register(String name, List<String> tiers) {
 | 
			
		||||
        return register(name, tiers, 64);
 | 
			
		||||
    public static List<Item> register(String name, List<String> tiers, boolean tierFirst, RegistryKey<ItemGroup> group) {
 | 
			
		||||
        return register(name, tiers, 64, tierFirst, group);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<Item> register(String name, List<String> tiers, int maxCount) {
 | 
			
		||||
    public static List<Item> register(String name, List<String> tiers, RegistryKey<ItemGroup> group) {
 | 
			
		||||
        return register(name, tiers, 64, true, group);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static List<Item> register(String name, List<String> tiers, int maxCount, boolean tierFirst, RegistryKey<ItemGroup> group) {
 | 
			
		||||
        ArrayList<Item> items = new ArrayList<>();
 | 
			
		||||
        for (String tier : tiers) {
 | 
			
		||||
            items.add(SimpleItem.register(tier + "_" + name, maxCount));
 | 
			
		||||
            String itemName;
 | 
			
		||||
            if (tierFirst){
 | 
			
		||||
                itemName = tier + "_" + name;
 | 
			
		||||
            } else {
 | 
			
		||||
                itemName = name + "_" + tier;
 | 
			
		||||
            }
 | 
			
		||||
            items.add(SimpleItem.register(itemName, maxCount, group));
 | 
			
		||||
        }
 | 
			
		||||
        return items;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,212 +0,0 @@
 | 
			
		||||
package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.block.entity.*;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.inventory.SimpleInventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import systems.brn.server_storage.blockentities.HardDriveContainerBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.items.HardDriveItem;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.lib.StorageOperations.*;
 | 
			
		||||
 | 
			
		||||
public class ConnectedChests {
 | 
			
		||||
    public final List<Inventory> inventories;
 | 
			
		||||
    public final List<Inventory> hoppers;
 | 
			
		||||
    public final List<Inventory> driveContainers;
 | 
			
		||||
    public final List<HardDriveItem> drives;
 | 
			
		||||
    public final Inventory inventory;
 | 
			
		||||
 | 
			
		||||
    public final int containerCount;
 | 
			
		||||
    public final int containerSlots;
 | 
			
		||||
    public final int containerUsedSlots;
 | 
			
		||||
    public final int containerFreeSlots;
 | 
			
		||||
 | 
			
		||||
    public ConnectedChests(World world, BlockPos startPos, boolean sortAlphabetically, String searchString, boolean allInventories) {
 | 
			
		||||
        List<Inventory> inventories = new ArrayList<>();
 | 
			
		||||
        List<Inventory> hoppers = new ArrayList<>();
 | 
			
		||||
        List<Inventory> driveContainers = new ArrayList<>();
 | 
			
		||||
        List<HardDriveItem> drives = new ArrayList<>();
 | 
			
		||||
        Set<BlockPos> visited = new HashSet<>();
 | 
			
		||||
 | 
			
		||||
        getConnectedChestsHelper(world, startPos, inventories, hoppers, driveContainers, drives, visited, allInventories);
 | 
			
		||||
 | 
			
		||||
        this.inventories = inventories;
 | 
			
		||||
        this.hoppers = hoppers;
 | 
			
		||||
        this.driveContainers = driveContainers;
 | 
			
		||||
        this.drives = drives;
 | 
			
		||||
        this.containerCount = inventories.size();
 | 
			
		||||
        this.inventory = getCombinedInventory(sortAlphabetically, searchString);
 | 
			
		||||
 | 
			
		||||
        int tempContainerSlots = 0;
 | 
			
		||||
        int tempContainerUsedSlots = 0;
 | 
			
		||||
        int tempContainerFreeSlots = 0;
 | 
			
		||||
        for (Inventory inventory : inventories) {
 | 
			
		||||
            tempContainerSlots += inventory.size();
 | 
			
		||||
            for (int slot = 0; slot < inventory.size(); slot++) {
 | 
			
		||||
                if (inventory.getStack(slot).isEmpty()) {
 | 
			
		||||
                    tempContainerFreeSlots++;
 | 
			
		||||
                } else {
 | 
			
		||||
                    tempContainerUsedSlots++;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            assert tempContainerSlots == tempContainerUsedSlots + tempContainerFreeSlots;
 | 
			
		||||
        }
 | 
			
		||||
        containerSlots = tempContainerSlots;
 | 
			
		||||
        containerUsedSlots = tempContainerUsedSlots;
 | 
			
		||||
        containerFreeSlots = tempContainerFreeSlots;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static boolean isEnabledContainer(BlockEntity blockEntity, boolean allContainers) {
 | 
			
		||||
        return (allContainers && blockEntity instanceof Inventory) ||
 | 
			
		||||
                blockEntity instanceof BarrelBlockEntity ||
 | 
			
		||||
                blockEntity instanceof ChestBlockEntity ||
 | 
			
		||||
                blockEntity instanceof ShulkerBoxBlockEntity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void getConnectedChestsHelper(World world, BlockPos pos, List<Inventory> inventories, List<Inventory> hoppers, List<Inventory> driveContainers, List<HardDriveItem> drives, Set<BlockPos> visited, Boolean allContainers) {
 | 
			
		||||
        if (visited.contains(pos)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        visited.add(pos);
 | 
			
		||||
 | 
			
		||||
        BlockEntity blockEntity = world.getBlockEntity(pos);
 | 
			
		||||
 | 
			
		||||
        if (blockEntity instanceof HardDriveContainerBlockEntity) {
 | 
			
		||||
            driveContainers.add((Inventory) blockEntity);
 | 
			
		||||
            //loop over all items in inventory
 | 
			
		||||
            for (int slot = 0; slot < inventories.size(); slot++) {
 | 
			
		||||
                ItemStack slotStack = ((Inventory) blockEntity).getStack(slot);
 | 
			
		||||
                //drives.add(new HardDriveItem(slotStack, (HardDriveContainerBlockEntity) blockEntity));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isEnabledHopper(blockEntity)) {
 | 
			
		||||
            hoppers.add((Inventory) blockEntity);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (isEnabledContainer(blockEntity, allContainers) || blockEntity instanceof StorageBlockEntity) {
 | 
			
		||||
            if (isEnabledContainer(blockEntity, allContainers) && !(blockEntity instanceof StorageBlockEntity)) {
 | 
			
		||||
                inventories.add((Inventory) blockEntity);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (Direction direction : Direction.values()) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(direction);
 | 
			
		||||
                getConnectedChestsHelper(world, nextPos, inventories, hoppers, driveContainers, drives, visited, allContainers);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Modify getCombinedInventoryFromChests to include item metadata and combine stacks
 | 
			
		||||
    private SimpleInventory getCombinedInventory(boolean sortAlphabetically, String query) {
 | 
			
		||||
        Map<ItemStack, Integer> itemStackMap = new HashMap<>();
 | 
			
		||||
        for (Inventory inventory : inventories) {
 | 
			
		||||
            addInventoryToMap(inventory, itemStackMap);
 | 
			
		||||
        }
 | 
			
		||||
        return filterInventory(getSimpleInventory(itemStackMap.size(), itemStackMap, sortAlphabetically), query, sortAlphabetically);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Modify filterInventory to include item metadata
 | 
			
		||||
    private SimpleInventory filterInventory(SimpleInventory inventory, String query, boolean sortAlphabetically) {
 | 
			
		||||
        if (query == null || query.isEmpty()) {
 | 
			
		||||
            return inventory;
 | 
			
		||||
        }
 | 
			
		||||
        Map<ItemStack, Integer> itemStackMap = new HashMap<>();
 | 
			
		||||
        int itemCount = 0;
 | 
			
		||||
        for (int slot = 0; slot < inventory.size(); slot++) {
 | 
			
		||||
            ItemStack stack = inventory.getStack(slot);
 | 
			
		||||
            ItemStack filteredStack = filterStack(stack, query);
 | 
			
		||||
            if (!filteredStack.isEmpty()) {
 | 
			
		||||
                itemCount++;
 | 
			
		||||
                int count = itemStackMap.getOrDefault(filteredStack, 0) + filteredStack.getCount();
 | 
			
		||||
                itemStackMap.put(filteredStack, count);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return getSimpleInventory(itemCount, itemStackMap, sortAlphabetically);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean tryPutItemStack(ItemStack stack) {
 | 
			
		||||
 | 
			
		||||
        // Iterate over each chest to try and insert the ItemStack
 | 
			
		||||
        for (Inventory chest : inventories) {
 | 
			
		||||
            if (!(chest instanceof HopperBlockEntity)) {
 | 
			
		||||
                stack = insertStackIntoInventory(chest, stack);
 | 
			
		||||
                if (stack.isEmpty()) {
 | 
			
		||||
                    return true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If we still have remaining items, return false
 | 
			
		||||
        return stack.isEmpty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean isEnabledHopper(BlockEntity blockEntity) {
 | 
			
		||||
        return blockEntity instanceof HopperBlockEntity ||
 | 
			
		||||
                blockEntity instanceof TrappedChestBlockEntity ||
 | 
			
		||||
                blockEntity instanceof FurnaceBlockEntity ||
 | 
			
		||||
                blockEntity instanceof BlastFurnaceBlockEntity ||
 | 
			
		||||
                blockEntity instanceof SmokerBlockEntity ||
 | 
			
		||||
                blockEntity instanceof BrewingStandBlockEntity;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canAddItemStack(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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void autoSuck() {
 | 
			
		||||
        for (Inventory chest : hoppers) {
 | 
			
		||||
            for (int i = 0; i < chest.size(); i++) {
 | 
			
		||||
                ItemStack slotStack = chest.getStack(i);
 | 
			
		||||
                if (!slotStack.isEmpty()) {
 | 
			
		||||
                    if (this.canAddItemStack(slotStack)) {
 | 
			
		||||
                        if (this.tryPutItemStack(slotStack)) {
 | 
			
		||||
                            removeFromInventory(chest, slotStack, slotStack.getCount());
 | 
			
		||||
                        }
 | 
			
		||||
                        ;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canRemove(ItemStack stackToRemove) {
 | 
			
		||||
        return canRemoveCount(stackToRemove, inventory) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack removeItemStack(ItemStack stackToRemove) {
 | 
			
		||||
 | 
			
		||||
        int remainingToRemove = stackToRemove.getCount();
 | 
			
		||||
        ItemStack outStack = stackToRemove.copy();
 | 
			
		||||
 | 
			
		||||
        for (Inventory chest : inventories) {
 | 
			
		||||
            remainingToRemove = removeFromInventory(chest, stackToRemove, remainingToRemove);
 | 
			
		||||
            if (remainingToRemove <= 0) {
 | 
			
		||||
                return outStack;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        outStack.setCount(outStack.getCount() - remainingToRemove);
 | 
			
		||||
        return outStack;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.util.StringIdentifiable;
 | 
			
		||||
 | 
			
		||||
public enum ConnectionType implements StringIdentifiable {
 | 
			
		||||
    NONE("none"),
 | 
			
		||||
    BUS("bus"),
 | 
			
		||||
    INVENTORY("inventory");
 | 
			
		||||
    private final String name;
 | 
			
		||||
 | 
			
		||||
    ConnectionType(String name) {
 | 
			
		||||
        this.name = name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String asString() {
 | 
			
		||||
        return this.name;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        return this.name;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,34 +1,50 @@
 | 
			
		||||
package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import com.mojang.serialization.Codec;
 | 
			
		||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
 | 
			
		||||
import eu.pb4.polymer.core.api.other.PolymerComponent;
 | 
			
		||||
import net.minecraft.component.ComponentType;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.network.codec.PacketCodecs;
 | 
			
		||||
import net.minecraft.registry.Registries;
 | 
			
		||||
import net.minecraft.registry.Registry;
 | 
			
		||||
import net.minecraft.util.dynamic.Codecs;
 | 
			
		||||
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.function.UnaryOperator;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class DriveComponents {
 | 
			
		||||
    public static final Codec<Map<ItemStack, Integer>> ITEMSTACK_MAP_CODEC = Codec.unboundedMap(ItemStack.CODEC, Codec.INT);
 | 
			
		||||
    public static final Codec<List<ItemStack>> ITEMSTACK_LIST_CODEC = Codec.list(ItemStack.CODEC);
 | 
			
		||||
    public static final Codec<List<Integer>> INTEGER_LIST_CODEC = Codec.list(Codec.INT);
 | 
			
		||||
 | 
			
		||||
    public static final ComponentType<Integer> MAX_ITEMS = register(
 | 
			
		||||
            "max_items", builder -> builder.codec(Codecs.POSITIVE_INT).packetCodec(PacketCodecs.VAR_INT)
 | 
			
		||||
    public static final Codec<Map<ItemStack, Integer>> ITEMSTACK_MAP_CODEC = RecordCodecBuilder.create(instance ->
 | 
			
		||||
            instance.group(
 | 
			
		||||
                    ITEMSTACK_LIST_CODEC.fieldOf("itemStacks").forGetter(map -> new ArrayList<>(map.keySet())),
 | 
			
		||||
                    INTEGER_LIST_CODEC.fieldOf("counts").forGetter(map -> new ArrayList<>(map.values()))
 | 
			
		||||
            ).apply(instance, (itemStacks, counts) -> {
 | 
			
		||||
                Map<ItemStack, Integer> map = new HashMap<>();
 | 
			
		||||
                for (int i = 0; i < itemStacks.size(); i++) {
 | 
			
		||||
                    map.put(itemStacks.get(i), counts.get(i));
 | 
			
		||||
                }
 | 
			
		||||
                return map;
 | 
			
		||||
            })
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    public static final ComponentType<Integer> USED_ITEMS = register(
 | 
			
		||||
            "used_items", builder -> builder.codec(Codecs.NONNEGATIVE_INT).packetCodec(PacketCodecs.VAR_INT)
 | 
			
		||||
    );
 | 
			
		||||
    public static final Codec<UUID> UUID_CODEC = RecordCodecBuilder.create(instance ->
 | 
			
		||||
            instance.group(
 | 
			
		||||
                    Codec.LONG.fieldOf("mostSigBits").forGetter(UUID::getMostSignificantBits),
 | 
			
		||||
                    Codec.LONG.fieldOf("leastSigBits").forGetter(UUID::getLeastSignificantBits)
 | 
			
		||||
            ).apply(instance, UUID::new));
 | 
			
		||||
 | 
			
		||||
    public static final ComponentType<Map<ItemStack, Integer>> ITEMSTACK_MAP = register(
 | 
			
		||||
            "itemstack_map",
 | 
			
		||||
            builder -> builder.codec(ITEMSTACK_MAP_CODEC) // No packetCodec needed for this example
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    public static final ComponentType<UUID> UUID_COMPONENT = register(
 | 
			
		||||
            "drive_uuid",
 | 
			
		||||
            builder -> builder.codec(UUID_CODEC) // No packetCodec needed for this example
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private static <T> ComponentType<T> register(String id, UnaryOperator<ComponentType.Builder<T>> builderOperator) {
 | 
			
		||||
        ComponentType<T> componentType = Registry.register(
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,15 @@ public abstract class PagedGui extends SimpleGui {
 | 
			
		||||
    public static final String GUI_AUTOSUCK_OFF = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGViODFlZjg5MDIzNzk2NTBiYTc5ZjQ1NzIzZDZiOWM4ODgzODhhMDBmYzRlMTkyZjM0NTRmZTE5Mzg4MmVlMSJ9fX0=";
 | 
			
		||||
    public static final String GUI_AUTOSUCK_ON = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMThjNDQzYWRhNmUzOWZjYTgzN2EwMzgzYjBhNWUzZTU1NDc3M2I5NjYwYzQ4NzNmNTkxMDMyZGJlOWFkY2RmOCJ9fX0=";
 | 
			
		||||
 | 
			
		||||
    public static final String GUI_SIDE_NORTH = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZGEyMjFlNGY5NmJlZTYyNjE3NTIzOTZhMzI2NWZmYTRkZWRmOGZmNDgzOWFiZDE0ZjQ5ZWRlZTFlNTMwOTIifX19";
 | 
			
		||||
    public static final String GUI_SIDE_SOUTH = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDcxMDEzODQxNjUyODg4OTgxNTU0OGI0NjIzZDI4ZDg2YmJiYWU1NjE5ZDY5Y2Q5ZGJjNWFkNmI0Mzc0NCJ9fX0=";
 | 
			
		||||
    public static final String GUI_SIDE_EAST = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWFlZWY4OGUyYzkyOGI0NjZjNmVkNWRlYWE0ZTE5NzVhOTQzNmMyYjFiNDk4ZjlmN2NiZjkyYTliNTk5YTYifX19";
 | 
			
		||||
    public static final String GUI_SIDE_WEST = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODBjOTQ4M2Y1MWQxMjY3NDMyZTBmMmYzYmFhOGNkOTNlNjViNWVhYzc0ODJiMjdkYmNjZWJhZmI3MjE3NDhiIn19fQ==";
 | 
			
		||||
    public static final String GUI_SIDE_UP = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY5OTFkY2JhMjVlYWUyNDNlYjVjZWI4MzI1ZjRhYjc4ZjlmMTQxMjdjMzgyZjZjZDQyYzRjNzgwNDJkNGI1In19fQ==";
 | 
			
		||||
    public static final String GUI_SIDE_DOWN = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmE2NjE0MTlkZTQ5ZmY0YTJjOTdiMjdmODY4MDE0ZmJkYWViOGRkN2Y0MzkyNzc3ODMwYjI3MTRjYWFmZDFmIn19fQ==";
 | 
			
		||||
    public static final String GUI_MODE_INPUT = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNWM5OWRmYjI3MDRlMWJkNmU3ZmFjZmI0M2IzZTZmYmFiYWYxNmViYzdlMWZhYjA3NDE3YTZjNDY0ZTFkIn19fQ==";
 | 
			
		||||
    public static final String GUI_MODE_OUTPUT = "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2JiMWQxN2NlYmM1ZjBlY2M5ODdiODBlZmMwM2UzMmVjYjFjYjQwZGJjNWJjZTJmYWYzZTYwNTQyYTQwIn19fQ==";
 | 
			
		||||
 | 
			
		||||
    public static final int PAGE_SIZE = 9 * 5;
 | 
			
		||||
    protected final Runnable closeCallback;
 | 
			
		||||
    public boolean ignoreCloseCallback;
 | 
			
		||||
@@ -73,7 +82,7 @@ public abstract class PagedGui extends SimpleGui {
 | 
			
		||||
        return this.page - 1 >= 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void updateDisplay() {
 | 
			
		||||
    public void updateDisplay() {
 | 
			
		||||
        var offset = page * PAGE_SIZE;
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < PAGE_SIZE; i++) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										199
									
								
								src/main/java/systems/brn/server_storage/lib/StorageNetwork.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,199 @@
 | 
			
		||||
package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.block.Block;
 | 
			
		||||
import net.minecraft.block.BlockState;
 | 
			
		||||
import net.minecraft.block.entity.*;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.util.math.Direction;
 | 
			
		||||
import net.minecraft.world.World;
 | 
			
		||||
import systems.brn.server_storage.blockentities.HardDriveContainerBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.InventoryInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blocks.BusConnectorBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.HardDriveContainerBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.InventoryInterfaceBlock;
 | 
			
		||||
import systems.brn.server_storage.blocks.StorageInterfaceBlock;
 | 
			
		||||
import systems.brn.server_storage.items.HardDrive;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.DRIVES;
 | 
			
		||||
import static systems.brn.server_storage.blocks.BusConnectorBlock.*;
 | 
			
		||||
import static systems.brn.server_storage.lib.StorageOperations.*;
 | 
			
		||||
 | 
			
		||||
public class StorageNetwork {
 | 
			
		||||
    public List<HardDriveContainerBlockEntity> driveContainers;
 | 
			
		||||
    public List<StorageInterfaceBlockEntity> storageInterfaceBlockEntities;
 | 
			
		||||
    public List<InventoryInterfaceBlockEntity> inventoryInterfaceBlockEntities;
 | 
			
		||||
    public List<HardDrive> drives;
 | 
			
		||||
    public Map<ItemStack, Integer> itemStackMap;
 | 
			
		||||
    public Map<ItemStack, Integer> filteredItemStackMap;
 | 
			
		||||
 | 
			
		||||
    public int driveContainerCount;
 | 
			
		||||
    public int drivesCount;
 | 
			
		||||
    public int driveTotalSlots;
 | 
			
		||||
    public int driveUsedSlots;
 | 
			
		||||
    public int driveFreeSlots;
 | 
			
		||||
 | 
			
		||||
    public StorageNetwork(World world, BlockPos startPos, boolean sortAlphabetically, String searchString) {
 | 
			
		||||
        reindexNetwork(world, startPos, sortAlphabetically, searchString);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void reindexNetwork(World world, BlockPos startPos, boolean sortAlphabetically, String searchString) {
 | 
			
		||||
        List<HardDriveContainerBlockEntity> driveContainers = new ArrayList<>();
 | 
			
		||||
        List<StorageInterfaceBlockEntity> storageInterfaceBlockEntities = new ArrayList<>();
 | 
			
		||||
        List<InventoryInterfaceBlockEntity> inventoryInterfaceBlockEntities = new ArrayList<>();
 | 
			
		||||
        List<HardDrive> drives = new ArrayList<>();
 | 
			
		||||
        Set<BlockPos> visited = new HashSet<>();
 | 
			
		||||
 | 
			
		||||
        scan(world, startPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
 | 
			
		||||
        this.driveContainers = driveContainers;
 | 
			
		||||
        this.drives = drives;
 | 
			
		||||
        this.storageInterfaceBlockEntities = storageInterfaceBlockEntities;
 | 
			
		||||
        this.inventoryInterfaceBlockEntities = inventoryInterfaceBlockEntities;
 | 
			
		||||
 | 
			
		||||
        countStuff();
 | 
			
		||||
 | 
			
		||||
        filteredItemStackMap = getCombinedMap(sortAlphabetically, searchString);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void countStuff() {
 | 
			
		||||
        driveUsedSlots = 0;
 | 
			
		||||
        driveFreeSlots = 0;
 | 
			
		||||
        driveTotalSlots = 0;
 | 
			
		||||
        driveContainerCount = driveContainers.size();
 | 
			
		||||
        drivesCount = drives.size();
 | 
			
		||||
        for (HardDriveContainerBlockEntity driveContainer : this.driveContainers) {
 | 
			
		||||
            driveFreeSlots += driveContainer.getAvailableSlots();
 | 
			
		||||
            driveUsedSlots += driveContainer.getUsedSlots();
 | 
			
		||||
            driveTotalSlots += driveContainer.getTotalSlots();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void updateDisplays(){
 | 
			
		||||
        for (StorageInterfaceBlockEntity storageInterfaceBlockEntity : storageInterfaceBlockEntities) {
 | 
			
		||||
            storageInterfaceBlockEntity.updateDisplays();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void scan(World world, BlockPos pos, BlockPos startPos, List<HardDriveContainerBlockEntity> driveContainers, List<StorageInterfaceBlockEntity> storageInterfaceBlockEntities, List<InventoryInterfaceBlockEntity> inventoryInterfaceBlockEntities, List<HardDrive> drives, Set<BlockPos> visited) {
 | 
			
		||||
        if (visited.contains(pos)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        visited.add(pos);
 | 
			
		||||
 | 
			
		||||
        BlockState blockState = world.getBlockState(pos);
 | 
			
		||||
 | 
			
		||||
        Block block = blockState.getBlock();
 | 
			
		||||
 | 
			
		||||
        if (block instanceof HardDriveContainerBlock) {
 | 
			
		||||
            BlockEntity blockEntity = world.getBlockEntity(pos);
 | 
			
		||||
            if (blockEntity instanceof HardDriveContainerBlockEntity driveContainerBlockEntity) {
 | 
			
		||||
                driveContainers.add(driveContainerBlockEntity);
 | 
			
		||||
                driveContainerBlockEntity.indexDrives();
 | 
			
		||||
                drives.addAll(driveContainerBlockEntity.drives);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (block instanceof StorageInterfaceBlock) {
 | 
			
		||||
            BlockEntity blockEntity = world.getBlockEntity(pos);
 | 
			
		||||
            if (blockEntity instanceof StorageInterfaceBlockEntity storageInterfaceBlockEntity){
 | 
			
		||||
                storageInterfaceBlockEntities.add(storageInterfaceBlockEntity);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (block instanceof InventoryInterfaceBlock) {
 | 
			
		||||
            BlockEntity blockEntity = world.getBlockEntity(pos);
 | 
			
		||||
            if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity){
 | 
			
		||||
                inventoryInterfaceBlockEntities.add(inventoryInterfaceBlockEntity);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (block instanceof BusConnectorBlock || pos == startPos) {
 | 
			
		||||
 | 
			
		||||
            if (blockState.getOrEmpty(NORTH).isPresent() && blockState.get(NORTH) == ConnectionType.BUS) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(Direction.NORTH);
 | 
			
		||||
                scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
            }
 | 
			
		||||
            if (blockState.getOrEmpty(SOUTH).isPresent() && blockState.get(SOUTH) == ConnectionType.BUS) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(Direction.SOUTH);
 | 
			
		||||
                scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
            }
 | 
			
		||||
            if (blockState.getOrEmpty(EAST).isPresent() && blockState.get(EAST) == ConnectionType.BUS) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(Direction.EAST);
 | 
			
		||||
                scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
            }
 | 
			
		||||
            if (blockState.getOrEmpty(WEST).isPresent() && blockState.get(WEST) == ConnectionType.BUS) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(Direction.WEST);
 | 
			
		||||
                scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
            }
 | 
			
		||||
            if (blockState.getOrEmpty(UP).isPresent() && blockState.get(UP) == ConnectionType.BUS) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(Direction.UP);
 | 
			
		||||
                scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
            }
 | 
			
		||||
            if (blockState.getOrEmpty(DOWN).isPresent() && blockState.get(DOWN) == ConnectionType.BUS) {
 | 
			
		||||
                BlockPos nextPos = pos.offset(Direction.DOWN);
 | 
			
		||||
                scan(world, nextPos, startPos, driveContainers, storageInterfaceBlockEntities, inventoryInterfaceBlockEntities, drives, visited);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Modify getCombinedInventoryFromChests to include item metadata and combine stacks
 | 
			
		||||
    private TreeMap<ItemStack, Integer> getCombinedMap(boolean sortAlphabetically, String query) {
 | 
			
		||||
        itemStackMap = new HashMap<>();
 | 
			
		||||
        for (HardDrive drive : drives) {
 | 
			
		||||
            itemStackMap = drive.addToMap(itemStackMap);
 | 
			
		||||
        }
 | 
			
		||||
        return sortAndFilterMap(itemStackMap, sortAlphabetically, query);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    public int putItemStackRemainder(ItemStack stack) {
 | 
			
		||||
        if (DRIVES.contains(stack.getItem())){
 | 
			
		||||
            return stack.getCount();
 | 
			
		||||
        }
 | 
			
		||||
        // Iterate over each chest to try and insert the ItemStack
 | 
			
		||||
        int leftOvers = stack.getCount();
 | 
			
		||||
        for (InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity : inventoryInterfaceBlockEntities) {
 | 
			
		||||
            leftOvers = inventoryInterfaceBlockEntity.processIncoming(stack.copy(), leftOvers);
 | 
			
		||||
            if (leftOvers <= 0) {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        ItemStack driveStack = stack.copy();
 | 
			
		||||
        driveStack.setCount(leftOvers);
 | 
			
		||||
        for (HardDrive drive : drives) {
 | 
			
		||||
            driveStack = drive.insertStackIntoInventory(driveStack);
 | 
			
		||||
            if (driveStack.isEmpty()) {
 | 
			
		||||
                return 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If we still have remaining items, return false
 | 
			
		||||
        return driveStack.getCount();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canAddItemStack(ItemStack stack) {
 | 
			
		||||
        return stack.getCount() <= driveFreeSlots && !DRIVES.contains(stack.getItem());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean canRemove(ItemStack stackToRemove) {
 | 
			
		||||
        return canRemoveCount(stackToRemove, itemStackMap) == 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack removeItemStack(ItemStack stackToRemove) {
 | 
			
		||||
        ItemStack outStack = stackToRemove.copy();
 | 
			
		||||
 | 
			
		||||
        for (HardDrive drive : drives) {
 | 
			
		||||
            outStack = drive.removeStackFromInventory(outStack);
 | 
			
		||||
            if (outStack.getCount() >= stackToRemove.getCount()) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If we still have remaining items, return false
 | 
			
		||||
        return outStack;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,19 +1,43 @@
 | 
			
		||||
package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.inventory.SimpleInventory;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.TreeMap;
 | 
			
		||||
 | 
			
		||||
public class StorageOperations {
 | 
			
		||||
    // Modify getSimpleInventory to include item metadata and sort conditionally
 | 
			
		||||
    public static @NotNull SimpleInventory getSimpleInventory(int size, Map<ItemStack, Integer> itemStackMap, boolean sortAlphabetically) {
 | 
			
		||||
    public static TreeMap<ItemStack, Integer> sortAndFilterMap(Map<ItemStack, Integer> itemStackMap, boolean sortAlphabetically, String query) {
 | 
			
		||||
        TreeMap<ItemStack, Integer> sortedMap = getItemStackIntegerTreeMap(itemStackMap, sortAlphabetically);
 | 
			
		||||
 | 
			
		||||
        if (query == null || query.isEmpty() || query.equals("*")) {
 | 
			
		||||
            sortedMap.putAll(itemStackMap);
 | 
			
		||||
        } else {
 | 
			
		||||
            Map<ItemStack, Integer> filteredMap = new HashMap<>();
 | 
			
		||||
            for (Map.Entry<ItemStack, Integer> entry : itemStackMap.entrySet()) {
 | 
			
		||||
                if (filterItem(entry.getKey().getItem(), query)){
 | 
			
		||||
                    filteredMap.put(entry.getKey(), entry.getValue());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            sortedMap.putAll(filteredMap);
 | 
			
		||||
        }
 | 
			
		||||
        return sortedMap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static boolean filterItem(Item item, String query){
 | 
			
		||||
        if (item != null) {
 | 
			
		||||
            String itemName = String.valueOf(item);
 | 
			
		||||
            return itemName == null || itemName.contains(query);
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static @NotNull TreeMap<ItemStack, Integer> getItemStackIntegerTreeMap(Map<ItemStack, Integer> itemStackMap, boolean sortAlphabetically) {
 | 
			
		||||
        TreeMap<ItemStack, Integer> sortedMap;
 | 
			
		||||
 | 
			
		||||
        if (sortAlphabetically) {
 | 
			
		||||
@@ -33,51 +57,35 @@ public class StorageOperations {
 | 
			
		||||
                return countCompare == 0 ? String.valueOf(o1.getItem()).compareToIgnoreCase(String.valueOf(o2.getItem())) : countCompare;
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sortedMap.putAll(itemStackMap);
 | 
			
		||||
 | 
			
		||||
        SimpleInventory inv = new SimpleInventory(size);
 | 
			
		||||
        int invPointer = 0;
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : sortedMap.entrySet()) {
 | 
			
		||||
            ItemStack stack = entry.getKey();
 | 
			
		||||
            int count = entry.getValue();
 | 
			
		||||
            stack.setCount(count);
 | 
			
		||||
            inv.heldStacks.set(invPointer, stack); //bypass stack maximum
 | 
			
		||||
            invPointer++;
 | 
			
		||||
        }
 | 
			
		||||
        return inv;
 | 
			
		||||
        return sortedMap;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Modify filterStack to include item metadata
 | 
			
		||||
    public static ItemStack filterStack(ItemStack stack, String query) {
 | 
			
		||||
        Item item = stack.getItem();
 | 
			
		||||
        if (item != null) {
 | 
			
		||||
            String itemName = String.valueOf(item);
 | 
			
		||||
            if (itemName != null && !itemName.contains(query)) {
 | 
			
		||||
                return ItemStack.EMPTY;
 | 
			
		||||
    public static int canInsertToStack(ItemStack stack1, ItemStack stack2, int maxInsert) {
 | 
			
		||||
        if (stack1.isEmpty() || ItemStack.areItemsEqual(stack1, stack2)) {
 | 
			
		||||
            int remainingSpace = stack1.isEmpty() ? stack2.getMaxCount() : stack1.getMaxCount() - stack1.getCount();
 | 
			
		||||
            maxInsert += remainingSpace;
 | 
			
		||||
            // If the maximum insertion count is greater than or equal to the item count, return the item count
 | 
			
		||||
            if (maxInsert >= stack2.getCount()) {
 | 
			
		||||
                return stack2.getCount();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return stack;
 | 
			
		||||
        return maxInsert;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int canInsertItemIntoPlayerInventory(PlayerEntity player, ItemStack itemStack) {
 | 
			
		||||
    public static int canInsertItemIntoInventory(Inventory inventory, ItemStack itemStack) {
 | 
			
		||||
        // Get the player's inventory
 | 
			
		||||
        PlayerInventory playerInventory = player.getInventory();
 | 
			
		||||
 | 
			
		||||
        int maxInsert = 0;
 | 
			
		||||
 | 
			
		||||
        // Iterate through the slots in the player's inventory
 | 
			
		||||
        for (int i = 0; i < playerInventory.main.size(); i++) {
 | 
			
		||||
            ItemStack slotStack = playerInventory.main.get(i);
 | 
			
		||||
 | 
			
		||||
            // Check if the slot is empty or if there's space for the item
 | 
			
		||||
            if (slotStack.isEmpty() || ItemStack.areItemsEqual(slotStack, itemStack)) {
 | 
			
		||||
                int remainingSpace = slotStack.isEmpty() ? itemStack.getMaxCount() : slotStack.getMaxCount() - slotStack.getCount();
 | 
			
		||||
                maxInsert += remainingSpace;
 | 
			
		||||
                // If the maximum insertion count is greater than or equal to the item count, return the item count
 | 
			
		||||
                if (maxInsert >= itemStack.getCount()) {
 | 
			
		||||
                    return itemStack.getCount();
 | 
			
		||||
                }
 | 
			
		||||
        if (inventory instanceof PlayerInventory playerInventory) {
 | 
			
		||||
            // Iterate through the slots in the player's inventory
 | 
			
		||||
            for (int i = 0; i < playerInventory.main.size(); i++) {
 | 
			
		||||
                ItemStack slotStack = playerInventory.main.get(i);
 | 
			
		||||
                maxInsert = canInsertToStack(slotStack, itemStack, maxInsert);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
                ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
                maxInsert = canInsertToStack(slotStack, itemStack, maxInsert);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -115,7 +123,7 @@ public class StorageOperations {
 | 
			
		||||
        return stack;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int removeFromInventory(Inventory inventory, ItemStack stackToRemove, int remainingToRemove) {
 | 
			
		||||
    public static void removeFromInventory(Inventory inventory, ItemStack stackToRemove, int remainingToRemove) {
 | 
			
		||||
        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
            ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
            if (canCombine(slotStack, stackToRemove)) {
 | 
			
		||||
@@ -129,21 +137,36 @@ public class StorageOperations {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (remainingToRemove <= 0) {
 | 
			
		||||
                    return remainingToRemove;
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return remainingToRemove;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int canRemoveCount(ItemStack stackToRemove, Inventory inventory) {
 | 
			
		||||
        int remainingToRemove = stackToRemove.getCount();
 | 
			
		||||
 | 
			
		||||
    public static int howMuchFits(ItemStack stack, Inventory inventory){
 | 
			
		||||
        int out = 0;
 | 
			
		||||
        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
            ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
            if (slotStack.isEmpty()) {
 | 
			
		||||
                out += stack.getMaxCount();
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (canCombine(slotStack, stack)) {
 | 
			
		||||
                int remaining = slotStack.getMaxCount() - slotStack.getCount();
 | 
			
		||||
                out += remaining;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static int canRemoveCount(ItemStack stackToRemove, Map<ItemStack, Integer> itemsMap) {
 | 
			
		||||
        int remainingToRemove = stackToRemove.getCount();
 | 
			
		||||
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : itemsMap.entrySet()) {
 | 
			
		||||
            ItemStack slotStack = entry.getKey();
 | 
			
		||||
            if (canCombine(slotStack, stackToRemove)) {
 | 
			
		||||
                // If the slot contains the same item type
 | 
			
		||||
                if (slotStack.getCount() >= remainingToRemove) {
 | 
			
		||||
                if (entry.getValue() >= remainingToRemove) {
 | 
			
		||||
                    // If the count in the slot is sufficient to remove the requested amount
 | 
			
		||||
                    return 0;
 | 
			
		||||
                } else {
 | 
			
		||||
@@ -174,7 +197,7 @@ public class StorageOperations {
 | 
			
		||||
            ItemStack existingStack = entry.getKey();
 | 
			
		||||
            if (ItemStack.areItemsAndComponentsEqual(stack, existingStack)) {
 | 
			
		||||
                int newCount = entry.getValue() + stack.getCount();
 | 
			
		||||
                itemStackMap.put(existingStack, newCount);
 | 
			
		||||
                entry.setValue(newCount);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ package systems.brn.server_storage.lib;
 | 
			
		||||
 | 
			
		||||
import net.minecraft.component.DataComponentTypes;
 | 
			
		||||
import net.minecraft.component.type.LoreComponent;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.Item;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
@@ -21,13 +20,13 @@ import java.util.stream.Collectors;
 | 
			
		||||
 | 
			
		||||
public class Util {
 | 
			
		||||
 | 
			
		||||
    public static List<RawFilteredPair<Text>> generateBookContent(Inventory inventory) {
 | 
			
		||||
    public static List<RawFilteredPair<Text>> generateBookContent(Map<ItemStack, Integer> itemMap) {
 | 
			
		||||
        List<String> pages = new ArrayList<>();
 | 
			
		||||
        for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
            ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
        for (Map.Entry<ItemStack, Integer> entry : itemMap.entrySet()) {
 | 
			
		||||
            ItemStack slotStack = entry.getKey();
 | 
			
		||||
            if (!slotStack.isEmpty()) {
 | 
			
		||||
                Item itemName = slotStack.getItem();
 | 
			
		||||
                pages.add(itemName + " " + slotStack.getCount());
 | 
			
		||||
                pages.add(itemName + " " + entry.getValue());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return stringToBookContent(String.join(System.lineSeparator(), pages));
 | 
			
		||||
@@ -106,7 +105,7 @@ public class Util {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static ArrayList<CraftingEntry> getCraftableRecipes(Inventory inventory, MinecraftServer server) {
 | 
			
		||||
    public static ArrayList<CraftingEntry> getCraftableRecipes(Map<ItemStack, Integer> itemStackMap, MinecraftServer server) {
 | 
			
		||||
        RecipeManager recipeManager = server.getRecipeManager();
 | 
			
		||||
        List<RecipeEntry<CraftingRecipe>> allRecipes = recipeManager.listAllOfType(RecipeType.CRAFTING);
 | 
			
		||||
 | 
			
		||||
@@ -152,10 +151,9 @@ public class Util {
 | 
			
		||||
                    ItemStack stackIn = entry.getKey();
 | 
			
		||||
                    Integer count = entry.getValue();
 | 
			
		||||
                    boolean itemFound = false;
 | 
			
		||||
                    for (int i = 0; i < inventory.size(); i++) {
 | 
			
		||||
                        ItemStack slotStack = inventory.getStack(i);
 | 
			
		||||
                        Item slotItem = slotStack.getItem();
 | 
			
		||||
                        int slotCount = slotStack.getCount();
 | 
			
		||||
                    for (Map.Entry<ItemStack, Integer> itemEntry : itemStackMap.entrySet()){
 | 
			
		||||
                        Item slotItem = itemEntry.getKey().getItem();
 | 
			
		||||
                        int slotCount = itemEntry.getValue();
 | 
			
		||||
                        if (stackIn.getItem() == slotItem) {
 | 
			
		||||
                            count -= slotCount;
 | 
			
		||||
                            entry.setValue(count);
 | 
			
		||||
@@ -172,9 +170,6 @@ public class Util {
 | 
			
		||||
                    if (count > 0) {
 | 
			
		||||
                        canMake = false;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        if(recipe.value().getResult(server.getRegistryManager()).getItem() == Items.REDSTONE_BLOCK){
 | 
			
		||||
                            int asdasd = 0;
 | 
			
		||||
                        }
 | 
			
		||||
                        int thisMaxAmount = Math.floorDivExact(Math.abs(count), stackIn.getCount());
 | 
			
		||||
                        if (maxAmount == -1) {
 | 
			
		||||
                            maxAmount = thisMaxAmount;
 | 
			
		||||
 
 | 
			
		||||
@@ -7,36 +7,34 @@ import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.screen.ScreenHandler;
 | 
			
		||||
import net.minecraft.screen.ScreenHandlerType;
 | 
			
		||||
import net.minecraft.screen.slot.Slot;
 | 
			
		||||
import systems.brn.server_storage.lib.HardDriveSlot;
 | 
			
		||||
import systems.brn.server_storage.blockentities.HardDriveContainerBlockEntity;
 | 
			
		||||
 | 
			
		||||
public class DriveContainerScreenHandler extends ScreenHandler {
 | 
			
		||||
    private static final int CONTAINER_SIZE = 9;
 | 
			
		||||
    private static final int INVENTORY_START = 9;
 | 
			
		||||
    private static final int INVENTORY_END = 36;
 | 
			
		||||
    private static final int HOTBAR_START = 36;
 | 
			
		||||
    private static final int HOTBAR_END = 45;
 | 
			
		||||
    private final Inventory inventory;
 | 
			
		||||
    private final HardDriveContainerBlockEntity blockEntity;
 | 
			
		||||
 | 
			
		||||
    public DriveContainerScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) {
 | 
			
		||||
        super(ScreenHandlerType.GENERIC_3X3, syncId);
 | 
			
		||||
        checkSize(inventory, 9);
 | 
			
		||||
        this.inventory = inventory;
 | 
			
		||||
    public DriveContainerScreenHandler(int syncId, PlayerInventory playerInventory, HardDriveContainerBlockEntity blockEntity) {
 | 
			
		||||
        super(ScreenHandlerType.HOPPER, syncId);
 | 
			
		||||
        this.blockEntity = blockEntity;
 | 
			
		||||
        checkSize(blockEntity, HardDriveContainerBlockEntity.INVENTORY_SIZE);
 | 
			
		||||
        this.inventory = blockEntity;
 | 
			
		||||
        blockEntity.indexDrives();
 | 
			
		||||
        blockEntity.commitDrives();
 | 
			
		||||
        inventory.onOpen(playerInventory.player);
 | 
			
		||||
 | 
			
		||||
        for(int i = 0; i < 3; ++i) {
 | 
			
		||||
            for(int j = 0; j < 3; ++j) {
 | 
			
		||||
                this.addSlot(new HardDriveSlot(inventory, j + i * 3, 62 + j * 18, 17 + i * 18));
 | 
			
		||||
        int j;
 | 
			
		||||
        for (j = 0; j < 5; ++j) {
 | 
			
		||||
            this.addSlot(new Slot(inventory, j, 44 + j * 18, 20));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (j = 0; j < 3; ++j) {
 | 
			
		||||
            for (int k = 0; k < 9; ++k) {
 | 
			
		||||
                this.addSlot(new Slot(playerInventory, k + j * 9 + 9, 8 + k * 18, j * 18 + 51));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for(int i = 0; i < 3; ++i) {
 | 
			
		||||
            for(int j = 0; j < 9; ++j) {
 | 
			
		||||
                this.addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for(int i = 0; i < 9; ++i) {
 | 
			
		||||
            this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
 | 
			
		||||
        for (j = 0; j < 9; ++j) {
 | 
			
		||||
            this.addSlot(new Slot(playerInventory, j, 8 + j * 18, 109));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -45,18 +43,25 @@ public class DriveContainerScreenHandler extends ScreenHandler {
 | 
			
		||||
        return this.inventory.canPlayerUse(player);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public ItemStack quickMove(PlayerEntity player, int slot) {
 | 
			
		||||
        ItemStack temp = quickMoveHelper(player, slot);
 | 
			
		||||
        blockEntity.indexDrives();
 | 
			
		||||
        return temp;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public ItemStack quickMoveHelper(PlayerEntity player, int slot) {
 | 
			
		||||
        ItemStack itemStack = ItemStack.EMPTY;
 | 
			
		||||
        Slot slot2 = this.slots.get(slot);
 | 
			
		||||
        if (slot2.hasStack()) {
 | 
			
		||||
            ItemStack itemStack2 = slot2.getStack();
 | 
			
		||||
            itemStack = itemStack2.copy();
 | 
			
		||||
            if (slot < 9) {
 | 
			
		||||
                if (!this.insertItem(itemStack2, 9, 45, true)) {
 | 
			
		||||
            if (slot < this.inventory.size()) {
 | 
			
		||||
                if (!this.insertItem(itemStack2, this.inventory.size(), this.slots.size(), true)) {
 | 
			
		||||
                    return ItemStack.EMPTY;
 | 
			
		||||
                }
 | 
			
		||||
            } else if (!this.insertItem(itemStack2, 0, 9, false)) {
 | 
			
		||||
            } else if (!this.insertItem(itemStack2, 0, this.inventory.size(), false)) {
 | 
			
		||||
                return ItemStack.EMPTY;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -80,5 +85,6 @@ public class DriveContainerScreenHandler extends ScreenHandler {
 | 
			
		||||
    public void onClosed(PlayerEntity player) {
 | 
			
		||||
        super.onClosed(player);
 | 
			
		||||
        this.inventory.onClose(player);
 | 
			
		||||
        blockEntity.indexDrives();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,12 +2,14 @@ package systems.brn.server_storage.screens;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
 | 
			
		||||
import net.minecraft.entity.player.PlayerEntity;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.inventory.Inventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.recipe.CraftingRecipe;
 | 
			
		||||
import net.minecraft.recipe.Ingredient;
 | 
			
		||||
import net.minecraft.recipe.RecipeEntry;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.lib.CraftingEntry;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
 | 
			
		||||
@@ -24,23 +26,26 @@ public class CraftingScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    private ArrayList<CraftingEntry> craftingEntries;
 | 
			
		||||
 | 
			
		||||
    private final StorageInterfaceBlockEntity blockEntity;
 | 
			
		||||
 | 
			
		||||
    private ArrayList<DisplayElement> recipesList;
 | 
			
		||||
 | 
			
		||||
    public CraftingScreen(StorageScreen storageScreen) {
 | 
			
		||||
        super(storageScreen.getPlayer(), null);
 | 
			
		||||
        this.storageScreen = storageScreen;
 | 
			
		||||
        this.blockEntity = storageScreen.blockEntity;
 | 
			
		||||
        this.setTitle(Text.translatable("container.crafting"));
 | 
			
		||||
        this.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateDisplay(){
 | 
			
		||||
        storageScreen.blockEntity.rescanChests();
 | 
			
		||||
        blockEntity.reindexDrives();
 | 
			
		||||
        Map<ItemStack, Integer> itemStackMap = new HashMap<>();
 | 
			
		||||
        addInventoryToMap(storageScreen.getPlayer().getInventory(), itemStackMap);
 | 
			
		||||
        addInventoryToMap(storageScreen.blockEntity.chests.inventory, itemStackMap);
 | 
			
		||||
        Inventory inventory = getSimpleInventory(itemStackMap.size(), itemStackMap, false);
 | 
			
		||||
        this.craftingEntries = getCraftableRecipes(inventory, Objects.requireNonNull(player.getServer()));
 | 
			
		||||
        itemStackMap.putAll(blockEntity.network.itemStackMap);
 | 
			
		||||
        Map<ItemStack, Integer> items = sortAndFilterMap(itemStackMap, false, null);
 | 
			
		||||
        this.craftingEntries = getCraftableRecipes(items, Objects.requireNonNull(player.getServer()));
 | 
			
		||||
        this.recipesList = getAvailableRecipes();
 | 
			
		||||
        super.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
@@ -89,6 +94,23 @@ public class CraftingScreen extends PagedGui {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean canCraft(RecipeEntry<CraftingRecipe> recipeEntry) {
 | 
			
		||||
        for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
 | 
			
		||||
            ItemStack stackToRemove = findMatchingStack(ingredient);
 | 
			
		||||
            if (stackToRemove == null) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            int requiredCount = canRemoveCount(stackToRemove, this.blockEntity.network.itemStackMap);
 | 
			
		||||
 | 
			
		||||
            Map<ItemStack, Integer> playerInventory = new HashMap<>();
 | 
			
		||||
            addInventoryToMap(this.storageScreen.getPlayer().getInventory(), playerInventory);
 | 
			
		||||
            if (requiredCount > 0 && canRemoveCount(stackToRemove, playerInventory) < requiredCount) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean craftOneStack(PlayerEntity player, RecipeEntry<CraftingRecipe> recipeEntry, boolean toPlayerInventory) {
 | 
			
		||||
        if (!canCraft(recipeEntry)) {
 | 
			
		||||
            return true; //stop
 | 
			
		||||
@@ -97,18 +119,12 @@ public class CraftingScreen extends PagedGui {
 | 
			
		||||
        ArrayList<ItemStack> stacksToRemove = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        // Check and remove ingredients
 | 
			
		||||
        if (!canCraft(recipeEntry)) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
 | 
			
		||||
            ItemStack stackToRemove = findMatchingStack(ingredient);
 | 
			
		||||
            if (stackToRemove == null){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            int requiredCount = canRemoveCount(stackToRemove, this.storageScreen.blockEntity.chests.inventory);
 | 
			
		||||
 | 
			
		||||
            if (requiredCount > 0 && canRemoveCount(stackToRemove, this.storageScreen.getPlayer().getInventory()) < requiredCount) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else {
 | 
			
		||||
                stacksToRemove.add(stackToRemove);
 | 
			
		||||
            }
 | 
			
		||||
            stacksToRemove.add(stackToRemove);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (ItemStack stack : stacksToRemove) {
 | 
			
		||||
@@ -118,14 +134,15 @@ public class CraftingScreen extends PagedGui {
 | 
			
		||||
        // Add the result to the appropriate inventory
 | 
			
		||||
        ItemStack outputStack = recipeEntry.value().getResult(storageScreen.getPlayer().getRegistryManager()).copy();
 | 
			
		||||
        if (toPlayerInventory) {
 | 
			
		||||
            if (canInsertItemIntoPlayerInventory(player, outputStack) == outputStack.getCount()) {
 | 
			
		||||
                player.getInventory().insertStack(outputStack);
 | 
			
		||||
            PlayerInventory playerInventory = player.getInventory();
 | 
			
		||||
            if (canInsertItemIntoInventory(playerInventory, outputStack) == outputStack.getCount()) {
 | 
			
		||||
                playerInventory.insertStack(outputStack);
 | 
			
		||||
            } else {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (this.storageScreen.blockEntity.chests.canAddItemStack(outputStack)) {
 | 
			
		||||
                this.storageScreen.blockEntity.chests.tryPutItemStack(outputStack);
 | 
			
		||||
            if (this.blockEntity.network.canAddItemStack(outputStack)) {
 | 
			
		||||
                this.blockEntity.network.putItemStackRemainder(outputStack);
 | 
			
		||||
            } else {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
@@ -142,24 +159,9 @@ public class CraftingScreen extends PagedGui {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean canCraft(RecipeEntry<CraftingRecipe> recipeEntry) {
 | 
			
		||||
        for (Ingredient ingredient : recipeEntry.value().getIngredients()) {
 | 
			
		||||
            ItemStack stackToRemove = findMatchingStack(ingredient);
 | 
			
		||||
            if (stackToRemove == null){
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
            int requiredCount = canRemoveCount(stackToRemove, this.storageScreen.blockEntity.chests.inventory);
 | 
			
		||||
 | 
			
		||||
            if (requiredCount > 0 && canRemoveCount(stackToRemove, this.storageScreen.getPlayer().getInventory()) < requiredCount) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private ItemStack findMatchingStack(Ingredient ingredient) {
 | 
			
		||||
        for (ItemStack stack : ingredient.getMatchingStacks()) {
 | 
			
		||||
            if (this.storageScreen.blockEntity.chests.canRemove(stack)) {
 | 
			
		||||
            if (this.blockEntity.network.canRemove(stack)) {
 | 
			
		||||
                return stack;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -168,7 +170,7 @@ public class CraftingScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    private void removeItems(ItemStack stack) {
 | 
			
		||||
        // Logic to remove items from the storage
 | 
			
		||||
        ItemStack fromPlayer = this.storageScreen.blockEntity.chests.removeItemStack(stack);
 | 
			
		||||
        ItemStack fromPlayer = this.blockEntity.network.removeItemStack(stack);
 | 
			
		||||
        if (fromPlayer != null && fromPlayer.getCount() > 0) {
 | 
			
		||||
            Inventory playerInventory = player.getInventory();
 | 
			
		||||
            for (int i = 0; i < playerInventory.size(); i++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
package systems.brn.server_storage.screens;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.sgui.api.gui.SimpleGui;
 | 
			
		||||
import net.minecraft.screen.ScreenHandlerType;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
 | 
			
		||||
public class DriveScreen extends SimpleGui {
 | 
			
		||||
    BlockPos pos;
 | 
			
		||||
    public DriveScreen(ServerPlayerEntity player, BlockPos pos) {
 | 
			
		||||
        super(ScreenHandlerType.HOPPER, player, false);
 | 
			
		||||
        this.pos = pos;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,26 +1,29 @@
 | 
			
		||||
package systems.brn.server_storage.screens;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.sgui.api.gui.AnvilInputGui;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
import eu.pb4.sgui.api.gui.SimpleGui;
 | 
			
		||||
import systems.brn.server_storage.blockentities.InventoryInterfaceBlockEntity;
 | 
			
		||||
 | 
			
		||||
public class SearchScreen extends AnvilInputGui {
 | 
			
		||||
 | 
			
		||||
    private final PagedGui storageScreen;
 | 
			
		||||
    private final SimpleGui parentScreen;
 | 
			
		||||
 | 
			
		||||
    public SearchScreen(PagedGui storageScreen, String defaultText) {
 | 
			
		||||
        super(storageScreen.getPlayer(), storageScreen.getLockPlayerInventory());
 | 
			
		||||
        this.storageScreen = storageScreen;
 | 
			
		||||
        storageScreen.close();
 | 
			
		||||
    public SearchScreen(SimpleGui parentScreen, String defaultText) {
 | 
			
		||||
        super(parentScreen.getPlayer(), parentScreen.getLockPlayerInventory());
 | 
			
		||||
        this.parentScreen = parentScreen;
 | 
			
		||||
        parentScreen.close();
 | 
			
		||||
        this.setDefaultInputValue(defaultText);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onClose() {
 | 
			
		||||
        super.onClose();
 | 
			
		||||
        storageScreen.open();
 | 
			
		||||
        parentScreen.open();
 | 
			
		||||
        String query = this.getInput();
 | 
			
		||||
        if (storageScreen instanceof StorageScreen) {
 | 
			
		||||
            ((StorageScreen) storageScreen).doSearch(query);
 | 
			
		||||
        if (parentScreen instanceof StorageScreen storageScreen) {
 | 
			
		||||
            storageScreen.doSearch(query);
 | 
			
		||||
        } else if (parentScreen instanceof SettingsScreen settingsScreen && settingsScreen.blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
 | 
			
		||||
            inventoryInterfaceBlockEntity.doSearch(query);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,83 +1,97 @@
 | 
			
		||||
package systems.brn.server_storage.screens;
 | 
			
		||||
 | 
			
		||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
 | 
			
		||||
import eu.pb4.sgui.api.gui.SimpleGui;
 | 
			
		||||
import net.minecraft.block.entity.BlockEntity;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
import net.minecraft.server.network.ServerPlayerEntity;
 | 
			
		||||
import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.Formatting;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
import systems.brn.server_storage.blockentities.InventoryInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
 | 
			
		||||
public class SettingsScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    private final StorageScreen storageScreen;
 | 
			
		||||
    private final SimpleGui parentScreen;
 | 
			
		||||
 | 
			
		||||
    private ArrayList<DisplayElement> settingsList;
 | 
			
		||||
 | 
			
		||||
    public SettingsScreen(StorageScreen storageScreen) {
 | 
			
		||||
        super(storageScreen.getPlayer(), null);
 | 
			
		||||
        this.storageScreen = storageScreen;
 | 
			
		||||
    public final BlockEntity blockEntity;
 | 
			
		||||
 | 
			
		||||
    public SettingsScreen(@Nullable SimpleGui parentScreen, ServerPlayerEntity player, BlockEntity blockEntity) {
 | 
			
		||||
        super(player, null);
 | 
			
		||||
        this.parentScreen = parentScreen;
 | 
			
		||||
        this.blockEntity = blockEntity;
 | 
			
		||||
        clearSettings();
 | 
			
		||||
        this.setTitle(Text.translatable("mco.configure.world.buttons.settings"));
 | 
			
		||||
        if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
 | 
			
		||||
            inventoryInterfaceBlockEntity.openSettingsScreens.add(this);
 | 
			
		||||
        }
 | 
			
		||||
        this.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SettingsScreen(StorageScreen parentScreen) {
 | 
			
		||||
        this(parentScreen, parentScreen.getPlayer(), parentScreen.blockEntity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SettingsScreen(SimpleGui parentScreen, BlockEntity blockEntity) {
 | 
			
		||||
        this(parentScreen, parentScreen.getPlayer(), blockEntity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public SettingsScreen(ServerPlayerEntity player, BlockEntity blockEntity) {
 | 
			
		||||
        this(null, player, blockEntity);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void addSetting(DisplayElement setting) {
 | 
			
		||||
        this.settingsList.add(setting);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onClose() {
 | 
			
		||||
        super.onClose();
 | 
			
		||||
        storageScreen.open();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateDisplay() {
 | 
			
		||||
        this.settingsList = new ArrayList<>();
 | 
			
		||||
        this.settingsList.add(containers());
 | 
			
		||||
        this.settingsList.add(autoSuck());
 | 
			
		||||
        super.updateDisplay();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected PagedGui.DisplayElement containers() {
 | 
			
		||||
        return PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(storageScreen.blockEntity.allInventories ? "gui.all" : "options.fov.min").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_CONTAINERS)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            storageScreen.blockEntity.allInventories ^= true;
 | 
			
		||||
                            storageScreen.blockEntity.markDirty();
 | 
			
		||||
                            storageScreen.blockEntity.rescanChests();
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            updateDisplay();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
        if (parentScreen != null) {
 | 
			
		||||
            parentScreen.open();
 | 
			
		||||
        }
 | 
			
		||||
        if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
 | 
			
		||||
            inventoryInterfaceBlockEntity.openSettingsScreens.remove(this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getPageAmount() {
 | 
			
		||||
        return Math.ceilDivExact(settingsList.size(), 9*6);
 | 
			
		||||
        return Math.ceilDivExact(settingsList.size(), 9 * 6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement getElement(int id) {
 | 
			
		||||
        if (id >= 0 && id < settingsList.size()) {
 | 
			
		||||
            return settingsList.get(id);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
        } else {
 | 
			
		||||
            return DisplayElement.empty();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected PagedGui.DisplayElement autoSuck() {
 | 
			
		||||
        return PagedGui.DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable(storageScreen.blockEntity.autoSuck ? "gui.yes" : "gui.no").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(storageScreen.blockEntity.autoSuck ? GUI_AUTOSUCK_ON : GUI_AUTOSUCK_OFF)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            storageScreen.blockEntity.autoSuck ^= true;
 | 
			
		||||
                            storageScreen.blockEntity.rescanChests();
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            updateDisplay();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    public DisplayElement getItem() {
 | 
			
		||||
        if (settingsList.isEmpty()) {
 | 
			
		||||
            return DisplayElement.filler();
 | 
			
		||||
        } else {
 | 
			
		||||
            return DisplayElement.of(
 | 
			
		||||
                    new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                            .setName(Text.translatable("mco.configure.world.settings.title").formatted(Formatting.WHITE))
 | 
			
		||||
                            .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                            .setSkullOwner(GUI_SETTINGS)
 | 
			
		||||
                            .setCallback((x, y, z) -> {
 | 
			
		||||
                                playClickSound(getPlayer());
 | 
			
		||||
                                this.open();
 | 
			
		||||
                            })
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void clearSettings() {
 | 
			
		||||
        this.settingsList = new ArrayList<>();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package systems.brn.server_storage.screens;
 | 
			
		||||
import eu.pb4.sgui.api.ClickType;
 | 
			
		||||
import eu.pb4.sgui.api.elements.GuiElementBuilder;
 | 
			
		||||
import eu.pb4.sgui.api.elements.GuiElementInterface;
 | 
			
		||||
import net.minecraft.entity.player.PlayerInventory;
 | 
			
		||||
import net.minecraft.item.ItemStack;
 | 
			
		||||
import net.minecraft.item.Items;
 | 
			
		||||
import net.minecraft.screen.slot.SlotActionType;
 | 
			
		||||
@@ -11,7 +12,7 @@ import net.minecraft.text.Text;
 | 
			
		||||
import net.minecraft.util.Formatting;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import org.jetbrains.annotations.Nullable;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.blockentities.StorageInterfaceBlockEntity;
 | 
			
		||||
import systems.brn.server_storage.lib.PagedGui;
 | 
			
		||||
 | 
			
		||||
import static systems.brn.server_storage.ServerStorage.ServerStorage_Crafting_Enable;
 | 
			
		||||
@@ -21,13 +22,13 @@ import static systems.brn.server_storage.lib.Util.removeCountFromLore;
 | 
			
		||||
 | 
			
		||||
public class StorageScreen extends PagedGui {
 | 
			
		||||
    private final ServerPlayerEntity player;
 | 
			
		||||
    public final StorageBlockEntity blockEntity;
 | 
			
		||||
    public final StorageInterfaceBlockEntity blockEntity;
 | 
			
		||||
 | 
			
		||||
    public StorageScreen(ServerPlayerEntity player, BlockPos pos, @Nullable Runnable closeCallback) {
 | 
			
		||||
        super(player, closeCallback);
 | 
			
		||||
        this.player = player;
 | 
			
		||||
        this.setLockPlayerInventory(false);
 | 
			
		||||
        this.blockEntity = (StorageBlockEntity) player.getWorld().getBlockEntity(pos);
 | 
			
		||||
        this.blockEntity = (StorageInterfaceBlockEntity) player.getWorld().getBlockEntity(pos);
 | 
			
		||||
        assert blockEntity != null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -35,21 +36,25 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
    public boolean open() {
 | 
			
		||||
        page = blockEntity.page;
 | 
			
		||||
        this.blockEntity.openStorageScreens.add(this);
 | 
			
		||||
        this.blockEntity.rescanChests();
 | 
			
		||||
        blockEntity.updateDisplays();
 | 
			
		||||
        return super.open();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void updateDisplay() {
 | 
			
		||||
        String title = blockEntity.chests.containerUsedSlots +
 | 
			
		||||
        blockEntity.justReindexDrives();
 | 
			
		||||
        String title = blockEntity.network.driveUsedSlots +
 | 
			
		||||
                "u/" +
 | 
			
		||||
                blockEntity.chests.containerSlots +
 | 
			
		||||
                blockEntity.network.driveTotalSlots +
 | 
			
		||||
                "t(" +
 | 
			
		||||
                blockEntity.chests.containerFreeSlots +
 | 
			
		||||
                blockEntity.network.driveFreeSlots +
 | 
			
		||||
                "f)" +
 | 
			
		||||
                "[" +
 | 
			
		||||
                blockEntity.chests.containerCount +
 | 
			
		||||
                "c]";
 | 
			
		||||
                blockEntity.network.driveContainerCount +
 | 
			
		||||
                "c]" +
 | 
			
		||||
                "[" +
 | 
			
		||||
                blockEntity.network.drivesCount +
 | 
			
		||||
                "d]";
 | 
			
		||||
 | 
			
		||||
        setTitle(Text.of(title));
 | 
			
		||||
        super.updateDisplay();
 | 
			
		||||
@@ -57,14 +62,17 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected int getPageAmount() {
 | 
			
		||||
        return Math.ceilDivExact(blockEntity.chests.inventory.size(), 9 * 6);
 | 
			
		||||
        return Math.ceilDivExact(blockEntity.network.itemStackMap.size(), 9 * 6);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement getElement(int id) {
 | 
			
		||||
        if (blockEntity.chests.inventory.size() > id) {
 | 
			
		||||
            ItemStack itemStack = blockEntity.chests.inventory.getStack(id);
 | 
			
		||||
            ItemStack newStack = addCountToLore(itemStack.getCount(), itemStack, null);
 | 
			
		||||
        if (blockEntity.network.itemStackMap.size() > id) {
 | 
			
		||||
            ItemStack itemStackKey = (ItemStack) blockEntity.network.itemStackMap.keySet().toArray()[id];
 | 
			
		||||
            ItemStack aestheticStack = itemStackKey.copy();
 | 
			
		||||
            int count = blockEntity.network.itemStackMap.get(itemStackKey);
 | 
			
		||||
            aestheticStack.setCount(Math.max(aestheticStack.getMaxCount(), count));
 | 
			
		||||
            ItemStack newStack = addCountToLore(count, aestheticStack, null);
 | 
			
		||||
            GuiElementBuilder guiElement = new GuiElementBuilder(newStack);
 | 
			
		||||
            return DisplayElement.of(guiElement);
 | 
			
		||||
        }
 | 
			
		||||
@@ -74,7 +82,8 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean onClick(int index, ClickType type, SlotActionType action, GuiElementInterface element) {
 | 
			
		||||
        GuiElementInterface clickedElement = getSlot(index);
 | 
			
		||||
        if (clickedElement != null) {
 | 
			
		||||
        ItemStack cursorStack = getPlayer().currentScreenHandler.getCursorStack();
 | 
			
		||||
        if (clickedElement != null && cursorStack.isEmpty()) {
 | 
			
		||||
            ItemStack clickedItem = clickedElement.getItemStack();
 | 
			
		||||
            ItemStack noLoreStack = removeCountFromLore(clickedItem);
 | 
			
		||||
            if (type.isRight) {
 | 
			
		||||
@@ -95,27 +104,35 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!(type.isRight && type.shift)) {
 | 
			
		||||
                int insertCount = canInsertItemIntoPlayerInventory(player, noLoreStack);
 | 
			
		||||
                PlayerInventory playerInventory = player.getInventory();
 | 
			
		||||
                int insertCount = canInsertItemIntoInventory(playerInventory, noLoreStack);
 | 
			
		||||
                ItemStack insertingStack = noLoreStack.copy();
 | 
			
		||||
                insertingStack.setCount(insertCount);
 | 
			
		||||
                blockEntity.rescanChests();
 | 
			
		||||
                if (blockEntity.chests.canRemove(noLoreStack) && insertCount > 0) {
 | 
			
		||||
                    player.getInventory().insertStack(insertingStack.copy());
 | 
			
		||||
                    blockEntity.chests.removeItemStack(insertingStack);
 | 
			
		||||
                    blockEntity.rescanChests();
 | 
			
		||||
                blockEntity.reindexDrives();
 | 
			
		||||
                if (blockEntity.network.canRemove(noLoreStack) && insertCount > 0) {
 | 
			
		||||
                    playerInventory.insertStack(insertingStack.copy());
 | 
			
		||||
                    blockEntity.network.removeItemStack(insertingStack);
 | 
			
		||||
                    blockEntity.reindexDrives();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!cursorStack.isEmpty()) {
 | 
			
		||||
            insertItem(cursorStack);
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void insertItem(ItemStack stack) {
 | 
			
		||||
        int canPutIn = stack.getCount() - blockEntity.network.putItemStackRemainder(stack);
 | 
			
		||||
        if (canPutIn > 0) {
 | 
			
		||||
            removeFromInventory(player.getInventory(), stack, canPutIn);
 | 
			
		||||
            blockEntity.reindexDrives();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean insertItem(ItemStack stack, int startIndex, int endIndex, boolean fromLast) {
 | 
			
		||||
        blockEntity.rescanChests();
 | 
			
		||||
        if (blockEntity.chests.tryPutItemStack(stack)) {
 | 
			
		||||
            removeFromInventory(player.getInventory(), stack, stack.getCount());
 | 
			
		||||
        }
 | 
			
		||||
        blockEntity.rescanChests();
 | 
			
		||||
        blockEntity.reindexDrives();
 | 
			
		||||
        insertItem(stack);
 | 
			
		||||
        return super.insertItem(stack, startIndex, endIndex, fromLast);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -136,17 +153,8 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement settings() {
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
                new GuiElementBuilder(Items.PLAYER_HEAD)
 | 
			
		||||
                        .setName(Text.translatable("mco.configure.world.settings.title").formatted(Formatting.WHITE))
 | 
			
		||||
                        .hideDefaultTooltip().noDefaults()
 | 
			
		||||
                        .setSkullOwner(GUI_SETTINGS)
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            SettingsScreen settingsScreen = new SettingsScreen(this);
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            settingsScreen.open();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
        SettingsScreen settingsScreen = new SettingsScreen(this);
 | 
			
		||||
        return settingsScreen.getItem();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -159,7 +167,7 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
                        .setCallback((x, y, z) -> {
 | 
			
		||||
                            this.blockEntity.sortAlphabetically ^= true;
 | 
			
		||||
                            playClickSound(getPlayer());
 | 
			
		||||
                            this.blockEntity.rescanChests();
 | 
			
		||||
                            this.blockEntity.reindexDrives();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
@@ -184,7 +192,7 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected DisplayElement crafting() {
 | 
			
		||||
        if (!this.getPlayer().getWorld().getGameRules().getBoolean(ServerStorage_Crafting_Enable)){
 | 
			
		||||
        if (!this.getPlayer().getWorld().getGameRules().getBoolean(ServerStorage_Crafting_Enable)) {
 | 
			
		||||
            return DisplayElement.filler();
 | 
			
		||||
        }
 | 
			
		||||
        return DisplayElement.of(
 | 
			
		||||
@@ -203,7 +211,7 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
 | 
			
		||||
    public void doSearch(String query) {
 | 
			
		||||
        this.blockEntity.searchString = query;
 | 
			
		||||
        this.blockEntity.rescanChests();
 | 
			
		||||
        this.blockEntity.reindexDrives();
 | 
			
		||||
        this.page = 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -218,7 +226,7 @@ public class StorageScreen extends PagedGui {
 | 
			
		||||
                            playClickSound(player);
 | 
			
		||||
                            this.page = 0;
 | 
			
		||||
                            this.blockEntity.searchString = "";
 | 
			
		||||
                            this.blockEntity.rescanChests();
 | 
			
		||||
                            this.blockEntity.reindexDrives();
 | 
			
		||||
                        })
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
{
 | 
			
		||||
  "multipart": [
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "north": "none", "south": "none", "west": "none", "east": "none", "up": "none", "down": "none" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_blank" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "north": "bus" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_bus_north" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "south": "bus" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_bus_south" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "west": "bus" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_bus_west" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "east": "bus" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_bus_east" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "up": "bus" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_bus_up" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "down": "bus" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/bus_connector_bus_down" }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,32 @@
 | 
			
		||||
{
 | 
			
		||||
  "multipart": [
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "north": "none", "south": "none", "west": "none", "east": "none", "up": "none", "down": "none" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_blank" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "north": "inventory" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_inventory_north" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "south": "inventory" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_inventory_south" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "west": "inventory" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_inventory_west" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "east": "inventory" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_inventory_east" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "up": "inventory" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_inventory_up" }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "when": { "down": "inventory" },
 | 
			
		||||
      "apply": { "model": "serverstorage:block/inventory_interface_inventory_down" }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,10 +1,14 @@
 | 
			
		||||
{
 | 
			
		||||
  "block.serverstorage.storage": "Networked storage interface",
 | 
			
		||||
 | 
			
		||||
  "block.serverstorage.inventory_interface": "Networked inventory interface",
 | 
			
		||||
 | 
			
		||||
  "block.serverstorage.drive_container": "Hard drive container",
 | 
			
		||||
 | 
			
		||||
  "item.serverstorage.drive_casing": "Hard drive casing",
 | 
			
		||||
 | 
			
		||||
  "block.serverstorage.bus_connector": "Storage network connector",
 | 
			
		||||
 | 
			
		||||
  "item.serverstorage.iron_drive": "Iron hard drive",
 | 
			
		||||
  "item.serverstorage.iron_head": "Iron hard drive head",
 | 
			
		||||
  "item.serverstorage.iron_platter": "Iron hard drive platter",
 | 
			
		||||
@@ -19,5 +23,37 @@
 | 
			
		||||
 | 
			
		||||
  "item.serverstorage.netherite_drive": "Netherite hard drive",
 | 
			
		||||
  "item.serverstorage.netherite_head": "Netherite hard drive head",
 | 
			
		||||
  "item.serverstorage.netherite_platter": "Netherite hard drive platter"
 | 
			
		||||
  "item.serverstorage.netherite_platter": "Netherite hard drive platter",
 | 
			
		||||
 | 
			
		||||
  "item.serverstorage.module_bus": "Bus module",
 | 
			
		||||
  "item.serverstorage.module_configuration": "Configuration module",
 | 
			
		||||
  "item.serverstorage.module_container": "Container module",
 | 
			
		||||
  "item.serverstorage.module_display": "Display module",
 | 
			
		||||
  "item.serverstorage.module_drive": "Drive module",
 | 
			
		||||
  "item.serverstorage.module_filtering": "Filtering module",
 | 
			
		||||
  "item.serverstorage.module_inventory": "Inventory module",
 | 
			
		||||
  "item.serverstorage.module_pagination": "Pagination module",
 | 
			
		||||
  "item.serverstorage.module_transport": "Transport module",
 | 
			
		||||
 | 
			
		||||
  "item.serverstorage.module_pcb": "Module PCB",
 | 
			
		||||
 | 
			
		||||
  "item.serverstorage.drive_controller": "Drive controller",
 | 
			
		||||
  "item.serverstorage.cpu": "Central Processing Unit",
 | 
			
		||||
  "item.serverstorage.cpu_substrate": "CPU substrate",
 | 
			
		||||
  "item.serverstorage.pcb": "Printed Circuit Board",
 | 
			
		||||
  "item.serverstorage.pcb_substrate": "PCB substrate",
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  "gui.serverstorage.store_all": "Store all items from inventory",
 | 
			
		||||
  "gui.serverstorage.filter": "Filter",
 | 
			
		||||
  "gui.serverstorage.sort_alphabetically": "Sort alphabetically",
 | 
			
		||||
  "gui.serverstorage.sort_descending": "Sort by count descending",
 | 
			
		||||
  "gui.serverstorage.mode_input": "Input",
 | 
			
		||||
  "gui.serverstorage.mode_output": "Output",
 | 
			
		||||
  "gui.serverstorage.direction_north": "North",
 | 
			
		||||
  "gui.serverstorage.direction_south": "South",
 | 
			
		||||
  "gui.serverstorage.direction_west": "West",
 | 
			
		||||
  "gui.serverstorage.direction_east": "East",
 | 
			
		||||
  "gui.serverstorage.direction_up": "Up",
 | 
			
		||||
  "gui.serverstorage.direction_down": "Down"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube_all",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "all": "serverstorage:block/bus_connector_bus"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube_all",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "all": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube_all",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "all": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/bus_connector_bus",
 | 
			
		||||
    "up": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "north": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "south": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "west": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "east": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "up": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "north": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "south": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "west": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "east": "serverstorage:block/bus_connector_bus"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "up": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "north": "serverstorage:block/bus_connector_bus",
 | 
			
		||||
    "south": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "west": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "east": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "up": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "north": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "south": "serverstorage:block/bus_connector_bus",
 | 
			
		||||
    "west": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "east": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "up": "serverstorage:block/bus_connector_bus",
 | 
			
		||||
    "north": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "south": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "west": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "east": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "up": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "north": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "south": "serverstorage:block/bus_connector_blank",
 | 
			
		||||
    "west": "serverstorage:block/bus_connector_bus",
 | 
			
		||||
    "east": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube_all",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "all": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube_all",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "all": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube_all",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "all": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/inventory_interface_inventory",
 | 
			
		||||
    "up": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "north": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "south": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "west": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "east": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "up": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "north": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "south": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "west": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "east": "serverstorage:block/inventory_interface_inventory"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "up": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "north": "serverstorage:block/inventory_interface_inventory",
 | 
			
		||||
    "south": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "west": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "east": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "up": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "north": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "south": "serverstorage:block/inventory_interface_inventory",
 | 
			
		||||
    "west": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "east": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "up": "serverstorage:block/inventory_interface_inventory",
 | 
			
		||||
    "north": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "south": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "west": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "east": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,11 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "block/cube",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "down": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "up": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "north": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "south": "serverstorage:block/inventory_interface_blank",
 | 
			
		||||
    "west": "serverstorage:block/inventory_interface_inventory",
 | 
			
		||||
    "east": "serverstorage:block/inventory_interface_blank"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "serverstorage:block/bus_connector_blank"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/cpu"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/cpu_substrate"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/drive_controller"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,3 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "serverstorage:block/inventory_interface"
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_bus"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_configuration"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_container"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_display"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_drive"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_filtering"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_inventory"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_pagination"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_pcb"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/module_transport"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/pcb"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "parent": "minecraft:item/handheld",
 | 
			
		||||
  "textures": {
 | 
			
		||||
    "layer0": "serverstorage:item/pcb_substrate"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
		 After Width: | Height: | Size: 372 B  | 
| 
		 After Width: | Height: | Size: 388 B  | 
| 
		 After Width: | Height: | Size: 410 B  | 
| 
		 Before Width: | Height: | Size: 390 B After Width: | Height: | Size: 434 B  | 
| 
		 Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 441 B  | 
| 
		 Before Width: | Height: | Size: 414 B After Width: | Height: | Size: 448 B  | 
| 
		 Before Width: | Height: | Size: 386 B After Width: | Height: | Size: 439 B  | 
| 
		 Before Width: | Height: | Size: 399 B After Width: | Height: | Size: 438 B  | 
| 
		 Before Width: | Height: | Size: 408 B After Width: | Height: | Size: 441 B  | 
| 
		 Before Width: | Height: | Size: 317 B After Width: | Height: | Size: 403 B  | 
| 
		 Before Width: | Height: | Size: 143 B After Width: | Height: | Size: 331 B  | 
| 
		 After Width: | Height: | Size: 397 B  | 
| 
		 After Width: | Height: | Size: 396 B  | 
							
								
								
									
										
											BIN
										
									
								
								src/main/resources/assets/serverstorage/textures/item/cpu.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 379 B  | 
| 
		 After Width: | Height: | Size: 313 B  | 
| 
		 Before Width: | Height: | Size: 173 B After Width: | Height: | Size: 322 B  | 
| 
		 After Width: | Height: | Size: 396 B  | 
| 
		 Before Width: | Height: | Size: 757 B After Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 764 B After Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 761 B After Width: | Height: | Size: 1.2 KiB  | 
| 
		 Before Width: | Height: | Size: 342 B After Width: | Height: | Size: 419 B  | 
| 
		 Before Width: | Height: | Size: 248 B After Width: | Height: | Size: 401 B  | 
| 
		 Before Width: | Height: | Size: 238 B After Width: | Height: | Size: 350 B  | 
| 
		 Before Width: | Height: | Size: 365 B After Width: | Height: | Size: 410 B  | 
| 
		 After Width: | Height: | Size: 377 B  | 
| 
		 After Width: | Height: | Size: 421 B  | 
| 
		 After Width: | Height: | Size: 504 B  | 
| 
		 After Width: | Height: | Size: 380 B  |