'use strict'; const Vec3 = require('vec3'); const conf = require('../../conf'); class Organizer { constructor() { this.categories = conf.storage?.categories || { minerals: ['diamond', 'netherite_ingot', 'gold_ingot', 'iron_ingot'], food: ['bread', 'cooked_porkchop', 'steak'], tools: ['diamond_sword', 'diamond_pickaxe', 'netherite_pickaxe'], armor: ['diamond_chestplate', 'netherite_helmet'], blocks: ['stone', 'dirt', 'cobblestone'], redstone: ['redstone', 'repeater', 'piston'], misc: [] }; } categorizeItem(itemName) { // Fast path: check each category for (const [category, items] of Object.entries(this.categories)) { if (items.includes(itemName)) { return category; } } return 'misc'; } async findShulkerForItem(database, itemId, categoryName) { // Find shulker with matching item that has space const shulker = await database.findShulkerForItem(itemId, categoryName); return shulker; } async findEmptyShulkerSlot(database, categoryName) { // Find an empty shulker in the appropriate category and row (prefer row 4 for empty storage) const chests = await database.getChests(); // Filter chests by category and row 4 (top row for empty/new shulkers) const categoryChests = chests.filter(c => c.category === categoryName && c.row === 4 ).sort((a, b) => a.column - b.column); // Left to right for (const chest of categoryChests) { const shulkers = await database.getShulkersByChest(chest.id); // Find first shulker that's empty (slotCount = 0) or has space for (const shulker of shulkers) { if (!shulker.item_focus) { // Empty shulker available return { chest_id: chest.id, chestPosition: new Vec3(chest.pos_x, chest.pos_y, chest.pos_z), chestSlot: shulker.slot, shulker_id: shulker.id }; } } } // If no empty shulker, look for first available slot in row 4 // ... this would need to scan actual chest for empty slots return null; } async sortItemIntoStorage(bot, database, item, categoryName) { // Find existing shulker with same item and space const existingShulker = await this.findShulkerForItem(database, item.id, categoryName); if (existingShulker) { // Space available, add to existing shulker console.log(`Organizer: Found shulker ${existingShulker.id} for ${item.name}`); return existingShulker; } else { // Need new shulker console.log(`Organizer: Creating new shulker for ${item.name} (${categoryName})`); const shulkerSlot = await this.findEmptyShulkerSlot(database, categoryName); if (!shulkerSlot) { console.log(`Organizer: No available shulker slot for ${item.name}`); return null; } // Create/prepare new shulker await database.upsertShulker( shulkerSlot.chest_id, shulkerSlot.chestSlot, 'shulker_box', categoryName, item.name // item_focus ); console.log(`Organizer: Created shulker at chest ${shulkerSlot.chest_id}, slot ${shulkerSlot.chestSlot}`); return { chest_id: shulkerSlot.chest_id, slot: shulkerSlot.chestSlot, new: true }; } } } module.exports = Organizer;