diff --git a/server/database.js b/server/database.js index 924786d..910d6c1 100644 --- a/server/database.js +++ b/server/database.js @@ -145,6 +145,25 @@ export function initializeDatabase() { ) `); + // Chunk analysis table (ore density per chunk) + db.exec(` + CREATE TABLE IF NOT EXISTS chunks ( + x INTEGER NOT NULL, + z INTEGER NOT NULL, + analysis TEXT DEFAULT '{}', + scanned_at INTEGER NOT NULL, + PRIMARY KEY (x, z) + ) + `); + + // Add block_state and block_tags columns to world_blocks if not present + try { + db.exec(`ALTER TABLE world_blocks ADD COLUMN block_state TEXT DEFAULT '{}'`); + } catch (e) { /* column already exists */ } + try { + db.exec(`ALTER TABLE world_blocks ADD COLUMN block_tags TEXT DEFAULT '{}'`); + } catch (e) { /* column already exists */ } + // Create indexes for better performance db.exec(` CREATE INDEX IF NOT EXISTS idx_world_blocks_discovered @@ -156,6 +175,16 @@ export function initializeDatabase() { ON task_queue(status, priority DESC); `); + db.exec(` + CREATE INDEX IF NOT EXISTS idx_world_blocks_name + ON world_blocks(block_name); + `); + + db.exec(` + CREATE INDEX IF NOT EXISTS idx_chunks_coords + ON chunks(x, z); + `); + console.log('✅ Database initialized'); } @@ -203,12 +232,14 @@ export function getTurtleConfig(turtleId) { } // World Blocks -export function saveWorldBlock(x, y, z, blockName, metadata, discoveredBy) { +export function saveWorldBlock(x, y, z, blockName, metadata, discoveredBy, blockState = null, blockTags = null) { const stmt = db.prepare(` - INSERT OR REPLACE INTO world_blocks (x, y, z, block_name, metadata, discovered_by, discovered_at) - VALUES (?, ?, ?, ?, ?, ?, ?) + INSERT OR REPLACE INTO world_blocks (x, y, z, block_name, metadata, discovered_by, discovered_at, block_state, block_tags) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) `); - stmt.run(x, y, z, blockName, metadata || 0, discoveredBy, Date.now()); + stmt.run(x, y, z, blockName, metadata || 0, discoveredBy, Date.now(), + blockState ? JSON.stringify(blockState) : '{}', + blockTags ? JSON.stringify(blockTags) : '{}'); } export function getWorldBlocks(limit = 10000) { @@ -545,5 +576,82 @@ export function closeDatabase() { db.close(); } +// ========== CHUNK ANALYSIS ========== + +export function saveChunkAnalysis(x, z, analysis) { + const stmt = db.prepare(` + INSERT OR REPLACE INTO chunks (x, z, analysis, scanned_at) + VALUES (?, ?, ?, ?) + `); + stmt.run(x, z, JSON.stringify(analysis), Date.now()); +} + +export function getChunkAnalysis(x, z) { + const stmt = db.prepare('SELECT * FROM chunks WHERE x = ? AND z = ?'); + const row = stmt.get(x, z); + if (row) { + return { ...row, analysis: JSON.parse(row.analysis) }; + } + return null; +} + +export function getAllChunkAnalyses() { + const stmt = db.prepare('SELECT * FROM chunks'); + return stmt.all().map(row => ({ + ...row, + analysis: JSON.parse(row.analysis) + })); +} + +// ========== BLOCK SEARCH ========== + +export function getBlocksWithNameLike(fromX, fromY, fromZ, toX, toY, toZ, namePattern) { + const stmt = db.prepare(` + SELECT x, y, z, block_name as name, metadata, block_state, block_tags + FROM world_blocks + WHERE x BETWEEN ? AND ? + AND y BETWEEN ? AND ? + AND z BETWEEN ? AND ? + AND block_name LIKE ? + `); + return stmt.all( + Math.min(fromX, toX), Math.max(fromX, toX), + Math.min(fromY, toY), Math.max(fromY, toY), + Math.min(fromZ, toZ), Math.max(fromZ, toZ), + namePattern + ).map(row => ({ + ...row, + state: row.block_state ? JSON.parse(row.block_state) : {}, + tags: row.block_tags ? JSON.parse(row.block_tags) : {}, + })); +} + +export function getBlock(x, y, z) { + const stmt = db.prepare('SELECT block_name as name, metadata, block_state, block_tags FROM world_blocks WHERE x = ? AND y = ? AND z = ?'); + const row = stmt.get(x, y, z); + if (row) { + return { + ...row, + state: row.block_state ? JSON.parse(row.block_state) : {}, + tags: row.block_tags ? JSON.parse(row.block_tags) : {}, + }; + } + return null; +} + +export function deleteBlocksInArea(fromX, fromY, fromZ, toX, toY, toZ) { + const stmt = db.prepare(` + DELETE FROM world_blocks + WHERE x BETWEEN ? AND ? + AND y BETWEEN ? AND ? + AND z BETWEEN ? AND ? + `); + return stmt.run( + Math.min(fromX, toX), Math.max(fromX, toX), + Math.min(fromY, toY), Math.max(fromY, toY), + Math.min(fromZ, toZ), Math.max(fromZ, toZ) + ); +} + // Export database instance for custom queries if needed export { db };