> For the complete documentation index, see [llms.txt](https://docs.minecraftbot.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.minecraftbot.com/examples/start-plugins/wheat-farmer-intermediate.md).

# Wheat Farmer (intermediate)

**FarmTask.cs**

Task responsible for finding, breaking, and replanting wheat.

{% tabs %}
{% tab title="Commented Code" %}

```csharp
public class FarmTask : ITask, ITickListener
    {
        // Add additional costs to Jumping in order to discourage
        // the bot from jumping on our crops.
        private static MapOptions MO = new MapOptions()
        {
            AdditionalWeights = new MapOptionWeights()
            {
                JumpGap = 25,
                JumpUp = 25
            }
        };

        // https://docs.minecraftbot.com/api/utility/locationblacklistcollection
        private static LocationBlacklistCollection BLACKLIST = LocationBlacklistCollection.CreateGlobal(3, // blacklist location globally after 3 bots fail to reach it.
                                                                                                        600000, 1); // blacklist location for 10 minutes.

        private const int GROWN_WHEAT_METADATA = 7;
        private const int WHEAT_ID = 59;
        private const int SEED_ID = 295;

        public override bool Exec() {
            return !Context.Player.IsDead() &&
                   !Context.Player.State.Eating && !Context.Player.State.EatRequestQueued && // do not run if we are about to eat/are eating.
                   !Inventory.IsFull() && Context.Containers.GetOpenWindow() == null; // do not run if a chest is open or our inventory is full, as in that case the store task is running.
        }

        public async Task OnTick() {
            var block = await Context.World.FindClosest(64, 8, // search 64x64x8 area
                                                        WHEAT_ID, CpuMode.Medium_Usage,
                                                        consideredBlock => consideredBlock.GetMetadata() == GROWN_WHEAT_METADATA  // filter to only fully grown blocks (determined by metadata).
                                                                           && !BLACKLIST.IsBlocked(Context, consideredBlock.GetLocation())); // filter by blacklist as well.

            if (block == null)
                // We didn't find any grown wheat blocks close to the bot.
                return;

            if ((await block.MoveTo(MO).Task).Result == MoveResultType.Completed) {
                // Successfully moved to block, attempt to mine it.
                var mineAction = await block.Dig();
                await mineAction.DigTask;

                // Attempt to replant at the position that we mined at.
                if(await Inventory.Select(SEED_ID))
                    await block.PlaceAt(); // attempt to place the seeds at the block that we just mined.
            }
            else {
                // Could not path to the block, add it to our temporary block.
                BLACKLIST.AddToBlockCounter(Context, block.GetLocation());
            }
        }
    }
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public class FarmTask : ITask, ITickListener
    {
        private static MapOptions MO = new MapOptions()
        {
            AdditionalWeights = new MapOptionWeights() { JumpGap = 25, JumpUp = 25 } 
        };
        private static LocationBlacklistCollection BLACKLIST = LocationBlacklistCollection.CreateGlobal(3, 600000, 1); 

        private const int GROWN_WHEAT_METADATA = 7;
        private const int WHEAT_ID = 59;
        private const int SEED_ID = 295;

        public override bool Exec() {
            return !Context.Player.IsDead() &&
                   !Context.Player.State.Eating && !Context.Player.State.EatRequestQueued &&
                   !Inventory.IsFull() && Context.Containers.GetOpenWindow() == null;
        }

        public async Task OnTick() {
            var block = await Context.World.FindClosest(64, 8,
                                                        WHEAT_ID, CpuMode.Medium_Usage,
                                                        consideredBlock => consideredBlock.GetMetadata() == GROWN_WHEAT_METADATA
                                                                           && !BLACKLIST.IsBlocked(Context, consideredBlock.GetLocation()));

            if (block == null) return;

            if ((await block.MoveTo(MO).Task).Result == MoveResultType.Completed) {
                var mineAction = await block.Dig();
                await mineAction.DigTask;

                if(await Inventory.Select(SEED_ID))
                    await block.PlaceAt();
            else {
                BLACKLIST.AddToBlockCounter(Context, block.GetLocation());
            }
        }
    }
```

{% endtab %}
{% endtabs %}

**StoreTask.cs**

Task responsible for storing items into the nearest non-full chest when the bot's inventory is full.

{% tabs %}
{% tab title="Commented Code" %}

```csharp
    public class StoreTask : ITask, ITickListener
    {
        public override bool Exec() {
            return !Context.Player.IsDead() &&
                   !Context.Player.State.Eating && !Context.Player.State.EatRequestQueued && // do not run if we are about to eat/are eating.
                   (Inventory.IsFull() || Context.Containers.GetOpenWindow() != null); // run when our inventory is full or we have a chest open.
        }

        public async Task OnTick() {

            // Locate the nearest chests.
            var chestMap = Context.Functions.CreateChestMap();
            await chestMap.UpdateChestList();

            // Attempt to open a chest that is not full.
            var window = await chestMap.Open(ChestStatus.NotFull);
            if (window == null) return;

            // In this case we deposite all of our items, however
            // you could extend this by not storing food.
            await window.Deposit();
            await window.Close();
        }
    }
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
    public class StoreTask : ITask, ITickListener
    {
        public override bool Exec() {
            return !Context.Player.IsDead() &&
                   !Context.Player.State.Eating && !Context.Player.State.EatRequestQueued &&
                   (Inventory.IsFull() || Context.Containers.GetOpenWindow() != null);
        }

        public async Task OnTick() {

            var chestMap = Context.Functions.CreateChestMap();
            await chestMap.UpdateChestList();

            var window = await chestMap.Open(ChestStatus.NotFull);
            if (window == null) return;
            
            await window.Deposit();
            await window.Close();
        }
    }
```

{% endtab %}
{% endtabs %}

{% file src="/files/-LtGklFWfTGaYXyZJES4" %}
Full Plugin Source Code
{% endfile %}
