Mostly works
This commit is contained in:
@@ -2,12 +2,11 @@
|
||||
|
||||
const Vec3 = require('vec3');
|
||||
const { sleep } = require('../../utils');
|
||||
const { goals: { GoalNear } } = require('mineflayer-pathfinder');
|
||||
|
||||
const Database = require('./database');
|
||||
|
||||
class ShulkerHandler {
|
||||
constructor() {
|
||||
this.operationInProgress = false;
|
||||
this.scanner = null; // set by Storage after init
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ class ShulkerHandler {
|
||||
bot.bot.setControlState('sneak', false);
|
||||
|
||||
// Stop pathfinder movement too
|
||||
try { bot.bot.pathfinder.stop(); } catch (e) { /* ignore */ }
|
||||
bot.bot.clearControlStates();
|
||||
|
||||
// Retry dig up to 3 times — shulker closing animation can block the first attempt
|
||||
for (let digAttempt = 0; digAttempt < 3; digAttempt++) {
|
||||
@@ -395,18 +394,9 @@ class ShulkerHandler {
|
||||
async takeWholeShulker(bot, chestPos, chestSlot, shulkerId) {
|
||||
console.log(`ShulkerHandler: Taking whole shulker from chest at ${chestPos}, slot ${chestSlot}`);
|
||||
|
||||
if (this.operationInProgress) {
|
||||
throw new Error('Another shulker operation is in progress');
|
||||
}
|
||||
this.operationInProgress = true;
|
||||
|
||||
try {
|
||||
const invSlot = await this.takeShulkerFromChest(bot, chestPos, chestSlot, shulkerId);
|
||||
console.log(`ShulkerHandler: Whole shulker taken, now in inventory slot ${invSlot}`);
|
||||
return invSlot;
|
||||
} finally {
|
||||
this.operationInProgress = false;
|
||||
}
|
||||
const invSlot = await this.takeShulkerFromChest(bot, chestPos, chestSlot, shulkerId);
|
||||
console.log(`ShulkerHandler: Whole shulker taken, now in inventory slot ${invSlot}`);
|
||||
return invSlot;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,7 +425,7 @@ class ShulkerHandler {
|
||||
const retreatZ = botPos.z + (dz / dist) * 1.5;
|
||||
try {
|
||||
|
||||
await bot.bot.pathfinder.goto(new GoalNear(retreatX, botPos.y, retreatZ, 0.5));
|
||||
await bot.goTo({ where: new Vec3(retreatX, botPos.y, retreatZ), range: 0 });
|
||||
await sleep(300);
|
||||
} catch (e) {
|
||||
console.log(`ShulkerHandler: Retreat pathfind failed: ${e.message}`);
|
||||
@@ -503,7 +493,7 @@ class ShulkerHandler {
|
||||
const angle = (attempt * Math.PI / 2) + Math.PI / 4;
|
||||
const moveX = pos.x + Math.cos(angle) * 3;
|
||||
const moveZ = pos.z + Math.sin(angle) * 3;
|
||||
await bot.bot.pathfinder.goto(new GoalNear(moveX, pos.y, moveZ, 1));
|
||||
await bot.goTo({ where: new Vec3(moveX, pos.y, moveZ), range: 1 });
|
||||
} catch (e) {
|
||||
console.log(`ShulkerHandler: Move failed: ${e.message}`);
|
||||
}
|
||||
@@ -591,11 +581,6 @@ class ShulkerHandler {
|
||||
async depositIntoShulker(bot, chestPos, chestSlot, itemName, count, shulkerId, chestId, itemFilter = null) {
|
||||
console.log(`ShulkerHandler: Depositing ${count}x ${itemName} into shulker at chest ${chestPos} slot ${chestSlot}`);
|
||||
|
||||
if (this.operationInProgress) {
|
||||
throw new Error('Another shulker operation is in progress');
|
||||
}
|
||||
this.operationInProgress = true;
|
||||
|
||||
let placedPos = null;
|
||||
|
||||
try {
|
||||
@@ -716,8 +701,6 @@ class ShulkerHandler {
|
||||
}
|
||||
if (!recovered) throw error;
|
||||
return { deposited: 0, updatedSlotItem: null };
|
||||
} finally {
|
||||
this.operationInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,132 +712,123 @@ class ShulkerHandler {
|
||||
async unpackShulkerFromInventory(bot, shulkerItem) {
|
||||
console.log(`ShulkerHandler: Unpacking shulker ${shulkerItem.name} from inventory`);
|
||||
|
||||
if (this.operationInProgress) {
|
||||
throw new Error('Another shulker operation is in progress');
|
||||
// Step 1: Find placement spot
|
||||
const spot = this.findPlacementSpot(bot);
|
||||
|
||||
// Ensure bot is far enough from placement spot
|
||||
const botPos = bot.bot.entity.position;
|
||||
const placeDist = botPos.distanceTo(spot.position.offset(0.5, 0, 0.5));
|
||||
if (placeDist < 1.5) {
|
||||
console.log(`ShulkerHandler: Too close to placement spot (${placeDist.toFixed(1)} blocks), stepping back`);
|
||||
const dx = botPos.x - spot.position.x;
|
||||
const dz = botPos.z - spot.position.z;
|
||||
const dist = Math.sqrt(dx * dx + dz * dz) || 1;
|
||||
const retreatX = botPos.x + (dx / dist) * 1.5;
|
||||
const retreatZ = botPos.z + (dz / dist) * 1.5;
|
||||
try {
|
||||
|
||||
await bot.goTo({ where: new Vec3(retreatX, botPos.y, retreatZ), range: 0 });
|
||||
await sleep(300);
|
||||
} catch (e) {
|
||||
console.log(`ShulkerHandler: Retreat pathfind failed: ${e.message}`);
|
||||
}
|
||||
}
|
||||
this.operationInProgress = true;
|
||||
|
||||
try {
|
||||
// Step 1: Find placement spot
|
||||
const spot = this.findPlacementSpot(bot);
|
||||
// Step 2: Equip and place the shulker
|
||||
await bot.bot.equip(shulkerItem, 'hand');
|
||||
await bot.bot.waitForTicks(5);
|
||||
|
||||
// Ensure bot is far enough from placement spot
|
||||
const botPos = bot.bot.entity.position;
|
||||
const placeDist = botPos.distanceTo(spot.position.offset(0.5, 0, 0.5));
|
||||
if (placeDist < 1.5) {
|
||||
console.log(`ShulkerHandler: Too close to placement spot (${placeDist.toFixed(1)} blocks), stepping back`);
|
||||
const dx = botPos.x - spot.position.x;
|
||||
const dz = botPos.z - spot.position.z;
|
||||
const dist = Math.sqrt(dx * dx + dz * dz) || 1;
|
||||
const retreatX = botPos.x + (dx / dist) * 1.5;
|
||||
const retreatZ = botPos.z + (dz / dist) * 1.5;
|
||||
try {
|
||||
// Verify we're actually holding the shulker
|
||||
const heldItem = bot.bot.heldItem;
|
||||
if (!heldItem || !heldItem.name.includes('shulker_box')) {
|
||||
throw new Error(`Cannot equip shulker for unpack (holding: ${heldItem?.name || 'nothing'})`);
|
||||
}
|
||||
|
||||
await bot.bot.pathfinder.goto(new GoalNear(retreatX, botPos.y, retreatZ, 0.5));
|
||||
await sleep(300);
|
||||
} catch (e) {
|
||||
console.log(`ShulkerHandler: Retreat pathfind failed: ${e.message}`);
|
||||
// Look at the top face center of placement block
|
||||
await bot.bot.lookAt(spot.placeOn.position.offset(0.5, 1, 0.5), true);
|
||||
await bot.bot.waitForTicks(3);
|
||||
|
||||
// SAFETY: verify held item is a shulker RIGHT before placing — never place anything else
|
||||
const prePlaceItem = bot.bot.heldItem;
|
||||
if (!prePlaceItem || !prePlaceItem.name.includes('shulker_box')) {
|
||||
throw new Error(`ABORT: held item changed before place (holding: ${prePlaceItem?.name || 'nothing'})`);
|
||||
}
|
||||
|
||||
await bot.bot.placeBlock(spot.placeOn, spot.faceVec);
|
||||
await bot.bot.waitForTicks(10);
|
||||
|
||||
// Verify shulker was placed
|
||||
const placedBlock = bot.bot.blockAt(spot.position);
|
||||
if (!placedBlock || !placedBlock.name.includes('shulker_box')) {
|
||||
// Something wrong was placed — break it immediately
|
||||
console.error(`ShulkerHandler: WRONG BLOCK placed at ${spot.position} (${placedBlock?.name}), breaking it`);
|
||||
try { await bot.bot.dig(bot.bot.blockAt(spot.position)); } catch (e) { /* best effort */ }
|
||||
throw new Error(`Failed to place shulker at ${spot.position}`);
|
||||
}
|
||||
|
||||
// Step 3: Open the shulker
|
||||
const shulkerWindow = await bot.openContainer(placedBlock);
|
||||
await bot.bot.waitForTicks(5);
|
||||
|
||||
// Step 4: Move ALL items from shulker into bot inventory
|
||||
const extracted = [];
|
||||
let inventoryFull = false;
|
||||
const shulkerSlotCount = shulkerWindow.inventoryStart;
|
||||
|
||||
for (let s = 0; s < shulkerSlotCount; s++) {
|
||||
const shulkerSlotItem = shulkerWindow.slots[s];
|
||||
if (!shulkerSlotItem) continue;
|
||||
|
||||
// Find a target slot in bot inventory (stack first, then empty)
|
||||
let targetSlot = null;
|
||||
|
||||
for (let i = shulkerWindow.inventoryStart; i < shulkerWindow.inventoryEnd; i++) {
|
||||
const invItem = shulkerWindow.slots[i];
|
||||
if (invItem && invItem.name === shulkerSlotItem.name && invItem.count < invItem.stackSize) {
|
||||
targetSlot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: Equip and place the shulker
|
||||
await bot.bot.equip(shulkerItem, 'hand');
|
||||
await bot.bot.waitForTicks(5);
|
||||
|
||||
// Verify we're actually holding the shulker
|
||||
const heldItem = bot.bot.heldItem;
|
||||
if (!heldItem || !heldItem.name.includes('shulker_box')) {
|
||||
throw new Error(`Cannot equip shulker for unpack (holding: ${heldItem?.name || 'nothing'})`);
|
||||
}
|
||||
|
||||
// Look at the top face center of placement block
|
||||
await bot.bot.lookAt(spot.placeOn.position.offset(0.5, 1, 0.5), true);
|
||||
await bot.bot.waitForTicks(3);
|
||||
|
||||
// SAFETY: verify held item is a shulker RIGHT before placing — never place anything else
|
||||
const prePlaceItem = bot.bot.heldItem;
|
||||
if (!prePlaceItem || !prePlaceItem.name.includes('shulker_box')) {
|
||||
throw new Error(`ABORT: held item changed before place (holding: ${prePlaceItem?.name || 'nothing'})`);
|
||||
}
|
||||
|
||||
await bot.bot.placeBlock(spot.placeOn, spot.faceVec);
|
||||
await bot.bot.waitForTicks(10);
|
||||
|
||||
// Verify shulker was placed
|
||||
const placedBlock = bot.bot.blockAt(spot.position);
|
||||
if (!placedBlock || !placedBlock.name.includes('shulker_box')) {
|
||||
// Something wrong was placed — break it immediately
|
||||
console.error(`ShulkerHandler: WRONG BLOCK placed at ${spot.position} (${placedBlock?.name}), breaking it`);
|
||||
try { await bot.bot.dig(bot.bot.blockAt(spot.position)); } catch (e) { /* best effort */ }
|
||||
throw new Error(`Failed to place shulker at ${spot.position}`);
|
||||
}
|
||||
|
||||
// Step 3: Open the shulker
|
||||
const shulkerWindow = await bot.openContainer(placedBlock);
|
||||
await bot.bot.waitForTicks(5);
|
||||
|
||||
// Step 4: Move ALL items from shulker into bot inventory
|
||||
const extracted = [];
|
||||
let inventoryFull = false;
|
||||
const shulkerSlotCount = shulkerWindow.inventoryStart;
|
||||
|
||||
for (let s = 0; s < shulkerSlotCount; s++) {
|
||||
const shulkerSlotItem = shulkerWindow.slots[s];
|
||||
if (!shulkerSlotItem) continue;
|
||||
|
||||
// Find a target slot in bot inventory (stack first, then empty)
|
||||
let targetSlot = null;
|
||||
|
||||
if (targetSlot === null) {
|
||||
for (let i = shulkerWindow.inventoryStart; i < shulkerWindow.inventoryEnd; i++) {
|
||||
const invItem = shulkerWindow.slots[i];
|
||||
if (invItem && invItem.name === shulkerSlotItem.name && invItem.count < invItem.stackSize) {
|
||||
if (!shulkerWindow.slots[i]) {
|
||||
targetSlot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetSlot === null) {
|
||||
for (let i = shulkerWindow.inventoryStart; i < shulkerWindow.inventoryEnd; i++) {
|
||||
if (!shulkerWindow.slots[i]) {
|
||||
targetSlot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetSlot === null) {
|
||||
console.log('ShulkerHandler: Bot inventory full during unpack');
|
||||
inventoryFull = true;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
const itemName = shulkerSlotItem.name;
|
||||
const itemCount = shulkerSlotItem.count;
|
||||
await bot.bot.moveSlotItem(s, targetSlot);
|
||||
await sleep(200);
|
||||
extracted.push({ name: itemName, count: itemCount });
|
||||
} catch (error) {
|
||||
console.error(`ShulkerHandler: Error moving item from shulker slot ${s}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Close the shulker window — wait for closing animation
|
||||
await bot.bot.closeWindow(shulkerWindow);
|
||||
await bot.bot.waitForTicks(30);
|
||||
|
||||
// Step 6: Break the shulker block and pick it up
|
||||
const collected = await this.digAndCollectShulker(bot, spot.position);
|
||||
if (!collected) {
|
||||
console.error('ShulkerHandler: Shulker not found in inventory after breaking');
|
||||
if (targetSlot === null) {
|
||||
console.log('ShulkerHandler: Bot inventory full during unpack');
|
||||
inventoryFull = true;
|
||||
break;
|
||||
}
|
||||
|
||||
console.log(`ShulkerHandler: Unpacked ${extracted.length} item stacks from shulker`);
|
||||
return { extracted, inventoryFull };
|
||||
|
||||
} finally {
|
||||
this.operationInProgress = false;
|
||||
try {
|
||||
const itemName = shulkerSlotItem.name;
|
||||
const itemCount = shulkerSlotItem.count;
|
||||
await bot.bot.moveSlotItem(s, targetSlot);
|
||||
await sleep(200);
|
||||
extracted.push({ name: itemName, count: itemCount });
|
||||
} catch (error) {
|
||||
console.error(`ShulkerHandler: Error moving item from shulker slot ${s}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Step 5: Close the shulker window — wait for closing animation
|
||||
await bot.bot.closeWindow(shulkerWindow);
|
||||
await bot.bot.waitForTicks(30);
|
||||
|
||||
// Step 6: Break the shulker block and pick it up
|
||||
const collected = await this.digAndCollectShulker(bot, spot.position);
|
||||
if (!collected) {
|
||||
console.error('ShulkerHandler: Shulker not found in inventory after breaking');
|
||||
}
|
||||
|
||||
console.log(`ShulkerHandler: Unpacked ${extracted.length} item stacks from shulker`);
|
||||
return { extracted, inventoryFull };
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -865,11 +839,6 @@ class ShulkerHandler {
|
||||
async withdrawFromShulker(bot, chestPos, chestSlot, itemName, count, shulkerId, chestId) {
|
||||
console.log(`ShulkerHandler: Withdrawing ${count}x ${itemName} from shulker at chest ${chestPos} slot ${chestSlot}`);
|
||||
|
||||
if (this.operationInProgress) {
|
||||
throw new Error('Another shulker operation is in progress');
|
||||
}
|
||||
this.operationInProgress = true;
|
||||
|
||||
let placedPos = null;
|
||||
|
||||
try {
|
||||
@@ -1000,8 +969,6 @@ class ShulkerHandler {
|
||||
}
|
||||
if (!recovered) throw error;
|
||||
return { withdrawn: 0, updatedSlotItem: null };
|
||||
} finally {
|
||||
this.operationInProgress = false;
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -1012,11 +979,6 @@ class ShulkerHandler {
|
||||
async withdrawFromShulkerSlot(bot, chestPos, chestSlot, shulkerSlot, count, shulkerId, chestId) {
|
||||
console.log(`ShulkerHandler: Withdrawing from shulker slot ${shulkerSlot} at chest ${chestPos} slot ${chestSlot}`);
|
||||
|
||||
if (this.operationInProgress) {
|
||||
throw new Error('Another shulker operation is in progress');
|
||||
}
|
||||
this.operationInProgress = true;
|
||||
|
||||
let placedPos = null;
|
||||
|
||||
try {
|
||||
@@ -1119,8 +1081,6 @@ class ShulkerHandler {
|
||||
console.error('ShulkerHandler: Slot withdraw failed, attempting recovery:', error.message);
|
||||
await this.returnShulkerToChest(bot, chestPos, chestSlot, placedPos, chestId);
|
||||
return { withdrawn: 0, updatedSlotItem: null };
|
||||
} finally {
|
||||
this.operationInProgress = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user