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 |