The Steve's Simple Storage GUI system provides a modern Minecraft inventory interface for storage management. The system uses the standard Container/Screen architecture with custom slots for storage interaction.
Server Side: StorageCoreMenu (Container)
- Manages slot layout and item transfer logic
- Handles shift-click operations
- Validates player access
Client Side: StorageCoreScreen (Screen)
- Renders GUI background and elements
- Handles user input and rendering
- Displays tooltips and labels
Location: core/.../gui/server/StorageCoreMenu
The server-side container that manages the storage GUI.
Slot Layout:
// Storage slots: 54 slots (6 rows × 9 columns)
for (int row = 0; row < 6; row++) {
for (int col = 0; col < 9; col++) {
int index = col + row * 9;
addSlot(new StorageSlot(storageContainer, blockEntity, index,
8 + col * 18, 18 + row * 18));
}
}
// Player inventory: 27 slots (3 rows × 9 columns)
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9,
8 + j * 18, 140 + i * 18));
}
}
// Player hotbar: 9 slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 198));
}Shift-Click Logic:
public ItemStack quickMoveStack(Player player, int index) {
Slot slot = this.slots.get(index);
if (slot != null && slot.hasItem()) {
ItemStack slotStack = slot.getItem();
if (index < 54) {
// Moving from storage to player inventory
moveItemStackTo(slotStack, 54, this.slots.size(), true);
} else {
// Moving from player inventory to storage
moveItemStackTo(slotStack, 0, 54, false);
}
}
}Location: core/.../gui/client/StorageCoreScreen
The client-side screen that renders the storage GUI.
Configuration:
public StorageCoreScreen(StorageCoreMenu menu, Inventory playerInventory, Component title) {
super(menu, playerInventory, title);
this.imageHeight = 222; // Height for 6 rows + player inventory
this.imageWidth = 176; // Standard width
// Position labels to prevent overlap
this.titleLabelY = 6; // Top of GUI
this.inventoryLabelY = this.imageHeight - 94; // Above player inventory
}Rendering:
protected void renderBg(GuiGraphics guiGraphics, float partialTick, int mouseX, int mouseY) {
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
guiGraphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
}Location: core/.../gui/slot/StorageSlot
Custom slot implementation for storage interaction.
Key Features:
- Item Insertion: Intercepts item placement to store in StorageInventory
- Drag & Drop: Supports standard Minecraft drag operations
- Remainder Handling: Returns items that couldn't be stored
- Logging: Comprehensive operation tracking
Implementation:
public void set(ItemStack stack) {
if (!stack.isEmpty() && storageCore != null) {
ItemStack remainder = storageCore.insertItem(stack);
super.set(remainder); // Show remainder in slot
} else {
super.set(stack);
}
}
public boolean mayPlace(ItemStack stack) {
return !stack.isEmpty(); // Accept all non-empty stacks
}The GUI uses a pixel-based coordinate system with the following layout:
┌─────────────────────────────────────────────────────────────────────┐
│ Title (Y=6) │
├─────────────────────────────────────────────────────────────────────┤
│ Storage Slots (6 rows × 9 columns) │
│ Y=18 to Y=125, X=8 to X=170 │
│ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┐ │
│ │ 0 │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ Row 0 (Y=18) │
│ ├───┼───┼───┼───┼───┼───┼───┼───┼───┤ │
│ │ 9 │10 │11 │12 │13 │14 │15 │16 │17 │ Row 1 (Y=36) │
│ │...│...│...│...│...│...│...│...│...│ │
│ │45 │46 │47 │48 │49 │50 │51 │52 │53 │ Row 5 (Y=108) │
│ └───┴───┴───┴───┴───┴───┴───┴───┴───┘ │
├─────────────────────────────────────────────────────────────────────┤
│ Inventory Label (Y=128) │
├─────────────────────────────────────────────────────────────────────┤
│ Player Inventory (3 rows × 9 columns) │
│ Y=140 to Y=194, X=8 to X=170 │
├─────────────────────────────────────────────────────────────────────┤
│ Player Hotbar (1 row × 9 columns) │
│ Y=198, X=8 to X=170 │
└─────────────────────────────────────────────────────────────────────┘
Total Height: 222 pixels
Total Width: 176 pixels
Storage Slots:
int x = 8 + column * 18; // Columns 0-8
int y = 18 + row * 18; // Rows 0-5Player Inventory:
int x = 8 + column * 18; // Columns 0-8
int y = 140 + row * 18; // Rows 0-2Player Hotbar:
int x = 8 + column * 18; // Columns 0-8
int y = 198; // Single rowLocation: assets/s3/textures/gui/storage_core.png
- Size: 256×256 pixels
- Format: PNG with transparency support
- Usage: Background for storage GUI
The GUI texture uses standard Minecraft GUI conventions:
- Background: Full texture area
- Slot Highlights: Standard 18×18 pixel slots
- Borders: 1-pixel borders around slot areas
-
Drag & Drop:
- Player drags item from inventory to storage slot
StorageSlot.set()intercepts and inserts into storage- Remainder appears in slot if storage becomes full
-
Shift-Click:
- Player shift-clicks item in player inventory
quickMoveStack()automatically finds available storage slot- Items transfer automatically without dragging
-
Direct Placement:
- Player clicks item stack on storage slot
- Standard Minecraft slot behavior with storage integration
-
Click & Drag:
- Currently not implemented (storage slots are insert-only)
- Future enhancement: Allow retrieval of stored items
-
Shift-Click:
- Currently not implemented for storage slots
- Future enhancement: Transfer stored items to player inventory
Location: neoforge/.../init/ModMenuTypes
public static final Supplier<MenuType<StorageCoreMenu>> STORAGE_CORE =
MENU_TYPES.register("storage_core", () ->
IMenuTypeExtension.create((windowId, inv, data) ->
new StorageCoreMenu(windowId, inv, data.readBlockPos())));Menu types are registered in the neoforge module and made available to core code via S3Platform static holders (see Build System - Platform Abstraction).
Location: neoforge/.../client/ClientEvents
@SubscribeEvent
public static void registerScreens(RegisterMenuScreensEvent event) {
event.register(ModMenuTypes.STORAGE_CORE.get(), StorageCoreScreen::new);
}Menu Operations:
LOGGER.debug("Creating StorageCoreMenu at {}", pos);
LOGGER.debug("quickMoveStack: slot {}", index);Slot Operations:
LOGGER.debug("StorageSlot.mayPlace: {} x{}", stack.getItem(), stack.getCount());
LOGGER.debug("StorageSlot.set: {} x{}", stack.getItem(), stack.getCount());-
Items Disappearing:
- Check
StorageSlot.set()implementation - Verify remainder handling
- Check storage capacity
- Check
-
Shift-Click Not Working:
- Verify
quickMoveStack()slot index ranges - Check
moveItemStackTo()parameters - Ensure proper slot registration
- Verify
-
GUI Layout Issues:
- Verify slot positioning coordinates
- Check GUI texture dimensions
- Validate label positioning
-
Item Retrieval ✅:
- Click storage slots to retrieve items
- Shift-click to move to player inventory
- Right-click for half stack retrieval
-
Search System ✅ (requires Search Box in multiblock):
- Search bar for finding specific items
- Real-time filter display based on search terms
- Multiple search modes: standard,
$tags,@mod,%tooltips
-
Sorting ✅ (requires Sort Box in multiblock):
- 6 sorting modes (count up/down, name A-Z/Z-A, mod A-Z/Z-A)
- Persistent sort mode selection
- See Storage System for details
-
JEI Integration ✅:
- Recipe transfer to crafting grid
- Ingredient lookup (R/U keys)
- Storage-aware recipe transfer handler
- Visual Enhancements:
- Item quantity overlays for large stacks
- Progress bars for storage capacity
- Visual indicators for full/empty slots
-
Performance:
- Lazy loading of storage slot contents
- Efficient rendering for large inventories
- Optimized network synchronization
-
Accessibility:
- Keyboard navigation support
- Screen reader compatibility
- Customizable GUI scaling
-
Integration:
- JEI recipe viewing from storage slots
- Waila/Hwyla tooltip integration
- REI compatibility for recipe lookup