PrismarineJS / mineflayer

Create Minecraft bots with a powerful, stable, and high level JavaScript API.
https://prismarinejs.github.io/mineflayer/
MIT License
4.96k stars 904 forks source link

The deposit operation goes stuck when playing online #312

Closed Darker closed 4 years ago

Darker commented 9 years ago

I created a program to clear all useless items in nearby chest. The core of it uses the async framework and looks like this:

TaskClearInChest.prototype.useChest = function(block) {
var _this = this;
var chest = this.bot.openChest(block); 
//Adds .onTimeout method to chest object  
addTimedEvents(chest);
//This array will be filled with useless items
var items = [];
//Asynchronously open the chest and also find out what items are to be removed
async.parallel([
    //Open chest
    function(callback) {
    //Wait 3 second for chest to open. If it doesn't, end with error
    chest.onTimeout("open", callback,
    function() {
    callback(new Error("Chest opening failed on timeout."));
    }, 3000);
    },
    //Find useless items
    function(callback) {
    //This fills the items array with actual items. The quantity will account for sum of item type in inventory
    _this.bot.inventory.manager.uselessItems(items)
    callback();
    }
],
//After chest is open AND items have been calculated - Finally empty the items in chest
function(error) {
    //If previous tasks caused error, terminate
    if(error) {
    _this.finishedError(1, error);
    return;
    }
    console.log("|BOT: ClearInChest| Depositing "+items.length+" item types.");
    //For each series automatically loops through array and calls callback for each item
    // This is done async but only one task at a time
    async.forEachSeries(items,
    //Deposit one item type
    function(item, callback) {

    console.log("|BOT: ClearInChest|    Deposit "+item+"...");
    //Deposit the actual count, no more, no less
    chest.deposit(item.type, item.metadata, item.count, function(err) { 

    if(err)
        console.log("|BOT: ClearInChest|      [ERROR]:"+ err.message);
    else
        console.log("|BOT: ClearInChest|      [DONE]");
    //Call callback so that next item is iterated, or the loop ends
    callback();
    });
    },
    //Finally over
    function(err) {
    chest.close();
    console.log("|BOT: ClearInChest| Clearing done, chest closed.");
    if(err)
    _this.finishedError(1, err);
    else
    _this.finished();
    }
    );   
}
);
}

The problem is that while on localhost this never fails and really clears all items to chest (unless the chest is full, but even then it reports error and ends), on online servers it goes stuck at certain point. When I disconnect the player, one stack of items is dropped. Any idea where should I search the point where it freezes?

Typical output on localhost:

|BOT: ClearInChest| Starting inventory clear operation.
|BOT: InventoryManager| 2 useless items found.
|BOT: ClearInChest| Depositing 2 item types.
|BOT: ClearInChest|    Deposit #7/0 x384...
|BOT: ClearInChest|      [DONE]
|BOT: ClearInChest|    Deposit #1/0 x64...
|BOT: ClearInChest|      [DONE]
|BOT: ClearInChest| Clearing done, chest closed.
|BOT: Task| Task clearinchest over.

On online server, it goes stuck after calling deposit - the deposit's callback is never called so I see:

|BOT: ClearInChest| Starting inventory clear operation.
|BOT: InventoryManager| 2 useless items found.
|BOT: ClearInChest| Depositing 2 item types.
|BOT: ClearInChest|    Deposit #7/0 x384...

and that's over. It also usually manages to stuff some items in chest before going stuck.

rom1504 commented 9 years ago

Can you use '''js instead of ''' to have syntax highlighting ?

I'm pretty sure the problem is with "Wait 3 second for chest to open" : why are you waiting 3 seconds ? Use the events of the chest ;) Look at https://github.com/andrewrk/mineflayer/blob/master/examples/chest.js#L87

The reason why it would work on localhost but not on an online server is probably lag.

Darker commented 9 years ago

You misunderstood: What I do is that if the open operation does not call the event within 3 seconds, the bot asumes that something's wrong. And as I said, it manages to put certain ammout of items in chest - and never fails when playing on localhost.

rom1504 commented 9 years ago

Oh yeah ok I understand. What kind of server are you connecting to ? do you get the same result with a vanilla server ? I think it might be possible you're not getting a confirmTransaction packet in your server, so the callback in clickWindow might never be called https://github.com/andrewrk/mineflayer/blob/master/lib/plugins/inventory.js#L350

rom1504 commented 4 years ago

seems it's not an issue