This commit is contained in:
2026-01-31 22:34:20 -05:00
parent 9acd38c94b
commit 7b326a112e
15 changed files with 3608 additions and 213 deletions

View File

@@ -0,0 +1,217 @@
'use strict';
const Database = require('./database');
const Scanner = require('./scanner');
const Organizer = require('./organizer');
const WebServer = require('./web');
class Storage {
constructor(args) {
console.log('Storage: Constructor called');
this.bot = args.bot;
this.config = args;
this.isReady = false;
this.webServer = null;
}
init() {
console.log('Storage: init() called');
return new Promise((resolve, reject) => {
this.bot.on('onReady', async () => {
try {
console.log(`Storage: Bot ${this.bot.name} is ready, initializing storage system...`);
// Initialize database
if (!Database.db) {
console.log('Storage: Initializing database...');
await Database.initialize(this.config.dbFile || './storage/storage.db');
} else {
console.log('Storage: Database already initialized');
}
// Initialize scanner and organizer
console.log('Storage: Creating Scanner and Organizer...');
this.scanner = new Scanner();
this.organizer = new Organizer();
// Start web server
console.log('Storage: Starting web server...');
this.webServer = new WebServer();
await this.webServer.start(this.bot);
if (this.config.startupTasks) {
console.log('Storage: Running startup tasks...');
await this.config.startupTasks();
}
this.isReady = true;
console.log('Storage: Initialization complete! Ready to use.');
resolve();
} catch (error) {
console.error('Storage: Error in init:', error);
reject(error);
}
});
});
}
async unload(keepDb = false) {
console.log('Storage: Unloading...');
if (this.webServer) {
console.log('Storage: Stopping web server...');
await this.webServer.close();
this.webServer = null;
}
if (this.scanner) delete this.scanner;
if (this.organizer) delete this.organizer;
// Close database only if not keeping it for web server
if (!keepDb && Database.db) {
console.log('Storage: Closing database...');
Database.close();
}
this.isReady = false;
console.log('Storage: Unload complete');
}
async scanArea(force = false) {
const { sleep } = require('../../utils');
console.log(`Storage[${this.bot.name}]: Scanning storage area...`);
const chests = await this.scanner.discoverChests(this.bot, this.config.scanRadius || 30, Database);
const shulkers = await this.scanner.scanAllChests(this.bot, Database);
console.log(`Storage[${this.bot.name}]: Complete - ${chests.length} chests, ${shulkers} shulkers`);
}
async handleTrade(playerName, itemsReceived) {
const { sleep } = require('../../utils');
console.log(`Storage[${this.bot.name}]: Processing trade from ${playerName}, received ${itemsReceived.length} item types`);
// Log trade
await Database.logTrade(playerName, 'deposit', itemsReceived);
// Store items
let totalItems = 0;
for (const item of itemsReceived) {
totalItems += item.count;
}
console.log(`Storage[${this.bot.name}]: Sorting ${totalItems} items from ${playerName}`);
}
async handleWithdrawRequest(playerName, itemId, count) {
console.log(`Storage[${this.bot.name}]: Withdraw request from ${playerName}: ${itemId} x${count}`);
// Search for item
const items = await Database.searchItems(itemId);
if (!items || items.length === 0) {
return this.bot.whisper(playerName, `Item not found: ${itemId}`);
}
const item = items[0];
if (item.total_count < count) {
return this.bot.whisper(playerName, `Not enough ${item.item_name}. Available: ${item.total_count}`);
}
// Queue withdrawal
await Database.queueWithdrawal(playerName, itemId, item.item_name, count);
this.bot.whisper(playerName, `Withdrawal queued. Use /trade when ready.`);
}
async getStatus(playerName) {
const stats = await Database.getStats();
this.bot.whisper(playerName, `Storage: ${stats.totalItems} items in ${stats.totalShulkers} shulkers (${stats.totalChests} chests)`);
}
async findItem(itemName) {
return await Database.searchItems(itemName);
}
async checkPermission(name, requiredRole) {
return await Database.checkPermission(name, requiredRole);
}
// Command handler for in-game commands
async handleCommand(from, command, ...args) {
console.log(`Storage: Command '${command}' from ${from} with args:`, args);
switch (command) {
case 'scan':
this.bot.whisper(from, 'Starting storage scan...');
try {
await this.scanArea(true);
const stats = await Database.getStats();
this.bot.whisper(from, `Scan complete! ${stats.totalChests} chests, ${stats.totalShulkers} shulkers, ${stats.totalItems} items`);
} catch (error) {
console.error('Storage: Scan error:', error);
this.bot.whisper(from, `Scan failed: ${error.message}`);
}
break;
case 'status':
await this.getStatus(from);
break;
case 'withdraw':
const [itemName, count] = args;
await this.handleWithdrawRequest(from, itemName, count);
break;
case 'find':
const [searchTerm] = args;
const items = await this.findItem(searchTerm);
if (items.length === 0) {
this.bot.whisper(from, `No items found matching '${searchTerm}'`);
} else {
const results = items.slice(0, 5).map(i => `${i.item_name}: ${i.total_count}`);
this.bot.whisper(from, `Found: ${results.join(', ')}`);
}
break;
case 'chests':
const chests = await Database.getChests();
this.bot.whisper(from, `Tracking ${chests.length} chests`);
break;
case 'organize':
this.bot.whisper(from, 'Organize not yet implemented');
break;
case 'addplayer':
const [playerName, role] = args;
try {
await Database.addPlayer(playerName, role || 'team');
this.bot.whisper(from, `Added ${playerName} as ${role || 'team'}`);
} catch (error) {
this.bot.whisper(from, `Failed to add player: ${error.message}`);
}
break;
case 'removeplayer':
const [removePlayer] = args;
try {
await Database.removePlayer(removePlayer);
this.bot.whisper(from, `Removed ${removePlayer}`);
} catch (error) {
this.bot.whisper(from, `Failed to remove player: ${error.message}`);
}
break;
case 'players':
const players = await Database.getAllPlayers();
const playerList = players.map(p => `${p.player_name}(${p.role})`).join(', ');
this.bot.whisper(from, `Players: ${playerList}`);
break;
default:
this.bot.whisper(from, `Unknown command: ${command}`);
}
}
}
module.exports = Storage;