A bit of an update

This commit is contained in:
Bruno Rybársky 2024-07-04 13:44:48 +02:00
parent 7f8d4b8eb3
commit c6b94b2716
137 changed files with 2468 additions and 724 deletions

BIN
assets/CPU.aseprite Normal file

Binary file not shown.

BIN
assets/Connector.aseprite Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/Module_PCB.aseprite Normal file

Binary file not shown.

BIN
assets/PCB.aseprite Normal file

Binary file not shown.

@ -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);
}
}

@ -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++) {

@ -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;
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);
// 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();
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,19 +119,13 @@ 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);
}
}
for (ItemStack stack : stacksToRemove) {
removeItems(stack);
@ -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,54 +1,63 @@
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();
if (parentScreen != null) {
parentScreen.open();
}
@Override
public void updateDisplay() {
this.settingsList = new ArrayList<>();
this.settingsList.add(containers());
this.settingsList.add(autoSuck());
super.updateDisplay();
if (blockEntity instanceof InventoryInterfaceBlockEntity inventoryInterfaceBlockEntity) {
inventoryInterfaceBlockEntity.openSettingsScreens.remove(this);
}
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();
})
);
}
@Override
@ -60,24 +69,29 @@ public class SettingsScreen extends PagedGui {
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(
public DisplayElement getItem() {
if (settingsList.isEmpty()) {
return DisplayElement.filler();
} else {
return DisplayElement.of(
new GuiElementBuilder(Items.PLAYER_HEAD)
.setName(Text.translatable(storageScreen.blockEntity.autoSuck ? "gui.yes" : "gui.no").formatted(Formatting.WHITE))
.setName(Text.translatable("mco.configure.world.settings.title").formatted(Formatting.WHITE))
.hideDefaultTooltip().noDefaults()
.setSkullOwner(storageScreen.blockEntity.autoSuck ? GUI_AUTOSUCK_ON : GUI_AUTOSUCK_OFF)
.setSkullOwner(GUI_SETTINGS)
.setCallback((x, y, z) -> {
storageScreen.blockEntity.autoSuck ^= true;
storageScreen.blockEntity.rescanChests();
playClickSound(getPlayer());
updateDisplay();
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();
})
);
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();
})
);
}
@ -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"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 402 B

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 439 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 399 B

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 408 B

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 317 B

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 B

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 173 B

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 764 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 761 B

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

After

Width:  |  Height:  |  Size: 419 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 248 B

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 B

After

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 504 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Some files were not shown because too many files have changed in this diff Show More