# Introduction

This is the official documentation of OQ.MineBot \[www\.minecraftbot.com] plugin API.

## Creating Project

1\. Firstly you must create a new Class Library (.NET Framework):

<div align="center"><img src="/files/-LpZU7lQirqsGrF4U8Tn" alt=""></div>

{% hint style="warning" %}
Make sure you create a .NET Framework project, as .NET Standard (.NET Core) will not work.
{% endhint %}

\
2\. It is recommended to change your Output path to your bot's plugin folder, so that you can immediately compile it and run the plugin:

![](/files/-LpZUZXGkURst8YWqq37)

\
3\. After you coded your plugin and you are ready to test, you must build the plugin:\
(*You must Reload your plugin tab after each build, in order to use the latest build version*)\
&#x20;<img src="/files/-LpZUgANWS0HlA1cwSnk" alt="" data-size="original">&#x20;

## Installation

You can set-up the plugin API in a few different ways, however some are considered better practices and others are easier. There are 3 different methods listed below, ranked by best practice.

{% hint style="info" %}
Watch our environment setup tutorial [here](https://www.youtube.com/watch?v=OiqslWioVso).
{% endhint %}

1. **NuGet package**

   1. Open NuGet package manager\
      &#x20;<img src="/files/-LpZGoUR3R07KKgZ-67P" alt="" data-size="original">&#x20;
   2. Install the **OQ.MineBot.PluginBase** package\
      &#x20;<img src="/files/-LpZHTDnZtsEn0B3NhRP" alt="" data-size="original">&#x20;

   *(When a bot update is released you must go into the package manager, select the OQ.MineBot.PluginBase package and click the Update button)*

2. **Github clone**

   1. Clone the MineBot API (<https://github.com/OnlyQubes/OQ.MineBot.PluginBase.git>) into a local folder.\
      &#x20;<img src="/files/-LnDvz4zfqEdyLTzvd19" alt="" data-size="original">&#x20;
   2. Add cloned project into your solution.\
      &#x20;<img src="/files/-LnDz8OfMRoUHnsksVoS" alt="" data-size="original">&#x20;
   3. Reference it in your plugin project.\
      &#x20;<img src="/files/-LnDuaiQbNj-2SKC9Qpz" alt="" data-size="original">&#x20;

   *(When a bot update is released you must update the local repository with "git pull")*

3. **Dll**

   1. Download the latest dll from [Github](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/releases).
   2. Reference it in your plugin project.\
      &#x20;<img src="/files/-LnDuaiQbNj-2SKC9Qpz" alt="" data-size="original">&#x20;

   *(When a bot update is released you must redownload the dll file and re-add the reference to the new one)*

## File Structure

Plugins are made up of two types of classes: IStartPlugin and ITask. A plugin must have one IStartPlugin class, which is generally named PluginCore, and can have many Task classes. Below you will find the explanation and purpose of each type.\
It is good practice to store the tasks in a separate folder like this:

<div align="left"><img src="/files/-LpYlFQV2J_-cMJ1ZVKB" alt=""></div>

### PluginCore

The PluginCore class generally inherits from IStartPlugin and contains base plugin functions, such as OnLoad, OnEnable, OnDisable, OnStart, and OnStop. This class will also have the Plugin attribute, which will define the name, description, and version of the plugin.&#x20;

\
The **Plugin attribute** **defines the name, description, and version of the plugin**. All plugins need to have this in order to be loaded. The attribute can be applied to the class in the following way:

```csharp
[Plugin(1, "Example Plugin", "This is the description of the plugin.")]
public class PluginCore : IStartPlugin { /* PluginCore.cs code would go here */ }
```

\
The **OnLoad method** is called once the plugin is loaded/reloaded, which is usually when the bot is started. The method can optionally **register the plugin's settings** in the following way:\
(You can find a list of the setting types [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Base/Settings/List))

```csharp
public override void OnLoad(int version, int subversion, int buildversion) {
    this.Setting.Add(new BoolSetting("Boolean setting", "Description goes here.", true));
    this.Setting.Add(new StringSetting("String setting", "Description goes here.", "this is the default value"));
    this.Setting.Add(new NumberSetting("Number setting", "Description goes here.", 10, 0, 20));
}
```

\
The **OnStart method** is called when the plugin is started on a bot (and will be called for each bot). It is usually **used to register task classes**, which are explained below. Generally the settings are passed into the tasks from this method through the task constructor (*can be seen below in line 3*). Tasks can be registered in the following way:

```csharp
public override void OnStart() {
    RegisterTask(new MyTask());
    RegisterTask(new MyOtherTask(this.Setting.GetValue<string>("This is a number setting")));
}
```

{% file src="/files/-LpV8Cp71lEf3yh8vcEv" %}
Example PluginCore.cs
{% endfile %}

####

### Task

**Task classes must inherit from ITask**, which will require you to implement `bool Exec()`. The returned boolean will determine whether any of the listeners (explained below) will execute or not, where true will execute the appropriate listener and false will not execute it. Example:

```csharp
public class MyTask : ITask, ITickListener {
    public override bool Exec() {
        // return true; // would always execute listeners when appropriate.
        // return false; // would never execute listeners.
        return !Context.Player.State.Eating; // only execute if not currently eating.
    }
    public async Task OnTick() {
        // Code in here will be called each tick while the player is not eating.
        // If the player is eating then this code will be skipped until it is done.
    }
}
```

**Task classes have access to the Context variables**, these variable refer to the current bot and allow you to interact with the bot or it's environment. Context variables are: Context, State, World, Inventory, ~~Actions~~ (*legacy*), where Context is the main/parent class that allows you to access everything regarding this bot and the other variables are shortcuts to those variables.

You can then also optionally override `async Task Start()` and/or `async Task Stop()`. Start gets called after the Context (this.Context, this.Player, This.Inventory, etc) is initialized. Stop gets called when the plugin is stop for this (or all) bot(s).

**Tasks can inherit from Listener classes** (you can find all listener types [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Base/Plugin/Listeners)), which will hook the appropriate calls and will get executed if the Exec function returns true. The following code showcases the **ITickListener**, which is generally the most used listener:

```csharp
public class MyTask : ITask, ITickListener {
    public override bool Exec() {
        // Execute listeners only if the player is dead.
        return Context.Player.IsDead();
    }
    public async Task OnTick() {
        // This will be executed for every tick that the player is dead (Exec returns true).
        await Context.Player.Respawn();
    }
}
```

{% file src="/files/-LpYkuywALi3q5gKpCRb" %}
Example RespawnTask.cs
{% endfile %}

*The main idea behind tasks is that they allow you to separate complex tasks/jobs into different classes, which only run when needed.*

## Async Programming

...


# Quick Start

A quick start on writing plugins for OQ.MineBot. This can be seen as a tl;dr version of the Introduction, however it's still highly recommended to read the Introduction section.

To get quickly started with plugin making simply follow these instructions:

### Part 1: creating project and setting up dependencies.

* Create a Class Library (.NET Framework)\
  &#x20;<img src="/files/-LpZU7lQirqsGrF4U8Tn" alt="" data-size="original">&#x20;
* Ensure that you have all of the necessary pre-requisites:
  * Open NuGet package manager.\
    &#x20;<img src="/files/-LpZGoUR3R07KKgZ-67P" alt="" data-size="original">&#x20;
  * Install the **OQ.MineBot.PluginBase** package.\
    &#x20;<img src="/files/-LpZHTDnZtsEn0B3NhRP" alt="" data-size="original">&#x20;
* Every plugin is required to have a PluginCore which is used for things like defining attributes like the name of the plugin, version, and description:\
  &#x20;<img src="/files/-LpZQUASCUImuF3NhgWm" alt="" data-size="original">&#x20;
* Then you will need to have an OnLoad method which will be called once the plugin is loaded/reloaded, which is usually when the bot is started. The settings are optional and can be overwritten if you don't want to include any settings:\
  &#x20;<img src="/files/-LpZRecnGbxwALaQ5I-1" alt="" data-size="original">&#x20;
* Finally, you will need an OnStart method which will register all of your task classes and is called as soon as the plugin is started on a bot:\
  &#x20;<img src="/files/-LpZRJLRkmxygPNjQGnq" alt="" data-size="original">&#x20;

### Part 2: creating tasks

* Create a task class, which will allow you to interact with the bot and it's environment.
* Inherit from ITask (and optionally any of the [Listeners](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Base/Plugin/Listeners)):\
  &#x20;<img src="/files/-LpZaoPGKUA3F4LIC4yw" alt="" data-size="original">&#x20;
* Implement Exec, which will tell the bot if any of the Listeners can be called, and add any listener code:\
  &#x20;<img src="/files/-LpZbUC1F-0yLwJSnzRz" alt="" data-size="original">&#x20;

<br>

:tada: **That's it, now you can build the plugin and test it on the bot**:tada: \
For a more in-depth guide check out the [Introduction page](https://docs.minecraftbot.com/).<br>

{% file src="/files/-LpZclX-neFHbqt9fVm6" %}
Download Template Code Here
{% endfile %}


# Start Plugins

Start plugins have a checkbox in the Plugins tab and are usually started on all of the connected accounts.


# Events (basic)

A basic code example that shows you how to make a plugin listen for certain events.

#### EventTask.cs

Task class that will be registered in PluginBase.cs and will be responsible to handle/report events that we receive from the server.

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

```csharp
public class EventTask : ITask, IDeathListener, ITickListener {

    // Start gets called once the Task is registered by 
    // PluginCore.cs using RegisterTask(). This ensures that
    // the Context variable has been set to the current bot's context.
    public override async Task Start() {
        // We can register events here for the events that do
        // not have an inheritable listener class.
        // (unlike inheritable listeners these events will ignore 
        // the Exec() function)
        EventsContext.Events.onChat += OnChatMessageReceived;
    }
    
    // The stop method is called once the plugin is stopped for this bot.
    public override async Task Stop() {
        // It is important to unregister any events that we register manually
        // (in Start).
        Context.Events.onChat -= OnChatMessageReceived;
    }

    // Determines wether the listeners (IDeathListener, ITickListener) will execute.
    // If this returns true then the listeners do execute normally,
    // otherwise the events will not be called.
    public override bool Exec() {
        // Always execute.
        return true;
    }

    // Event is called when bot dies and Exec() returns true,
    // this is because we inherit from IDeathListener.     
    public async Task OnDeath() {
        Console.WriteLine($"Oh no, the bot {Context.Player.GetUsername()} just died!");
    }
    
    public async Task OnTick() {
        // This is called each tick (~50ms) while Exec() returns true.
    }

    public void OnChatMessageReceived(IBotContext context, IChat message, byte position) {
        if (!Exec()) return; // manually check if Exec tells us to execute.
        Console.WriteLine($"Message received: {message.GetText()}");
    }
}
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public class EventTask : ITask, IDeathListener, ITickListener {

    public override async Task Start() {
        Context.Events.onChat += OnChatMessageReceived;
    }

    public override async Task Stop() {
        Context.Events.onChat -= OnChatMessageReceived;
    }

    public override bool Exec() {
        return true;
    }

    public async Task OnDeath() {
        Console.WriteLine($"Oh no, the bot {Context.Player.GetUsername()} just died!");
    }

    public async Task OnTick() { }

    public void OnChatMessageReceived(IBotContext context, IChat message, byte position) {
        if (!Exec()) return;
        Console.WriteLine($"Message received: {message.GetText()}");
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
You can find out all of the available inheritable Listener classes [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Base/Plugin/Listeners).
{% endhint %}


# Movement (basic)

A basic code example that shows you how to make the bot move between two locations.

#### MovementTask.cs

Task class that will be registered in PluginBase.cs and will be responsible for Movement in this plugin.\
While the player is not then this task will move between two Locations.

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

```csharp
public class MovementTask : ITask, ITickListener {
    
    public static ILocation Location1 = new Location(100, 10, 100);
    public static ILocation Location2 = new Location(  1, 10, 100);
    
    public override bool Exec() {
        // Do not execute 'OnTick' if the bot is dead.
        return !Context.Player.IsDead();
    }
    
    public async Task OnTick() {
        // The 'await' keyword waits until MoveTo completes/fails and
        // only then continues the execution.
        var moveResult = await Context.Player.MoveTo(Location1).Task;
        if(moveResult.Result != MoveResultType.Completed) {
            // Failed to move to the location, lets output an error 
            // to the console and return.
            Console.WriteLine($"Failed to move to {Location1}!");
            return;
        }
        
        // We have successfully reached Location1, 
        // now we can start moving to Location2.
        var moveTask = Context.Player.MoveTo(Location2);
        
        /*
            As the MoveTo(Location2) code does not have the 'await' keyword 
            we can execute other actions parallel and optionally await later
            for the task to complete.
        */
        
        // Wait until MoveTo completes/fails to Location2. We do not care
        // if it succeeded therefore we do no assign the result to any variable.
        await moveTask.Task;
    }
}
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public class MovementTask : ITask, ITickListener {
    
    public static ILocation Location1 = new Location(100, 10, 100);
    public static ILocation Location2 = new Location(  1, 10, 100);
    
    public override bool Exec() {
        return !Context.Player.IsDead();
    }
    
    public async Task OnTick() {
        var moveResult = await Context.Player.MoveTo(Location1).Task;
        if(moveResult.Result != MoveResultType.Completed) {
            Console.WriteLine($"Failed to move to {Location1}!");
            return;
        }
        
        await Context.Player.MoveTo(Location2).Task;
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
It is usually desirable to use the 'await' keyword as it will pause all execution until the task completes and then the result can be used. Not awaiting for tasks to complete can cause another function (e.g.: OnTick) to start while a task is running (e.g.: while still moving).

\
Don't know what async programming is? Check out Microsoft's documentation [here](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/).
{% endhint %}


# Killaura (intermediate)

This example will show you code for a basic plugin that will follow and attack the closest target-able player. The plugin incorporates multiple tasks and therefore is marked as intermediate.

**FightTask.cs**

This task is responsible for targeting, moving, and attacking the closest non-friendly player.

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

```csharp
public class FightTask : ITask, ITickListener
    {
        private string[] Friendly;

        public FightTask(string[] friendly) {
            this.Friendly = friendly;
        }

        public override bool Exec() {
            return !Context.Player.IsDead() && !Context.Player.State.Eating;
        }

        public async Task OnTick() {

            // Get the closest player to us that is not in our friends list.
            var target = Context.Entities.GetClosestPlayer(false,
                         entity => !Friendly.Contains(entity.GetName()));
            if (target == null)
                // No target found, so do nothing this tick.
                // Optionally you could make the bot roam in this case.
                return;

            // Begin moving towards the target. We do not await for the task
            // to complete since we also want to attack the target while we
            // are running.
            var movementTask = target.Follow();

            // Find the best sword in our inventory and attempt to select it.
            // This should/could be in a different task, as this task should
            // be only responsible for moving and attacking targets.
            var sword = Inventory.FindBest(EquipmentType.Sword);
            if(sword != null) await sword.Select();

            // Run this for as long as we are chasing this player OR
            // if we are already very close to the target player.
            while (movementTask.IsMoving() ||
                   target.Position.Distance(Context.Player.GetPosition()) < 2) {
                
                // Only attack the player if it is within 4 blocks to us.
                if(target.Position.Distance(Context.Player.GetPosition()) < 5)
                    target.Attack();

                // Wait 2 ticks before each attack.
                await Context.TickManager.Sleep(2);
            }
        }
    }
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public class FightTask : ITask, ITickListener
    {
        private string[] Friendly;

        public FightTask(string[] friendly) {
            this.Friendly = friendly;
        }

        public override bool Exec() {
            return !Context.Player.IsDead() && !Context.Player.State.Eating;
        }

        public async Task OnTick() {

            var target = Context.Entities.GetClosestPlayer(false, entity => !Friendly.Contains(entity.GetName()));
            if (target == null) return;

            var movementTask = target.Follow();

            var sword = Inventory.FindBest(EquipmentType.Sword);
            if(sword != null) await sword.Select();

            while (movementTask.IsMoving() ||
                   target.Position.Distance(Context.Player.GetPosition()) < 2) {
                
                if(target.Position.Distance(Context.Player.GetPosition()) < 5)
                    target.Attack();

                await Context.TickManager.Sleep(2);
            }
        }
    }
```

{% endtab %}
{% endtabs %}

**RespawnTask.cs**

This task is responsible for respawning the bot when it dies.&#x20;

```csharp
    public class RespawnTask : ITask, IDeathListener
    {
        public override bool Exec() {
            return true;
        }

        public async Task OnDeath() {
            await Context.Player.Respawn();
        }
    }
```

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


# Wheat Farmer (intermediate)

This will show you code for a wheat farmer, meaning that it finds the closest fully grown wheat blocks, moves to them, breaks them, and finally replants them.

**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 %}


# Request Plugins

Request plugins are the ones that can only be invoked on one or more account through the Accounts tab. This means that they do not have a checkmark in the Plugins tab and usually don't run on all bots

{% hint style="warning" %}
Usually developers should use [Start Plugins](https://docs.minecraftbot.com/examples/start-plugins). This is for more niche plugins that should be only ran on one (or a few) bots at a time, such as Chat Spy or Container Viewer.
{% endhint %}

{% content-ref url="/pages/-LnDc8BhjNDQrsR9zi1V" %}
[Start Plugins](/examples/start-plugins)
{% endcontent-ref %}


# Chat (advanced)


# Macro Component Additions

Plugins can also add custom components to the macro builder. Regular plugin api functions can be used within the Execute method. This page describes how to make a plugin that registers new components.

**PluginCore.cs**

```csharp
[Plugin(1, "Extra Macro Component Plugin", "Adds new macro components to the macro builder!")]
public class PluginCore : IStartPlugin
{
    /// <summary>
    /// Should be used to check compatability with the
    /// current version of the bot.
    /// </summary>
    public override void OnLoad(int version, int subversion, int buildversion) { }
    public override PluginResponse OnEnable(IBotSettings botSettings) {
        /* Regular plugin content */
        return base.OnEnable(botSettings);
    }
}
    
public class TestMacroComponent : IExternalMacroComponent {
    
    public TestMacroComponent() {
        this.Category = MacroComponentCategory.Misc;
        this.Outputs = new IMacroOutputCollection(
            new KeyValuePair<string, ExternalMacroOutput>("success", new ExternalMacroOutput("Success", "This output gets called once the call finishes", true)),
            new KeyValuePair<string, ExternalMacroOutput>("output_internal_name", new ExternalMacroOutput("Error", "This output will never get called", false))
        );
        this.Variables = new IMacroVariableCollection(
            new KeyValuePair<string, ExternalMacroVariable>("variable_internal_name1", new ExternalMacroVariable(typeof(string), "Message", "What message should we send to chat?", "my default message!"))
        );
    }
    
    public override string GetName() {
        return "Test macro component";
    }
    
    public override string GetInternalName() {
        return "ex:test_macro_component";
    }
    
    public override string GetDescription() {
        return "This is a test macro component";
    }
    public override string GetInteractiveDescription() {
        var variableValue = GetVariable<string>("variable_internal_name1");
        return 
            string.IsNullOrWhiteSpace(variableValue) ? GetDescription() 
            : $"I will say {variableValue}.";
    }
    
    public override string Execute(IBotContext Context) {
        Context.Functions.Chat("My message: " + GetVariable<string>("variable_internal_name1"));
        return "success"; // or return "output_internal_name"
    }
}
```

## Outputs

<div align="left"><img src="/files/-M81_-5O27Jm_a5RT6Re" alt="Macro component outputs"></div>

Outputs refer to possible paths that the macro component will lead to. **The execute method should return a name of one of the registered outputs**. These should be registered in the constructor, as can be seen here:

```csharp
public TestMacroComponent() {
    ...
    this.Outputs = new IMacroOutputCollection(
        new KeyValuePair<string, ExternalMacroOutput>("success", new ExternalMacroOutput("Success", "This output gets called once the call finishes", true)),
        new KeyValuePair<string, ExternalMacroOutput>("output_internal_name", new ExternalMacroOutput("Error", "This output will never get called", false))
    );
    ...
}
```


# Botting Command Additions

Plugins can also add custom commands to the botting tab. Regular plugin api functions can be used within the Activate method. This page describes how to make a plugin that registers new commands.

**PluginCore.cs**

```csharp
[Plugin(1, "Extra Botting Command Plugin", "Adds new command to the botting tab!")]
public class PluginCore : IStartPlugin
{
    /// <summary>
    /// Should be used to check compatability with the
    /// current version of the bot.
    /// </summary>
    public override void OnLoad(int version, int subversion, int buildversion) { }
    public override PluginResponse OnEnable(IBotSettings botSettings) {
        /* Regular plugin content */
        return base.OnEnable(botSettings);
    }
}

public class TestCommand : IExternalCommand {
    public override string Name => "Test Command 1";
    public override string Description => "This is a description for the command.";

    public TestCommand() {
        this.Variables = new ICommandVariableCollection(
            new ExternalCommandVariable(typeof(string), "internal_variable_name", "Text to print", "What message should we send to the chat?", "This is a default message")
        );
    }

    public override CommandResponse Activate(IBotContext Context, ICommandVariables arguments, IStopToken token) {
        Context.Functions.Chat("Hello, my message is: " + arguments.Get<string>("internal_variable_name"));
        return new CommandResponse(); // no parameters means success=true
    }
}
```


# BotViewer Additions

Plugins can extend bot viewer's functionallity. This can be achived in two ways: Base Extensions, which run as soon as the user connects to the server, and Chat Command Based Extensions.


# Base Extension

Base extensions for the Bot Viewer get called as soon as the user connects to the bot's server.

**PluginCore.cs**

```csharp
[Plugin(1, "Bot Viewer Extension Plugin", "Test plugin to showcase bot viewer possible extensions.")]
public class PluginCore : IStartPlugin
{
    public override void OnLoad(int version, int subversion, int buildversion) { }
    public override PluginResponse OnEnable(IBotSettings botSettings) { return base.OnEnable(botSettings); }
}

public class ExampleHandler : IBotServerHandler {
    public override async Task OnConnected() {
        // This function is called once a user connects to the bot's proxy server.

        this.Events.FromClient.ChatMessage += (message, token) => {
            // Catch all messages from the client that start with a # symbol.
            if (message.StartsWith("#")) {

                // servers have to respond in a json format, e.g. https://minecraft.tools/en/json_text.php
                this.Client.SendChat("{\"text\":\"Test plugin received '"+message+"' message from you.\", \"bold\":true}"); 
                
                token.Cancel(); // Do not forward it to the server game server.
            }
        };

        this.Events.ToClient.AddVelocityToEntity += (entityId, modifiers, token) => {
            // Disable all velocity data being sent from the server (no knockback).
            if(entityId == Context.Player.GetEntityId())
                token.Cancel();
        };
    }
}
```

<div align="left"><img src="/files/-M8Nsz7sOtHftJ0WhAG8" alt="Result from running the example code."></div>

## Events

As can be seen from the example code, there are two types of bot viewer based events: FromClient, which are events that get triggered by the client attempting to send data to the server, and ToClient, which are events that get triggered when the server is attempting to send data to the client.

Each of these events can be cancelled, which means it would never reach the desired destination (e.g.: cancel a ChatMessage event so a chat message is never actually sent to the server). This can be done by calling the *token.Cancel()* function, where the token variable is a pararemeter of each event.

## Sending Data to Client

Data can be sent to the client through the Client variable, which should be  accessed in the following way: *this.Client*, as can be seen in the example code. This class has functions that allow you to send data to the client, such as SendChat, which would send a chat message to che connected client.

{% hint style="info" %}
To send data to the server you can still use the Context variable, which is heavilly documented in the API section of the docs.
{% endhint %}


# Chat Command Based Extension

These chat commands can be discovered through the !help command. Chat Command Based Extensions get invoked once the user sends a chat message with the desired keyword (Name variable).

**PluginCore.cs**

```csharp
[Plugin(1, "Bot Viewer Extension Plugin", "Test plugin to showcase bot viewer possible extensions using chat command invocations.")]
public class PluginCore : IStartPlugin
{
    public override void OnLoad(int version, int subversion, int buildversion) { }
    public override PluginResponse OnEnable(IBotSettings botSettings) { return base.OnEnable(botSettings); }
}

public class ExampleChatHandler : IBotServerChatHandler {
    public override string Name { get; set; } = "test";
    public override string Description { get; set; } = "This is a test chat command handler for OQMineBot's bot server.";
    public override string[] RequiredArguments { get; set; } = {"none|all", "opt|opt2|opt3" };
    public override string[] OptionalArguments { get; set; } = { "greet|insult" };

    public override ChatHandlerResult Execute(IBotContext Context, IConnectedClient Client, IBotServerEvents Events, string[] arguments) {

        // Sanity checks.
        if (arguments.Length < 1) return new ChatHandlerResult(false, "Argument not found.");
        var argument = arguments[0].ToLower();
        if (argument != "none" && argument != "all") return new ChatHandlerResult(false, "Invalid argument.");

        /*
         * Execute command here.
         */

        return new ChatHandlerResult(true); // success
    }
}
```

<div align="left"><img src="/files/-M8NtJGQkyD--LDREIfR" alt="Result from running the example code."></div>


# ID System (Item & Block ids)

Minecraft has stopped using their legacy id system from the 1.13 update and up-wards. That means that legacy id's will only work for 1.8.\*-1.12.\* . This ID system has been created to help with this.

{% hint style="info" %}
It is recommended to use Blocks.Instance.GetId in the **Start** function of your ITask class, and store results in variables for the whole class to use. This is considered best practice for performance.
{% endhint %}

{% hint style="info" %}
You can find item id name's in such sites: <https://minecraftitemids.com/>, <https://www.minecraftinfo.com/idlist.htm>, <https://www.deadmap.com/idlist> ...
{% endhint %}

## Blocks

The simplest form of getting a numeric id for both legacy ids (1.8-1.12) and the flattened ids is to use the static Blocks.Instance global variable.

**Example usage:**

```csharp
var redstoneLampId = Blocks.Instance.GetId("minecraft:redstone_lamp").Value;
```

*Note how GetId() returns a ushort?, this means that in cases where the passed string, in this case "minecraft:resdstone\_lamp" is not a valid or a matching name, then null is returned.*

*This null mechanism is useful in casses where Minecraft uses different names for different versions, as in some cases you can do the following:*

```csharp
var someBlockId = Blocks.Instance.GetId("minecraft:some_block_1_8_name") ?? Blocks.Instance.GetId("minecraft:some_block_1_13_name");
```

### Block more utility

There are also more functions on Blocks.Instance that make it easier to work with ids. The notable ones are:

* **Blocks.Instance.GetIds -** get an array of ids for an array of inputs, example usage:

```csharp
var fallingBlocks = Blocks.Instance.GetIds("minecraft:sand", "minecraft:red_sand", "minecraft:gravel");
```

* ...

## Items

Item ids work in the exact same way as the Block system, except it uses \***Items\*.Instance.GetId, instead of \*Blocks\*.Instance.GetId!**

**Example usage:**

```csharp
var fishingRodId= Items.Instance.GetId("minecraft:fishing_rod").Value;
```

*Note how GetId() returns a ushort?, this means that in cases where the passed string, in this case "minecraft:fishing\_rod" is not a valid or a matching name, then null is returned.*

*This null mechanism is useful in casses where Minecraft uses different names for different versions, as in some cases you can do the following:*

```csharp
var someItemId = Items.Instance.GetId("minecraft:some_item_1_8_name") ?? Items.Instance.GetId("minecraft:some_item_1_13_name");
```

### Items more utility

There are also more functions on Items.Instance that make it easier to work with ids. The notable ones are:

* **Items.Instance.GetIds -** get an array of ids for an array of inputs, example usage:

```csharp
var food = Items.Instance.GetIds("minecraft:apple", "minecraft:bread", "minecraft:cooked_porkchop", "minecraft:cooked_fish", "minecraft:cookie", "minecraft:melon", "minecraft:cooked_beef", "minecraft:cooked_chicken", "minecraft:carrot", "minecraft:baked_potato",
                "minecraft:pumpkin_pie", "minecraft:cooked_mutton", "minecraftA:cooked_salmon", "minecraft:beetroot", "minecraft:beetroot_soup", "minecraft:dried_kelp", "minecraft:honey_bottle", "minecraft:cooked_rabbit", "minecraft:suspicious_stew", "minecraft:cooked_cod"
            );
```

* ...


# Events

This section describes the events that can be hooked through Context.Events.

| Events                 |
| ---------------------- |
| onTick                 |
| onChat                 |
| onDisconnected         |
| onGameJoined           |
| onSpawned              |
| onWorldReload          |
| onHealthUpdate         |
| onDeath                |
| onStartedStarving      |
| onBlockChanged         |
| onChunkLoaded          |
| onPlayerMoved          |
| onInventoryChanged     |
| onSprintingChanged     |
| onExplosion            |
| onEntityEffectAdded    |
| onObjectSpawned        |
| onEntityVelocity       |
| onPlayerUpdate         |
| onExperienceChanged    |
| onResourcePackReceived |
| onEntityAttached       |

## Usage

You will generally be Registering tasks in the Start method of the task class. You will also generally want to unregister them in Stop method, otherwise the plugin may not stop execution.

```csharp
/* We assume that this is in an ITask class and the
   class is registered using 'RegisterTask' in the PluginCore class.
*/

public override async Task Start() {
   Context.Events.onChat += OnChat;
}
public override async Task Stop() {
   // The plugin has been stopped, therefore we should
   // unregister all the events.
   Context.Events.onChat -= OnChat;   
}

private void OnChat(IBotContext context, IChat message, byte position) {
   Console.WriteLine($"Bot '{context.Player.GetUsername()}' " +
                     $"received the message '{message.GetText()}'");
}
```

## Events

### onTick

Called each client tick, which is around 50ms. ITickListener uses this.

```csharp
event IPlayerDelegates.PlayerDelegate onTick;
```

### onChat

Called when the bot receives a chat message from the server. This also includes middle of the screen titles and above the hotbar messages. The type of message (chat, screen, above hotbar) can be determined by the position variable.

```csharp
event IPlayerDelegates.OnChatDelegate onChat;
```

### onDisconnected

Called once the bot is disconnected from the server.

```csharp
event IPlayerDelegates.PlayerReasonDelegate onDisconnected;
```

### onGameJoined

Called once the player joins the game. It is important to note that this will most likely run only if the plugin is enabled before the bot is started.

```csharp
event IPlayerDelegates.OnGameJoinedDelegate onGameJoined;
```

### onSpawned

Called once the player spawns into the game. This usually signifies that the bot's entity has been spawned by the server and is visible by other players.

```csharp
event IPlayerDelegates.OnSpawnedDelegate onSpawned;
```

### onHealthUpdate

Called once the bot's health or hunger is updated by the server. It is important to note that this is also for hunger changes as well, while the name suggest that it's only for health updates.

```csharp
event IPlayerDelegates.OnHealthUpdateDelegate onHealthUpdate;
```

### onDeath

Called when the bot's health drops to 0, which signifies that it has died.

```csharp
event IPlayerDelegates.OnDeathDelegate onDeath;
```

### onStartedStarving

Called when the bot starts starving, which is when it reaches 0 food.

```csharp
event IPlayerDelegates.OnStartedStartvingDelegate onStartedStarving;
```

### onBlockChange

Called once a block in the world changes.

```csharp
event IPlayerDelegates.OnBlockChangedDelegate onBlockChanged;
```

### onChunkLoaded

Called once a chunk is loaded/reloaded.

```csharp
event IPlayerDelegates.OnBlockChangedDelegate onBlockChanged;
```

### onPlayerMoved

Called once this bot is **moved by the server. This will not be triggered when the bot moves it self.**

```csharp
event IPlayerDelegates.OnPlayerMovedDelegate onPlayerMoved;
```

### onInventoryChanged

Called once an slot gets set or updated. This will also usually trigger when a new container is opened, as the server updates each slot of the container window.

```csharp
event IPlayerDelegates.OnInventoryChangedDelegate onInventoryChanged;
```

### onSprintChanged

Called once the bot's sprint state gets updated.

```csharp
event IPlayerDelegates.OnPlayerSprintUpdateDelegate onSprintingChanged;
```

### onWorldReload

Called once the world is fully reloaded, which is generally when respawning or teleporting.

```csharp
event IPlayerDelegates.PlayerDelegate onWorldReload;
```

### onEntityAttached <a href="#onentityattached" id="onentityattached"></a>

Called when the server sends an entity attached packet (e.g.: player sits in a minecart).\
Note: *This is only supported for 1.8.\**

```csharp
event IPlayerDelegates.OnEntityAttached onEntityAttached;
```

​

### OnResourcePackReceived <a href="#onresourcepackreceived" id="onresourcepackreceived"></a>

Called when the server sends a resource pack URL and hash to the client.

```csharp
event IPlayerDelegates.OnResourcePackReceived onResourcePackReceived
```

​

### onExperienceChanged <a href="#onexperiencechanged" id="onexperiencechanged"></a>

Called when the server updates the bot's experience

```csharp
event IPlayerDelegates.OnExperienceChanged onExperienceChanged
```

​

### onPlayerUpdate <a href="#onplayerupdate" id="onplayerupdate"></a>

Called before the player update, allows you to cancel all physics.

```csharp
event IPlayerDelegates.OnPlayerUpdate onPlayerUpdate;
```

​

### onEntityVelocity <a href="#onentityvelocity" id="onentityvelocity"></a>

Called once the server set's an entities velocity,

```csharp
event IPlayerDelegates.OnEntityVelocity onEntityVelocity;
```

​

### onObjectSpawned <a href="#onobjectspawned" id="onobjectspawned"></a>

Called once an object spawns.

```csharp
 event IPlayerDelegates.OnObjectSpawned onObjectSpawned;
```

​

### onEntityEffectAdded <a href="#onentityeffectadded" id="onentityeffectadded"></a>

Called once an Entity receives an effect.

```csharp
event IPlayerDelegates.OnEntityEffect onEntityEffectAdded;
```

​

### onExplosion <a href="#onexplosion" id="onexplosion"></a>

Called once an explosion occurs.

```csharp
event IPlayerDelegates.OnExplosionDelegate onExplosion;
```


# Context

This section describes (most) classes that can be accessed by Start Plugins from the Context class.


# Player

| Methods               | Properties    |
| --------------------- | ------------- |
| GetUuid               | State         |
| GetUsername           | Manager       |
| GetPosition           | PhysicsEngine |
| GetLocation           | Crafting      |
| GetRotation           | Controls      |
| GetHealth             |               |
| GetFood               |               |
| GetFoodSaturation     |               |
| GetEntityId           |               |
| GetHeldSlot           |               |
| GetHeldIndex          |               |
| IsDead                |               |
| GetExperienceLevel    |               |
| GetExperience         |               |
| GetEffects            |               |
| HasEffect             |               |
| SetCrouchState        |               |
| IsCrouching           |               |
| Chat                  |               |
| Respawn               |               |
| SwapItemInHands       |               |
| UseHeld               |               |
| Swing                 |               |
| Eat                   |               |
| SetLook               |               |
| LookAt                |               |
| LookAtSmooth          |               |
| Jump                  |               |
| MoveDirection         |               |
| MoveTo                |               |
| MoveToRange           |               |
| MoveToRangeCustom     |               |
| MoveToInteactionRange |               |
| CreateReusablePath    |               |
| ExecuteReusablePath   |               |
| Disconnect            |               |

## Properties

### State

The state can be accessed by **Context.Player.State**.\
The state contains information that is relevant to the current session of the bot, such as LoggedIn, Spawned, Eating, etc.

### Controls

The controls can be accessed by **Context.Player.Controls**.\
Provides high-level controls over the bot. This class allows you to use mouse and keyboard controls such as ClickMouseButton, HoldMouseButton, SpamMouseButton, KeyboardHoldForward, etc.

### Crafting

The crafting manager can be accessed by **Context.Player.Crafting**.\
Provides a high-level crafting interface. This class gives you access to functions Craft(CraftingTask task), and GetMaxCrafts(CraftingTask task).\
Note: [comments on Github](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/Crafting/ICrafting.cs) provide adequate explanations for this class.

## Methods

### GetUuid

Returns the bot's uuid. You can use <https://mcuuid.net/> to convert a username to an uuid manually. The returned value is in the format of \`91a546fca6fe44c99550ab2291f28760\` (does not have dashes).

```csharp
string GetUuid();
```

### GetUsername

Returns the username of the bot.

```csharp
string GetUsername();
```

### GetPosition

Returns the position of the bot.

```csharp
IPosition GetPosition();
```

### GetLocation

Returns the Location of the bot, where the coordinates are rounded down from doubles to integers.

```csharp
ILocation GetLocation();
```

### GetRotation

Returns the rotation (yaw, pitch) of the bot.

```csharp
IRotation GetRotation();
```

### GetHealth

Returns the health of the bot.\
Note: *the Health is measured 0 (aka dead) up to 20 (full health), not up to 10 like Minecraft's visual indicators.*

```csharp
float GetHealth();
```

### GetFood

Returns the how much food the bot has.\
Note: *the Food is measured 0 up to 20, not up to 10 like Minecraft's visual indicators.*

```csharp
float GetFood();
```

### GetFoodSaturation

Returns the food saturation of the bot.

```csharp
float GetFoodSaturation();
```

### GetEntityId

Returns the bot's entity's id. This is sent over by the server to the bot and other bots may have different entity ids for this bot.

```csharp
int GetEntityId();
```

### GetHeldSlot

Returns the hobar slot that the bot has currently selected. This can be null or empty.

```csharp
 ISlot GetHeldSlot();
```

### GetHeldIndex

Returns the index (0-8) of the hotbar slot that the bot has currently selected.

```csharp
short GetHeldIndex();
```

### IsDead

Returns whether the bot is dead.

```csharp
bool IsDead();
```

###

### GetExperienceLevel

Returns the bot's experience level.

```csharp
int GetExperienceLevel();
```

### GetExperience

Returns the total experience points of the bot.

```csharp
int GetExperience();
```

### GetEffects

Returns the IEffectContainer of the bot, which can be used to determine the bot's status effects (e.g.: poisoned, regeneration, strength), their duration, and their level.

```csharp
IEffectContainer GetEffects()
```

### HasEffect

Returns whether the bot has the specified effect.

```csharp
bool HasEffect(Effects effect)
```

### SetCrouchState

Sets the crouching state of the bot to the specified mode (Couch, Uncrouched).

```csharp
Task SetCrouchState(CrouchStates mode);
```

### IsCrouching

Returns whether the bot is crouching.

```csharp
bool IsCrouching();
```

### Chat

Sends a chat message to the server. Server commands are also sent from this, however they have `/` appended to the beginning of the message.\
Note: *protocols up to 1.11 have a character limit of 100 characters per message, where as 1.11 and later protocols can have messages with up to 256 characters.*

```csharp
void Chat(string message);
```

### Respawn

Attempts to respawn the bot. The task that this function returns is completed once a world reload is done.

```csharp
Task Respawn();
```

### SwapItemInHands

Swaps the item that the player is currently holding in it's primary hand to it's off-hand and vice-versa.\
Note: *this only works on 1.9+.*

```csharp
Task SwapItemInHands();
```

### UseHeld

Right clicks the currently held item.

```csharp
Task UseHeld();
```

### Swing

Performs the (left) arm swing animation. **This is only the animation and will not hit any mobs or blocks.**

```csharp
Task Swing();
```

### Eat

Attempts to "eat" (hold right click) on the selected item. **This does not check whether the player is currently holding food, that is up to the developer to do!**

```csharp
Task<bool> Eat();
```

###

### SetLook

Sets the bot's rotation to the specified value. You can optionally await for this function as the server can take a bit to update the change. The await value is always 1 tick and is here only for the convenience.

```csharp
Task SetLook(IRotation rotation);
Task SetLook(Directions direction);
```

### LookAt

Sets the bot's rotation to look at the specified position. You can optionally await for this function as the server can take a bit to update the change. The await value is always 1 tick and is here only for the convenience.

```csharp
Task LookAt(IPosition position);
Task LookAt(ILocation location);
```

### LookAtSmooth

Smoothly (slowly, per multiple ticks) sets the bot's rotation to look at the specified position. You should await for this function to complete, as the rotation time is dynamic. You can optionally specify the look speed, however it is recommended to leave it as 'auto'.

```csharp
Task LookAtSmooth(IPosition position, LookSpeed speed = LookSpeed.auto);
Task LookAtSmooth(ILocation location, LookSpeed speed = LookSpeed.auto);
```

###

### Jump

The bot attempts to jump up. This will not move the bot horizontally, only vertically.

```csharp
void Jump();
```

### MoveDirection

Attempts to move the player in the specified direction. \
You can optionally specify the [MapOptions](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Movement/Maps/MapOptions.cs), which control what the bot can and cannot do while pathing (e.g.: can't build, can't walk on sand).

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, which contains the path that was used (MoveResult.Path) and the outcome (**MoveResult.Result**).\
Note: *Path can be used by re-used with`context.player.ExecuteReusablePath`.*

```csharp
MoveDirection(Direction direction, MapOptions options = null);
```

### MoveTo

Attempts to move the player to the specified location. \
You can optionally specify the [MapOptions](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Movement/Maps/MapOptions.cs), which control what the bot can and cannot do while pathing (e.g.: can't build, can't walk on sand).

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, which contains the path that was used (MoveResult.Path) and the outcome (**MoveResult.Result**).\
Note: *Path can be used by re-used with`context.player.ExecuteReusablePath`.*

```csharp
IMoveTask MoveTo(ILocation location, MapOptions options = null);
IMoveTask MoveTo(IPosition position, MapOptions options = null);
IMoveTask MoveTo(int x, int y, int z, MapOptions options = null);

/*
* E.g. of pathing and waiting for it to finish
*/
public async Task OnTick() {
        var moveResult = await Context.Player.MoveTo(new Location(100, 40, 100)).Task;
        if(moveResult.Result == MoveResultType.Completed) 
                Console.WriteLine("Moved to 100/40/100");
        else 
                Console.WriteLine("Failed to move to 100/40/100, path was "
                                  + moveResult.Result);
}
```

###

### MoveToRange

Attempts to move the player in range to the specified (within the specified range) or to the specified location it self. The range is circular, that means that the total distance to the block must be within the specified radius.\
You can optionally specify the [MapOptions](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Movement/Maps/MapOptions.cs), which control what the bot can and cannot do while pathing (e.g.: can't build, can't walk on sand).

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, which contains the path that was used (MoveResult.Path) and the outcome (**MoveResult.Result**).\
Note: *Path can be used by re-used with`context.player.ExecuteReusablePath`.*

```csharp
IMoveTask MoveToRange(ILocation location, int range, MapOptions options = null);
IMoveTask MoveToRange(IPosition position, int range, MapOptions options = null);
IMoveTask MoveToRange(int x, int y, int z, int range, MapOptions options = null);
```

### MoveToRangeCustom

Attempts to move the player onto a block that is within a specified range of the location and  canBlockBePicked returns true for the selected block. This allows developers to customize the block that the bot will pick to stand on.\
You can optionally specify the [MapOptions](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Movement/Maps/MapOptions.cs), which control what the bot can and cannot do while pathing (e.g.: can't build, can't walk on sand).

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, which contains the path that was used (MoveResult.Path) and the outcome (**MoveResult.Result**).\
Note: *Path can be used by re-used with`context.player.ExecuteReusablePath`.*

```csharp
IMoveTask MoveToRangeCustom(ILocation location, int range, Func<IBlock, bool> canBlockBePicked, MapOptions options = null);
IMoveTask MoveToRangeCustom(IPosition position, int range, Func<IBlock, bool> canBlockBePicked, MapOptions options = null);
IMoveTask MoveToRangeCustom(int x, int y, int z, int range, Func<IBlock, bool> canBlockBePicked, MapOptions options = null);
```

### MoveToInteractionRange

Attempts to move the player onto a block that the specified location can be reached from and seen from. This means that this takes both the interaction range of the player (\~4.5 blocks) and the visibility into account when looking for a block. \
You can optionally specify the [MapOptions](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Movement/Maps/MapOptions.cs), which control what the bot can and cannot do while pathing (e.g.: can't build, can't walk on sand).

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, which contains the path that was used (MoveResult.Path) and the outcome (**MoveResult.Result**).\
Note: *Path can be used by re-used with`context.player.ExecuteReusablePath`.*

```csharp
IMoveTask MoveToInteractionRange(ILocation location, MapOptions options = null);
IMoveTask MoveToInteractionRange(IPosition position, MapOptions options = null);
IMoveTask MoveToInteractionRange(int x, int y, int z, MapOptions options = null);
```

### FollowEntity

Makes the bot follow the specified entity. You can optionally specify the maxRange and the minRange that the bot must keep to the player. If no maxRange is specified then 1 is used, meaning the bot will path to the same position as the player is in.

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, the outcome of the path (**MoveResult.Result**).\
The IMoveTask.Task is marked as completed when either the player is reached or the player dies/moves out of ranges or when a new path is specified. Therefore for constant following you should place this on a loop where if the path is done then you re-queue another follow call.

```csharp
IMoveTask FollowEntity(IEntity entity, MapOptions options = null);
IMoveTask FollowEntity(IEntity entity, int maxRange, MapOptions options = null);
IMoveTask FollowEntity(IEntity entity, int maxRange, int minRange, MapOptions options = null);
```

### CreateReusablePath

Performs a path lookup and stores it into a reusable variable, which can be used later. The result of this function can be used with **ExecuteReusablePath** to actually perform that movement of the path.\
Note: *When reusing paths, the bots must start at the same location the path was created at.*

```csharp
Task<ICachedPath> CreateReusablePath(IPosition start, IPosition end, MapOptions options = null);
Task<ICachedPath> CreateReusablePath(ILocation start, ILocation end, MapOptions options = null);
```

### ExecuteReusablePath

{% hint style="warning" %}
The bot must be standing in the same location that the path originates from otherwise the bot may not path as expected.
{% endhint %}

Attempts to re-use a path that has been calculated beforehand.

Returns **IMoveTask**, which has functions to affect the current path, such as `SetNewTarget()` and `Stop()`. IMoveTask also contains the task that will be marked completed once the path is completed/cancelled. The task can be awaited by doing `await IMoveTask.Task`and returns a **MoveResult**, which contains the path that was used (MoveResult.Path) and the outcome (**MoveResult.Result**).

```csharp
IMoveTask ExecuteReusablePath(ICachedPath path);
```

### Disconnect

Disconnects the bot from the server. You can optionally specify the disconnect message, which will be shown in the accounts tab.

```csharp
void Disconnect(string message = null);
```


# Entities

This part refers to the class [**IEntityList.cs**](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/Entity/Lists/IEntityList.cs), which can be accessed through **Context.Entities**. This should be used when getting/finding entities/mobs/other players and will generally only return those values which have not been (yet) unloaded by the server, usually meaning that they are still in the entity render distance of the server.

| Methods             | Events          |
| ------------------- | --------------- |
| GetBots             | onEntityAdded   |
| GetClosestBot       | onEntityRemoved |
| GetPlayers          | onEntityMoved   |
| GetPlayer           | onPlayerMoved   |
| GetPlayerByUuid     |                 |
| GetClosestPlayer    |                 |
| GetEntities         |                 |
| GetEntity           |                 |
| GetClosestEntity    |                 |
| GetMobs             |                 |
| GetClosestMob       |                 |
| GetObjects          |                 |
| GetItemStackObjects |                 |
| GetClosestObject    |                 |
| GetAllLoadedNames   |                 |

## Methods

### GetBots

Returns a collection of **IPlayerEntity** where each entry corresponds to a (rendered) bot's entity.\
This may not get all bot entities in cases where the other bots are outside of this bot's entity render distance.

```csharp
IEnumerable<IPlayerEntity> GetBots();
```

###

### GetClosestBot

Returns the closest other bot's entity to the given position.\
This may return null if no bots are connected/in entity render distance.

```csharp
// Gets the closest bot to the current bot's location.
IPlayerEntity GetClosestBot();
// Gets the closest (other) bot to the given position.
IPlayerEntity GetClosestBot(IPosition position);
// Gets the closest (other) bot to the given location.
IPlayerEntity GetClosestBot(ILocation position);
// Gets the closest (other) bot to the given position.
IPlayerEntity GetClosestBot(double x, double y, double z);
```

###

### GetPlayers

Returns a collection of **IPlayerEntity** where each entry corresponds to a (rendered) player on the server. This can include bot entities depending on the parameters.

```csharp
IEnumerable<IPlayerEntity> GetPlayers(bool includeBots);
```

###

### GetPlayer

Returns a single **IPlayerEntity** according to the specified parameters.

```csharp
// Gets player by its entityId, where entity id is a unique
// number assigned to an entity by the server.
IPlayerEntity GetPlayer(int entityId);
// Gets player by its (user)name, e.g.: GetPlayer("OnlyQubes");
IPlayerEntity GetPlayer(string name );
```

###

### GetPlayerByUuid

Returns a single **IPlayerEntity** according to the specified [uuid](https://mcuuid.net/).

```csharp
IPlayerEntity GetPlayerByUuid(string uuid);
```

###

### GetClosestPlayer

Returns the closest other **IPlayerEntity** to the specified position. This can include bot entities depending on the parameters.

\* optionalValidityCheck - *optional parameter, which if not null will be called with a IPlayerEntity parameter. If this functions returns true then the entity will be processed, otherwise it will not be considered for the returned collection.*

```csharp
// Gets the closest player to the current bot's location.
IPlayerEntity GetClosestPlayer(bool includeBots = false, Func<IPlayerEntity, bool> optionalValidityCheck = null);
// Gets the closest player to the given position.
IPlayerEntity GetClosestPlayer(IPosition position, bool includeBots = false, Func<IPlayerEntity, bool> optionalValidityCheck = null);
// Gets the closest player to the given location.
IPlayerEntity GetClosestPlayer(ILocation position, bool includeBots = false, Func<IPlayerEntity, bool> optionalValidityCheck = null);
// Gets the closest player to the given position.
IPlayerEntity GetClosestPlayer(double x, double y, double z, bool includeBots = false, Func<IPlayerEntity, bool> optionalValidityCheck = null);
```

{% hint style="info" %}
Example call:\
`// Gets the closest player who's name starts with "Bot".`\
`Context.Entities.GetClosestPlayer(true, playerEntity => playerEntity.GetName().StartsWith("Bot"));`
{% endhint %}

{% content-ref url="/pages/-LneI4D5Xevz1lSExDv5" %}
[IPlayerEntity](/api/context/entities/iplayerentity)
{% endcontent-ref %}

###

### GetEntities

Returns a collection of **ILiving** where each entry corresponds to a (rendered) entity, such as an animal, a monster, and optionally can include players.

```csharp
IEnumerable<ILiving> GetEntities(bool includePlayers = false);
```

###

### GetEntity

Returns a single **ILiving** according to the specified entity id.

```csharp
// Gets entity by its entityId, where entity id is a unique
// number assigned to an entity by the server.
ILiving GetEntity(int entityId);
```

###

### GetClosestEntity

Returns the closest other **ILiving** to the specified position. This can include player entities depending on the parameters.

\* optionalValidityCheck - *optional parameter, which if not null will be called with a ILiving parameter. If this functions returns true then the entity will be processed, otherwise it will not be considered for the returned collection.*

```csharp
// Gets the closest entity to the current bot's location.
ILiving GetClosestEntity(bool includePlayers = false, Func<ILiving, bool> optionalValidityCheck = null);
// Gets the closest entity to the given position.
ILiving GetClosestEntity(IPosition position, bool includePlayers = false, Func<ILiving, bool> optionalValidityCheck = null);
// Gets the closest entity to the given location.
ILiving GetClosestEntity(ILocation position, bool includePlayers = false, Func<ILiving, bool> optionalValidityCheck = null);
// Gets the closest entity to the given position.
ILiving GetClosestEntity(double x, double y, double z, bool includePlayers = false, Func<ILiving, bool> optionalValidityCheck = null);
```

###

### GetMobs

Returns a collection of **IMobEntity** where each entry corresponds to a (rendered) mob, such as an animal, or a monster. The parameters of this function allow you to specify what sort of monsters can be included in the collection (e.g.: all, aggressive, passive, zombies).

```csharp
IEnumerable<IMobEntity> GetMobs(MobType type = MobType.All)
```

###

### GetClosestMob

Returns the closest **IMobEntity** to the specified position. This can look only for specific mob types, such as aggressive (MobType.Aggressive), passive (MobType.Pasive), zombies (MobType.Zomboe).

\* optionalValidityCheck - *optional parameter, which if not null will be called with a IMobEntity parameter. If this functions returns true then the entity will be processed, otherwise it will not be considered for the returned collection.*

```csharp
// Gets the closest mob to the current bot's location.
IMobEntity GetClosestMob(MobType type = MobType.All, Func<IMobEntity, bool> optionalValidityCheck = null);
// Gets the closest mob to the given position.
IMobEntity GetClosestMob(IPosition position, MobType type = MobType.All, Func<IMobEntity, bool> optionalValidityCheck = null);
// Gets the closest mob to the given location.
IMobEntity GetClosestMob(ILocation position, MobType type = MobType.All, Func<IMobEntity, bool> optionalValidityCheck = null);
// Gets the closest mob to the given position.
IMobEntity GetClosestMob(double x, double y, double z, MobType type = MobType.All, Func<IMobEntity, bool> optionalValidityCheck = null);
```

{% content-ref url="/pages/-LneIAxrZHdOEW-X1rnz" %}
[IMobEntity](/api/context/entities/imobentity)
{% endcontent-ref %}

###

### GetObjects

Returns a collection of **IObjectEntity** where each entry corresponds to an object, which is a special type of entity that will not show up when searching the internal entity list with GetEntities(). An example of an object is a dropped stack of items on the ground or an arrow.

```csharp
// Type allows you to specify what type of objects you are looking for.
// e.g.: arrows
IEnumerable<IObjectEntity> GetObjects(ObjectTypes type = ObjectTypes.All);
```

###

### GetItemStackObjects

Returns a collection of **IObjectEntity** where each entry corresponds to an object, where each entry corresponds to a stack of items on the ground. This is a wrapper function for GetObjects().

```csharp
IEnumerable<IObjectEntity> GetItemStackObjects();
```

###

### GetClosestObject

Returns the closest **IObjectEntity** to the specified position. This can look for specific types of objects (e.g.: arrows, item stacks).

\* optionalValidityCheck - *optional parameter, which if not null will be called with a IObjectEntity parameter. If this functions returns true then the entity will be processed, otherwise it will not be considered for the returned collection.*

```csharp
// Gets the closest object to the current bot's location.
IObjectEntity GetClosestObject(ObjectTypes type = ObjectTypes.All, Func<IObjectEntity, bool> optionalValidityCheck = null);
// Gets the closest object to the given position.
IObjectEntity GetClosestObject(IPosition position, ObjectTypes type = ObjectTypes.All, Func<IObjectEntity, bool> optionalValidityCheck = null);
// Gets the closest object to the given location.
IObjectEntity GetClosestObject(ILocation position, ObjectTypes type = ObjectTypes.All, Func<IObjectEntity, bool> optionalValidityCheck = null);
// Gets the closest object to the given position.
IObjectEntity GetClosestObject(double x, double y, double z, ObjectTypes type = ObjectTypes.All, Func<IObjectEntity, bool> optionalValidityCheck = null);
```

{% content-ref url="/pages/-LneIFrFgZtUBQOoQIQj" %}
[IObjectEntity](/api/context/entities/iobjectentity)
{% endcontent-ref %}

### GetAllLoadedNames

Returns all loaded uuid to name links from the server.

```csharp
IEnumerable<UUID> GetAllLoadedNames();
```

## Events

{% hint style="info" %}
You can register a function to an event with the '+=' operator.\
E.g.: `Context.Events.OnChat += ChatMessageHandler;`
{% endhint %}

### onEntityAdded

Event that is called when any entity is added to the loaded entity list. This includes players, mobs, and other entity types.\
The add event can be cancelled by setting the EvenCancelToken to isCancelled = true, which would make it not add the entity to the bot's entity list.

```csharp
EntityDelegate onEntityAdded;
// onEntityAdded += (entity, token) => 
//                  Console.WriteLine($"Loaded entity with id {entity.entitiId}");
```

###

### onEntityRemoved

Event that is called when any entity is removed from the loaded entity list. This includes players, mobs, and other entity types.\
The add event can be cancelled by setting the EvenCancelToken to isCancelled = true, which would make it not remove the entity from the bot's entity list.

```csharp
EntityDelegate onEntityRemoved;
// onEntityRemoved += (entity, token) => 
//                    Console.WriteLine($"Unloaded entity with id {entity.entityId}");
```

###

### onEntityMoved

Event that is called when any entity moves/is moved. This includes players, mobs, and other entity types.

```csharp
EntityInformationDelegate onEntityMoved;
// onEntityMoved += (entity) =>
//                  Console.WriteLine($"Entity with id {entity.entityId} moved");
```

###

### onPlayerMoved

Event that is called when a player entity moves/is moved.

```csharp
EntityInformationDelegate onPlayerMoved;
// onPlayerMoved += (entity) =>
// Console.WriteLine($"Player with name {((IPlayerEntity)entity).GetName()} moved");
```

## Example code using Entities

The code below searches for an player entity with the name "OnlyQubes". If the player is not found then the bot does nothing, otherwise if the player is found then we move to it's location and attempt to hit the closest aggressive mob while moving.

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

```csharp
public async void OnTick() {
    // Attempt to find the player with the username "OnlyQubes",
    // if the user is not found then we return/do nothing.
    IPlayerEntity playerEntity = Context.Entities.GetPlayer("OnlyQubes");
    if(playerEntity == null) return;
    
    // Attempt to move to the "OnlyQubes" player, while
    // moving attempt (as we don't check for distance) to hit the closest
    // aggresive mob.
    var moveTask = playerEntity.MoveTo();
    while(!moveTask.complete) {
        IMobEntity mobEntity = Context.Entities.GetClosestMob(MobType.Aggressive);
        if(mobEntity != null) await mobEntity.Attack();
        else await Context.TickManager.Wait(1); // no monster found, wait 1 tick before continuing the while loop.
    }
}
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public async void OnTick() {
    IPlayerEntity playerEntity = Context.Entities.GetPlayer("OnlyQubes");
    if(playerEntity == null) return;
    
    var moveTask = playerEntity.MoveTo();
    while(!moveTask.complete) {
        IMobEntity mobEntity = Context.Entities.GetClosestMob(MobType.Aggressive);
        if(mobEntity != null) await mobEntity.Attack();
        else await Context.TickManager.Wait(1);
    }
}
```

{% endtab %}
{% endtabs %}


# IPlayerEntity

Represents an instance of a player entity. This can also include other bots.

| Methods        | Properties   |
| -------------- | ------------ |
| GetName        | EntityId     |
| GetUuid        | Position     |
| IsBot          | Rotation     |
| GetHealth      | Effects      |
| IsDead         | Equipment    |
| GetAge         | HasDespawned |
| IsCrouched     | HasMoved     |
| IsSwimming     |              |
| IsSprinting    |              |
| HasLineOfSight |              |
| Attack         |              |
| Interact       |              |
| LookAt         |              |
| LookAtSmooth   |              |
| MoveTo         |              |
| MoveToRange    |              |
| Follow         |              |

## Methods

### GetName

Returns the name of this player.

```csharp
string GetName();
```

###

### GetUuid

Returns the uuid of this player. You can use <https://mcuuid.net/> to convert a username to an uuid manually. The returned value is in the format of \`91a546fca6fe44c99550ab2291f28760\` (does not have dashes).

```csharp
string GetUuid();
```

###

### IsBot

Returns true if the given player is a bot, otherwise returns false. This function will only return accurate results if the bots are from your personal OQ.MineBot client (You will not be able to detect other people's bots).

```csharp
bool IsBot();
```

###

### GetHealth

Returns the health of this player.\
Note: the Health is measured 0 (aka dead) up to 20 (full health), not up to 10 like Minecraft's visual indicators.

```csharp
float GetHealth();
```

###

### IsDead

Returns whether this player is dead.

```csharp
bool IsDead();
```

###

### GetAge

Returns the number of ticks that this player has existed for. This starts counting up as soon as this player is sent to the bot by the server (time since render). Each tick in this case refers to a Minecraft tick, which is 50ms per tick.

```csharp
int GetAge();
```

###

### IsCrouched

Returns whether this player is crouched or not.

```csharp
bool IsCrouched();
```

###

### IsSwimming

Returns whether this player is swimming or not. **This only works on 1.13 and above** and is used by the vanilla client to render to player the swimming animation.

```csharp
bool IsSwimming();
```

###

### IsSprinting

Returns whether this player is sprinting or not.

```csharp
bool IsSprinting();
```

###

### HasLineOfSight

Returns whether the bot has direct line of sight to this player. This **only works if the player is within 64 blocks of the bot**. You can optionally specify a specific body part to test against (default is BodyParts.Body).

```csharp
bool HasLineOfSight(BodyParts bodyPart = BodyParts.Body);
```

###

### Attack

Attacks this player. This does not move the bot to range, nor does it rotate the bots head to face the player.\
Note: *To be anti-cheat compliant, you must first use the LookAt function to look at the player before hitting it.*

```csharp
void Attack();
void Attack(Hands hand);
```

### Interact

Right-clicks this player. This does not move the bot to range, nor does it rotate the bots head to face the player.\
Note: *To be anti-cheat compliant, you must first use the LookAt function to look at the player before hitting it.*

```csharp
void Interact();
void Interact(Hands hand);
```

###

### LookAt

Rotates the bots head to look at the player. This can be used to look at a specific part of the player, such as the head, feet, or the body (default is BodyParts.Body).\
Returns a Task that lasts around 1 tick, which is how long it takes the server to update the players rotation.

```csharp
Task LookAt(BodyParts bodyPart = BodyParts.Body);
```

### LookAtSmooth

Smoothly (slowly, per multiple ticks) rotates the bots head to look at the player. This can be used to look at a specific part of the player, such as the head, feet, or the body (default is BodyParts.Body).\
You should await for this function to complete, as the rotation time is dynamic. You can optionally specify the look speed, however it is recommended to leave it as 'auto'.

```csharp
Task LookAtSmooth(BodyParts bodyPart = BodyParts.Body, LookSpeed speed = LookSpeed.auto);
```

###

### MoveTo

Attempts to move the location of this player. This is a wrapper function for [Player.MoveTo](https://docs.minecraftbot.com/api/context/player#moveto), for more information check that.

```csharp
IMoveTask MoveTo();
```

### MoveToRange

Attempts to move the bot into the specified range of this player. You must specify the max distance that we can be from this player to still be considered in range. This is a wrapper function for [Player.MoveToRange](https://docs.minecraftbot.com/api/context/player#movetorange), for more information check that.

```csharp
IMoveTask MoveToRange(int maxRange, MapOptions options = null);
```

### Follow

Attempts to move the location of this player, if the player moves then the path is recalculated and updated. This is a wrapper function for [Player.FollowEntity](https://docs.minecraftbot.com/api/context/player#followentity), for more information check that.

```csharp
IMoveTask Follow(MapOptions options = null)
IMoveTask Follow(int maxRange, MapOptions options = null)
IMoveTask Follow(int maxRange, int minRange, MapOptions options = null)
```


# IMobEntity

Represents an instance of a mob. This includes friendly mobs (e.g.: sheep, cow) and aggressive mobs (e.g.: zombie, skeleton).

| Methods        | Properties   |
| -------------- | ------------ |
| IsPassive      | MobType      |
| GetHealth      | EntityId     |
| IsDead         | Position     |
| GetAge         | Rotation     |
| HasLineOfSight | Effects      |
| Attack         | Equipment    |
| Interact       | HasDespawned |
| LookAt         | HasMoved     |
| LookAtSmooth   |              |
| MoveTo         |              |
| MoveToRange    |              |
| Follow         |              |

## Methods

### GetHealth

Returns the health of this mob.\
Note: *the Health is measured 0 (aka dead) up to 20 (full health), not up to 10 like Minecraft's visual indicators.*

```csharp
float GetHealth();
```

###

### IsDead

Returns whether this mob is dead.

```csharp
bool IsDead();
```

###

### GetAge

Returns the number of ticks that this mob has existed for. This starts counting up as soon as this mob is sent to the bot by the server (time since render). Each tick in this case refers to a Minecraft tick, which is 50ms per tick.

```csharp
int GetAge();
```

###

### HasLineOfSight

Returns whether the bot has direct line of sight to this mob. This **only works if the mob is within 64 blocks of the bot**. You can optionally specify a specific body part to test against (default is BodyParts.Body).

```csharp
bool HasLineOfSight(BodyParts bodyPart = BodyParts.Body);
```

###

### Attack

Attacks this mob. This does not move the bot to range, nor does it rotate the bots head to face the mob.\
Note: *to be anti-cheat compliant, you must first use the LookAt function to look at the mob before hitting it.*

```csharp
void Attack();
void Attack(Hands hand);
```

### Interact

Right-clicks this mob. This does not move the bot to range, nor does it rotate the bots head to face the mob.\
Note: *To be anti-cheat compliant, you must first use the LookAt function to look at the mob before hitting it.*

```csharp
void Interact();
void Interact(Hands hand);
```

###

### LookAt

Rotates the bots head to look at the mob. This can be used to look at a specific part of the mob, such as the head, feet, or the body (default is BodyParts.Body).\
Returns a Task that lasts around 1 tick, which is how long it takes the server to update the players rotation.

```csharp
Task LookAt(BodyParts bodyPart = BodyParts.Body);
```

###

### LookAtSmooth

Smoothly (slowly, per multiple ticks) rotates the bots head to look at the mob. This can be used to look at a specific part of the mob, such as the head, feet, or the body (default is BodyParts.Body).\
You should await for this function to complete, as the rotation time is dynamic. You can optionally specify the look speed, however it is recommended to leave it as 'auto'.

```csharp
Task LookAtSmooth(BodyParts bodyPart = BodyParts.Body, LookSpeed speed = LookSpeed.auto
```

### MoveTo

Attempts to move the location of this player. This is a wrapper function for [Player.MoveTo](https://docs.minecraftbot.com/api/context/player#moveto), for more information check that.

```csharp
IMoveTask MoveTo();
```

### MoveToRange

Attempts to move the bot into the specified range of this player. You must specify the max distance that we can be from this player to still be considered in range. This is a wrapper function for [Player.MoveToRange](https://docs.minecraftbot.com/api/context/player#movetorange), for more information check that.

```csharp
IMoveTask MoveToRange(int maxRange, MapOptions options = null);
```

### Follow

Attempts to move the location of this mob, if the mob moves then the path is recalculated and updated. This is a wrapper function for [Player.FollowEntity](https://docs.minecraftbot.com/api/context/player#followentity), for more information check that.

```csharp
IMoveTask Follow(MapOptions options = null)
IMoveTask Follow(int maxRange, MapOptions options = null)
IMoveTask Follow(int maxRange, int minRange, MapOptions options = null)
```


# IObjectEntity

Represents an instance of a world object. This includes entites such as dropped item stacks, falling sand, etc.

| Methods        | Properties   |
| -------------- | ------------ |
| GetAge         | Type         |
| HasLineOfSight | Object       |
| LookAt         | EntityId     |
| LookAtSmooth   | Position     |
| MoveTo         | HasDespawned |
| MoveToRange    |              |
| Follow         |              |

## Properties

### Type

Denotes the type of this object, e.g.: ItemStack, Boat, Minecart. The full list of types can be found in [OQ.MineBot.PluginBase.Classes.Entity.Objects.ObjectTypes](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/Entity/Objects/IWorldObjects.cs).

###

### *Object (legacy)*

This variable should be casted to a more specific type by checking the Type variable and casting based on that. A full list of types that this can be casted to can be found [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Classes/Entity/Objects/List). This will expose more relevant variables to the object, such as ProjectileObject has the entityId of the entity that shot it.

```csharp
// Example: casting based on Type
if(theObject.Type == ObjectTypes.Snowball)
    Console.WriteLine($"Entity with id {((ProjectileObject)theObject).shooterId} threw a snowball.");
```

## Methods

### GetAge

Returns the number of ticks that this object has existed for. This starts counting up as soon as this object is sent to the bot by the server (time since render). Each tick in this case refers to a Minecraft tick, which is 50ms per tick.

```csharp
int GetAge();
```

###

### HasLineOfSight

Returns whether the bot has direct line of sight to this object. This **only works if the object is within 64 blocks of the bot**. You can optionally specify a specific body part to test against (default is BodyParts.Body).

```csharp
bool HasLineOfSight(BodyParts bodyPart = BodyParts.Body);
```

###

### LookAt

Rotates the bots head to look at the object. This can be used to look at a specific part of the object, such as the head, feet, or the body (default is BodyParts.Body).\
Returns a Task that lasts around 1 tick, which is how long it takes the server to update the players rotation.

```csharp
Task LookAt(BodyParts bodyPart = BodyParts.Body);
```

### LookAtSmooth

Smoothly (slowly, per multiple ticks) rotates the bots head to look at the object. This can be used to look at a specific part of the object, such as the head, feet, or the body (default is BodyParts.Body).\
You should await for this function to complete, as the rotation time is dynamic. You can optionally specify the look speed, however it is recommended to leave it as 'auto'.

```csharp
Task LookAtSmooth(BodyParts bodyPart = BodyParts.Body, LookSpeed speed = LookSpeed.auto
```

###

### MoveTo

Attempts to move the location of this player. This is a wrapper function for [Player.MoveTo](https://docs.minecraftbot.com/api/context/player#moveto), for more information check that.

```csharp
IMoveTask MoveTo();
```

### MoveToRange

Attempts to move the bot into the specified range of this player. You must specify the max distance that we can be from this player to still be considered in range. This is a wrapper function for [Player.MoveToRange](https://docs.minecraftbot.com/api/context/player#movetorange), for more information check that.

```csharp
IMoveTask MoveToRange(int maxRange, MapOptions options = null);
```

### Follow

Attempts to move the location of this object, if the object is moved then the path is recalculated and updated. This is a wrapper function for [Player.FollowEntity](https://docs.minecraftbot.com/api/context/player#followentity), for more information check that.

```csharp
IMoveTask Follow(MapOptions options = null)
IMoveTask Follow(int maxRange, MapOptions options = null)
IMoveTask Follow(int maxRange, int minRange, MapOptions options = null)
```


# World

This part refers to the class [**IWorld.cs**](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/World/IWorld.cs), which can be accessed through **Context.World**. This will allow you to get and interact with blocks. The [IBlock](https://docs.minecraftbot.com/api/context/world/iblock) class is heavily integrated into this class and will further allow you to interact with the world.

| Methods                  |
| ------------------------ |
| GetBlock                 |
| GetBlocks                |
| GetBlockId               |
| GetBlockMetadata         |
| GetBlockEntityData       |
| GetLookingAt             |
| GetPathableLocationsFrom |
| PlaceAt                  |
| PlaceOn                  |
| Dig                      |
| FindFrom                 |
| FindClosestTo            |
| Find                     |
| FindClosest              |

## Methods

### GetBlock

Returns an **IBlock** which is an instance of a block at the given position. This is the most important function of the world class, as the IBlock class allows you to interact with the block, such as hit it, use it, break it, etc.

{% content-ref url="/pages/-LnlY8A\_4kC6mN8r4x8u" %}
[IBlock](/api/context/world/iblock)
{% endcontent-ref %}

```csharp
IBlock GetBlock(ILocation location);
IBlock GetBlock(IPosition position);
IBlock GetBlock(int x, int y, int z);
```

###

### GetBlocks

Returns a list of IBlock, where each entry corresponds to a block from the given location list.

{% content-ref url="/pages/-LnlY8A\_4kC6mN8r4x8u" %}
[IBlock](/api/context/world/iblock)
{% endcontent-ref %}

```csharp
IEnumerable<IBlock> GetBlocks(IEnumerable<ILocation> locations);
```

###

### GetBlockRaw

Returns the raw data of a block (how Minecraft sends it between server and client). The value contains both the ID of the block and the metadata. Each value can be extracted by doing `data >> 4` (ID) and  `data & 15` (metadata).

*This should be mainly used for performance critical operations, as it does not create any new objects and has both the id and metadata in a single location lookup.*

```csharp
ushort GetBlockRaw(ILocation location);
```

###

### GetBlockId

Returns the ID of a block at the given position.\
Reference <https://minecraft-ids.grahamedgecombe.com/>

```csharp
ushort GetBlockId(ILocation location);
ushort GetBlockId(IPosition position);
ushort GetBlockId(int x, int y, int z);
```

###

### GetBlockMetadata

Returns the metadata of a block at the given position.

```csharp
byte GetBlockMetadata(ILocation location);
byte GetBlockMetadata(IPosition position);
byte GetBlockMetadata(int x, int y, int z);
```

### GetBlockEntityData

Returns block entity data (e.g.: sign text) for blocks that have it, otherwise null is returned. The returned type is IBlockEntity data which by it self has a Type property, which further specifies the entity data type (e.g.: sign).\
A full list of BlockEntity types can be found [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Classes/Blocks/BlockEntities).

```csharp
IBlockEntity GetBlockEntityData(ILocation location);
IBlockEntity GetBlockEntityData(IPosition position);
IBlockEntity GetBlockEntityData(int x, int y, int z);
// the result is a generic type which can then be converted like this:
// if(blockEntityData.Type == BlockEntityType.Sign) {
//     var convertedData = (SignBlockEntity)blockEntityData;
//     var signText = convertedData.GetContinuousText();
// }
```

### GetLookingAt

Returns the block that the bot is looking at.\
This may return Null if there is no block in front of the bot, or it is out of interaction range (around 5 blocks).

{% content-ref url="/pages/-LnlY8A\_4kC6mN8r4x8u" %}
[IBlock](/api/context/world/iblock)
{% endcontent-ref %}

```csharp
IBlock GetLookingAt(); 
```

###

### GetPathableLocationsFrom

Returns an array of **ILocation**. The first block is always the specified location. The range specifies how far away a block can be from the location in order to be considered. The area considered is circular.\
This task can take a long time, depending on the range, therefore it is a Task that should be awaited for.\
*\* MapOptions - specifies the pathing options to considered (e.g.: max fall distance). If left null it will use the bots default MapOptions.*

```csharp
// If no location is specified it will use the bot's location.
Task<ILocation[]> GetPathableBlocksFrom(uint range, MapOptions mapOptions = null);
Task<ILocation[]> GetPathableBlocksFrom(ILocation location, uint range, MapOptions mapOptions = null);
Task<ILocation[]> GetPathableBlocksFrom(IPosition position, uint range, MapOptions mapOptions = null);
Task<ILocation[]> GetPathableBlocksFrom(int x, int y, int z, uint range, MapOptions mapOptions = null);
```

###

### PlaceAt

Attempts to place a block that the bot is currently holding (does not validate if the bot is holding a block, that is up to the developer) at the given location. This is done by getting the nearby block faces and checking whether we can place on them. **This does consider the visibility of faces**. If no visible face is found then false is returned, otherwise true.\
Note: *this does not check whether the server cancelled the block placement (removed the placed block), nor does this function move the player to the range of the block (that is up to developer to do).*

```csharp
Task<bool> PlaceAt(ILocation location);
Task<bool> PlaceAt(IPosition position);
Task<bool> PlaceAt(int x, int y, int z);
```

###

### PlaceOn

Attempts to place a block that the bot is currently holding by right clicking a block in the specified location on the specified face (side). The visibility of a face is not verified.\
Note: *this function does not move the player to the range of the block (that is up to developer to do).*

| Face Value | Face Representation |
| ---------- | ------------------- |
| 0          | Bottom (-Y)         |
| 1          | Top (+Y)            |
| 2          | North (-Z)          |
| 3          | South (+Z)          |
| 4          | West (-X)           |
| 5          | East (+X)           |

```csharp
Task PlaceOn(FaceData faceData);
Task PlaceOn(ILocation location,  sbyte face);
Task PlaceOn(IPosition position,  sbyte face);
Task PlaceOn(int x, int y, int z, sbyte face);
```

###

### Dig

Attempts to break the block at the given location. You can optionally specify the face (side) that will be used to dig the block. This does rotate the bots head to the appropriate block's face.\
If no face data is specified and no visible face is found then it will default to breaking the block using the Top (+Y) face.

The function returns `Task<IDigAction>` which completes once the block is broken or instantly if the dig action was invalid (e.g.: attempting to break bedrock). The variables `cancelled` and/or `completed` can be used to determine the dig actions outcome.

```csharp
Task<IDigAction> Dig(FaceData faceData);
Task<IDigAction> Dig(ILocation location, sbyte face);
Task<IDigAction> Dig(ILocation location);
Task<IDigAction> Dig(IPosition position);
Task<IDigAction> Dig(int x, int y, int z);
```

###

### FindFrom

Scans the world for a block with the given id(s). If a block with the specified id(s) is found then optionalIsPickable is called, where the developer can define custom block criteria. The scanned area starts from the specified location and spans the width in all directions (east, west, north, south) and the height in both direction (up, down).\
Note: *As scanning the world can take a long time (depending on the width/height) the function is limited to X ms per tick, where cpuMode determines how long the function can be on the cpu for. `CpuMode.High_Usage` will usually max out the users cpu, but will scan the area the fastest, whereas `CpuMode.Low_Usage` will take the longest but will use less cpu per tick.*

```csharp
Task<IBlock[]> FindFrom(ILocation location, int width, int height, ushort id, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
Task<IBlock[]> FindFrom(ILocation location, int width, int height, ushort[] ids, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
```

###

### Find

Wrapper function for **FindFrom** where FindFrom gets called with the location of the bot.

```csharp
Task<IBlock[]> Find(int width, int height, ushort id, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
Task<IBlock[]> Find(int width, int height, ushort[] ids, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
```

###

### FindClosestTo

**Scans the world for the first occurrence** of a block that matches the specified Id(s) and optionally if optionalIsPickable returns true. The scanned area starts from the specified location and spans the width in all directions (east, west, north, south) and the height in both direction (up, down).\
Note: *As scanning the world can take a long time (depending on the width/height) the function is limited to X ms per tick, where cpuMode determines how long the function can be on the cpu for. `CpuMode.High_Usage` will usually max out the users cpu, but will scan the area the fastest, whereas `CpuMode.Low_Usage` will take the longest but will use less cpu per tick.*

```csharp
Task<IBlock> FindClosestTo(ILocation location, int width, int height, ushort id, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
Task<IBlock> FindClosestTo(ILocation location, int width, int height, ushort[] ids, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
```

###

### FindClosest

Wrapper function for **FindClosestTo** where FindClosestTo gets called with the location of the bot.

```csharp
Task<IBlock> FindClosest(int width, int height, ushort id, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
Task<IBlock> FindClosest(int width, int height, ushort[] ids, CpuMode cpuMode, Func<IBlock, bool> optionalIsPickable = null);
```

## Example code using World

The code below searches for the closest torch block within a close range to the bot (10x10x4 area). If no block is found with the id 50 (torch), then the bot does nothing, otherwise it will break the block.

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

```csharp
public async void OnTick() {
    IBlock closestBlock = await Context.World.FindClosest(5, // width of search
                                                          2, // height of search
                                                          50); // id of the block we are searching for, 50 stands for torch.
    if(closestBlock != null) {
        // closestBlock variable is not null, that means that 
        // we found a torch block nearby.
        Console.WriteLine($"Found torch at {closestBlock.GetLocation()}, breaking it");
        // Attempt to dig the block. We use await to wait for the dig
        // task to complete, as we don't want the next tick to execute
        // until we have broken the block, otherwise the bot could try
        // to mine two blocks at once or the same block multiple times.
        await closestBlock.Dig();
    }
}
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public async void OnTick() {
    IBlock closestBlock = await Context.World.FindClosest(5, 2, 50);
    
    if(closestBlock != null) {
        Console.WriteLine($"Found torch at {closestBlock.GetLocation()}, breaking it");
        await closestBlock.Dig();
    }
}
```

{% endtab %}
{% endtabs %}


# IBlock

Represents a block in the world. This can be used to interact with the block (e.g.: dig, use) or block location (e.g.: place at).

| Methods                |
| ---------------------- |
| GetId                  |
| GetMetadata            |
| GetLocation            |
| GetBlockEntityData     |
| MoveTo                 |
| MoveToRange            |
| MoveToInteractionRange |
| IsBotStandingOn        |
| IsEntityStandingOn     |
| IsInteractiveRange     |
| GetVisibleFaces        |
| GetVisibleFacesFrom    |
| GetPlaceableFaces      |
| IsInvisible            |
| IsInvisibleFrom        |
| IsSafeToMine           |
| IsBlockDangerous       |
| IsSolid                |
| IsLiquid               |
| IsMineable             |
| IsAir                  |
| IsTransparent          |
| IsUndesirableForPath   |
| Use                    |
| Dig                    |
| Hit                    |
| LookAt                 |
| LookAtSmooth           |
| PlaceOn                |
| PlaceAt                |

## Methods

### GetId

Returns the Minecraft Block ID of the block.\
References: <https://minecraft-ids.grahamedgecombe.com/>

```csharp
ushort GetId();
```

### GetMetadata

Returns the Metadata of the block as a byte (0-255).

```csharp
byte GetMetadata();
```

### GetLocation

Returns the location of the block.

```csharp
ILocation GetLocation();
```

### GetBlockEntityData

Returns block entity data (e.g.: sign text) for blocks that have it, otherwise null is returned. The returned type is IBlockEntity data which by it self has a Type property, which further specifies the entity data type (e.g.: sign).\
A full list of BlockEntity types can be found [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/tree/master/Classes/Blocks/BlockEntities).

```csharp
IBlockEntity GetBlockEntityData();
// the result is a generic type which can then be converted like this:
// if(blockEntityData.Type == BlockEntityType.Sign) {
//     var convertedData = (SignBlockEntity)blockEntityData;
//     var signText = convertedData.GetContinuousText();
// }
```

### MoveTo

Attempts to move the bot onto this block. This is a wrapper function for [Player.MoveTo](https://docs.minecraftbot.com/api/context/player#moveto), for more information check that.

```csharp
IMoveTask MoveTo(MapOptions options = null);
```

### MoveToRange

Attempts to move the bot into the specified range of this block. You must specify the max distance that we can be from this block to still be considered in range. This is a wrapper function for [Player.MoveToRange](https://docs.minecraftbot.com/api/context/player#movetorange), for more information check that.

```csharp
IMoveTask MoveToRange(int maxRange, MapOptions options = null);
```

### MoveToInteractionRange

Attempts to move the bot to a location that it can interact with this block from. The function considers the visibility and bot's reach. This is a wrapper function for [Player.MoveToInteractionRange](https://docs.minecraftbot.com/api/context/player#movetointeractionrange), for more information check that.

```csharp
IMoveTask MoveToInteractionRange(MapOptions options = null);
```

### IsBotStandingOn

Returns true if this bot is standing on the given block, otherwise false.

```csharp
bool IsBotStandingOn();
```

### IsEntityStandingOn

Returns true if there is an entity that is standing on the block, otherwise false. If the output is true then the out parameter entities will contain a list of entities that are on the block.\
Note: *this does not include this bot's entity.*

```csharp
bool IsEntityStandingOn(out IEntity[] entities);
```

### IsInInteractionRange

Returns True if the block is within the interaction range (around 5 blocks) of the bot, otherwise false.

```csharp
bool IsInInteractionRange();
```

### GetVisibleFaces

Returns the faces (sides) that the bot can see from the current location of this block. This will be at most 3 faces.&#x20;

```csharp
FaceData[] GetVisibleFaces();
```

### GetVisibleFacesFrom

Returns the faces (sides) of this block that the bot could see from the given eye position. Eye position for the player is `feetPosition + 1.65`. This will be at most 3 faces.

```csharp
FaceData[] GetVisibleFacesFrom(IPosition eyePosition);
```

### GetPlaceableFaces

Returns the faces of this block that can be placed on (i.e.: don't have a block already attached to it).

```csharp
FaceData[] GetPlaceableFaces();
```

### IsVisibleFrom

Returns true if the bot would have direct line-of-sight to this block at a given eye position, otherwise false. Eye position for the player is `feetPosition + 1.65`.

```csharp
bool IsVisibleFrom(IPosition eyePosition);
```

### IsVisible

Wrapper function for **IsVisibleFrom** where IsVisibleFrom gets called with the bot's current eye position.

```csharp
bool IsVisible();
```

### IsSafeToMine

Returns true if mining this block would harm us in any way, otherwise false. By default this only considers the current bot instance, however the parameter regardOtherBots can enable checks for other bots safety as well.\
Note: *This accounts for things such as lava flowing into us, sand falling ontop of us, us falling down a cave, and almost any scenario where it would harm us.*

```csharp
bool IsSafeToMine(bool regardOtherBots = false);
```

### IsBlockDangerous

Returns true if the block will damage the player if we are near it or stand on it, otherwise false.\
Note: *Examples include Lava, Cactus, Magma Block, etc.*

```csharp
bool IsBlockDangerous();
```

### IsSolid

Returns true if the block is solid, otherwise false.\
Note: *Examples include stone, dirt, wooden planks, etc.*

```csharp
bool IsSolid();
```

### IsLiquid

Returns true if the block is a liquid (water or lava), otherwise false.

```csharp
bool IsLiquid();
```

### IsMineable

Returns true if the block is mineable, otherwise false.\
Note: *This does not account for tool inequality such as mining obsidian with iron pickaxes, this is just for if the block will ever be mineable such as mining water, bedrock, void, etc.*

```csharp
bool IsMineable();
```

### IsAir

Returns true if the block is an Air block (empty), otherwise false.

```csharp
bool IsAir();
```

### IsTransparent

Returns true if the block is transparent, otherwise false.\
Note: *Examples include torches, rails, signs, pressure plates, etc.*

```csharp
bool IsTransparent();
```

### IsUndesireableForPath

Returns true if there are any objects in the path that can slow the bot down, harm it, or get it stuck.\
Note: *This includes things like slime blocks, mob heads, lava, fences, etc.*

```csharp
bool IsUndesirableForPath();
```

### Use

Right clicks on the given block. This will consider visibility of the faces (sides) and will rotate the bots head to face the correct face (side), however it will not move the bot to the block (that is up to the developer to do).

```csharp
Task Use();
```

### Dig

Attempts to break this block. You can optionally specify the face (side) that will be used to dig the block. This does rotate the bots head to the appropriate block's face.\
If no face data is specified and no visible face is found then it will default to breaking the block using the Top (+Y) face.

The function returns `Task<IDigAction>` which completes once the block is broken or instantly if the dig action was invalid (e.g.: attempting to break bedrock). The variables `cancelled` and/or `completed` can be used to determine the dig actions outcome.

```csharp
Task<IDigAction> Dig();
Task<IDigAction> Dig(sbyte face);
Task<IDigAction> Dig(FaceData faceData);
```

### Hit

Hits (left clicks) the given block. This will consider visibility of the faces (sides) and will rotate the bots head to face the correct face (side), however it will not move the bot to the block (that is up to the developer to do).

```csharp
Task Hit();
```

### LookAt

Looks at the given block. If no parameter is provided then the bot will look at the center of the block, however optionally you can specify the face (side) of the block to look at.\
Note: *you can find a list of the faces and their corresponding information* [*here*](https://docs.minecraftbot.com/api/context/world#placeon)*.*

```csharp
Task LookAt(FaceData faceData = null);
Task LookAt(sbyte face);
```

### LookAtSmooth

Smoothly (slowly, per multiple ticks) looks at the given block. If no parameter is provided then the bot will look at the center of the block, however optionally you can specify the face (side) of the block to look at. You should await for this function to complete, as the rotation time is dynamic. You can optionally specify the look speed, however it is recommended to leave it as 'auto'.

```csharp
Task LookAtSmooth(FaceData faceData = null, LookSpeed speed = LookSpeed.auto);
Task LookAtSmooth(sbyte face, LookSpeed speed = LookSpeed.auto);
```

### PlaceAt

Attempts to place a block that the bot is currently holding (does not validate if the bot is holding a block, that is up to the developer) at this location. This is done by getting the nearby block faces and checking whether we can place on them. **This does consider the visibility of faces**. If no visible face is found then false is returned, otherwise true.\
Note: *this does not check whether the server cancelled the block placement (removed the placed block), nor does this function move the player to the range of the block (that is up to developer to do).*

```csharp
Task<bool> PlaceAt();
```

### PlaceOn

Attempts to place a block that the bot is currently holding by right clicking on this block's specified face (side). The visibility of a face is not verified.\
Note: *this function does not move the player to the range of the block (that is up to developer to do).*\
*You can find a list of the faces and their corresponding information* [*here*](https://docs.minecraftbot.com/api/context/world#placeon)*.*

```csharp
Task PlaceOn(FaceData faceData);
Task PlaceOn(sbyte face);
```


# Containers

| Methods          | Events          |
| ---------------- | --------------- |
| GetInventory     | onWindowAdded   |
| GetOpenWindow    | onWindowRemoved |
| CloseWindows     |                 |
| GetWindow        |                 |
| GetWindowByTitle |                 |
| GetWindowByType  |                 |

## Methods

### GetInventory

Returns the Inventory of the bot.\
Note: *IInventory extends from IWindow, which should be used as documentation when working with the inventory.*

```csharp
IInventory GetInventory();
```

### GetOpenWindow

Gets the currently open window.\
Note: *This can return null if no window is open.*

```csharp
IWindow GetOpenWindow();
```

### CloseWindows

Closes the currently open window, if no window is open then it will send an inventory close packet, however the server does not normally keep track if the inventory is open.

```csharp
Task CloseWindows();
```

### GetWindow

Gets the window by ID.\
Note: *the bot's inventory always has the id 0, therefore if the parameter id is 0 then the bot's inventory will be returned.*

```csharp
IWindow GetWindow(int id);
```

### GetWindowByTitle

Gets the window by title of the container.\
Note: the title must be unformatted/raw text, meaning it does not contain any color codes, or any text effects such as bold, or strikethrough.

```csharp
IWindow GetWindowByTitle(string title);
```

### GetWindowByType

Gets the window by type of container. The type of the window always starts with "minecraft:" and a list of container types can be found [here](https://i.imgur.com/LeWMMFd.png).

```csharp
IWindow GetWindowByType (string type);
```

## Example code using Containers

The code below searches the bot's inventory for slots that have diamonds in them and then drops the slots that were found if they have less than 64 diamonds.

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

```csharp
public async void OnTick() {
    // Find all slots that have diamonds (id 264) in them.
    var diamondSlots = Context.Containers.GetInventory().Find(264);
    
    // Loop through each slot that has a diamond in it.
    foreach (var diamondSlot in diamondSlots) {
        // Check if the amount of diamonds in the current slot is
        // less than 64. If it is less than 64, then we drop the item stack.
        if(diamondSlot.Count < 64)
            await diamondSlot.DropStack();
    }
}
```

{% endtab %}

{% tab title="Raw Code" %}

```csharp
public async void OnTick() {
    var diamondSlots = Context.Containers.GetInventory().Find(264);
    
    foreach (var diamondSlot in diamondSlots) {
        if(diamondSlot.Count < 64)
            await diamondSlot.DropStack();
    }
}
```

{% endtab %}
{% endtabs %}


# IWindow

Represents an instance of a (usually currently open) window/container. This includes double chests, single chests, bot's inventory, etc.

| Methods             | Events        |
| ------------------- | ------------- |
| GetId               | onSlotChanged |
| GetWindowType       | onSlotDropped |
| GetWindowName       |               |
| GetAt               |               |
| GetSlots            |               |
| IsOpen              |               |
| Close               |               |
| GetSlotCount        |               |
| Find                |               |
| FindFirst           |               |
| FindByMetadata      |               |
| FindFirstByMetadata |               |
| FindByType          |               |
| FindBest            |               |
| HasFreeSlots        |               |
| GetFreeSlots        |               |
| GetFreeSlot         |               |
| IsEmpty             |               |
| IsFull              |               |
| GetAmountOfItem     |               |
| MouseLeftClick      |               |
| MouseRightClick     |               |
| MouseShiftLeftClick |               |
| MouseMiddleClick    |               |
| ClickHotbarShortcut |               |
| Take                |               |
| Deposit             |               |

## Methods

### GetId

Gets the unique ID of the current container sent by the server.

```csharp
int GetId();
```

### GetWindowType

Returns the type of the current window. The type of the window always starts with "minecraft:" and a list of container types can be found [here](https://i.imgur.com/LeWMMFd.png).

```csharp
string GetWindowType();
```

### GetWindowName

Returns the title of the current window. This can contain color codes and text effects (e.g.: bold) and therefore IChat is returned. Use `window.GetWindowName().GetText()` to get the title of the window stripped of color codes and text effects.

```csharp
IChat GetWindowName();
```

### GetAt

Returns the slot at a given index of this window.\
The returned ISlot allows you to further interact with the slot (e.g.: drop it, select it, move it).\
Note: *Containers start from index 0 at the top left. EquipmentSlots parameters can only be used on the IInventory container or IPlayerEquipmentSlots.*

{% content-ref url="/pages/-Lo\_wJnh97hZqgCbjNvf" %}
[ISlot](/api/context/containers/islot)
{% endcontent-ref %}

```csharp
ISlot GetAt(int index);
ISlot GetAt(EquipmentSlots equipmentSlot);
```

### GetSlots

Returns either all slots for this window if includeEmpty parameter is true, otherwise it will only returns the slots that have an item in them.\
The returned ISlots allow you to further interact with the slots (e.g.: drop them, move them).

{% content-ref url="/pages/-Lo\_wJnh97hZqgCbjNvf" %}
[ISlot](/api/context/containers/islot)
{% endcontent-ref %}

```csharp
ISlot[] GetSlots(bool includeEmpty = false);
```

### IsOpen

Returns whether this window is currently open.

```csharp
bool IsOpen();
```

### Close

Attempts to close the current container.

```csharp
Task Close();
```

### Find

Returns all slot instances which match the given parameters. The parameter allow to both search based on IDs and Metadata, however metadata is optional.\
Note: *Minecraft Block ID's can be found at* [*https://minecraft-ids.grahamedgecombe.com/*](https://minecraft-ids.grahamedgecombe.com/)

```csharp
ISlot[] Find(ushort id);
ISlot[] Find(ushort[] ids);
ISlot[] Find(ushort id, short metadata);
ISlot[] Find(ushort[] ids, short[] metadata);
```

### FindFirst

Returns the **first** slot instance which matches the given parameters. The parameter allow to both search based on IDs and Metadata, however metadata is optional.\
Note: *Minecraft Block ID's can be found at* [*https://minecraft-ids.grahamedgecombe.com/*](https://minecraft-ids.grahamedgecombe.com/) .\
If the window is the bot's inventory then search will start from the hotbar, whereas all other window searches start from the top left.

```csharp
ISlot FindFirst(ushort id);
ISlot FindFirst(ushort[] ids);
ISlot FindFirst(ushort id, short metadata);
ISlot FindFirst(ushort[] ids, short[] metadata);
```

### FindByMetadata

Returns all slot instances which match the given Metadata parameter.

```csharp
    ISlot[] FindByMetadata(short metadata);
```

### FindFirstByMetaData

Returns the **first** slot instance which match the given Metadata parameter.\
Note: *if the window is the bot's inventory then search will start from the hotbar, whereas all other window searches start from the top left.*

```csharp
ISlot FindFirstByMetadata(short metadata);
```

### FindByType

Finds all slot instances of a given type such as finding all kinds of helmets (diamond, iron, leather, etc) or all kinds of tools (diamond shovel, iron shovel, etc.)\
You can find the EquipmentType enum [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/Window/IWindow.cs).

```csharp
ISlot[] FindByType(EquipmentType type);
```

### FindBest

Finds the best tier item of the specified type and returns it's slot. This will look at the material of the item (e.g.: diamond vs iron) and will consider if the item has enchantments, however it will not look at the type of the enchantments.\
You can find the EquipmentType enum [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/Window/IWindow.cs).\
You can find the EquipmentSlots enum [here](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/Classes/Window/Containers/Subcontainers/IPlayerEquipmentSlots.cs).

```csharp
ISlot FindBest(EquipmentType type);
ISlot FindBest(EquipmentSlots slot);
```

### HasFreeSlots

Returns whether the window has any free (non-occupied) slots.\
Note: *you can also optionally specify how many free slots it must have, by default it is 1.*

```csharp
bool HasFreeSlots(int minSlotCount = 1);
```

### GetFreeSlots

Returns an an array of free (non-occupied) slots.\
Note: *you can optionally specify how many free slots at most it can return, default is 255 which would return all free slots that the window has.*

```csharp
ISlot[] GetFreeSlots(int maxSlotCount = 255);
```

### GetFreeSlot

Attempts to get the **first** free (non-occupied) slot it can find.\
Note: *if the window is the bot's inventory then search will start from the hotbar, whereas all other window searches start from the top left.*

```csharp
ISlot GetFreeSlot ();
```

### IsEmpty

Returns true if all slots of the window are empty (non-occupied), otherwise false.\
Note: *if the window is the bot's inventory then the armor slots and crafting slots are not taken into account.*

```csharp
bool IsEmpty();
```

### IsFull

Returns true if all slots of the window are taken (occupied), otherwise false.\
Note: *if the window is the bot's inventory then the armor slots and crafting slots are not taken into account.*

```csharp
bool IsFull();
```

### GetAmountOfItem

Returns the amount of a given block ID there are in this window.

```csharp
int GetAmountOfItem(ushort id);
```

### MouseLeftClick

Attempts to Left click on a slot at the specified index.

```csharp
Task<bool> MouseLeftClick(int index);
```

### MouseRightClick

Attempts to Right click on a slot at the specified index.

```csharp
Task<bool> MouseRightClick(int index);
```

### MouseShiftLeftClick

Attempts to Shift + Left click a slot at the specified index.

```csharp
Task<bool> MouseShiftLeftClick(int index);
```

### MouseMiddleClick

Attempts to middle click a slot at the specified index.

```csharp
Task<bool> MouseMiddleClick(int index);
```

### ClickHotbarshortcut

Hovers the mouse over a slot, which is at the specified index, and clicks the hotbar shortcut (0-8). This can transfer items from the specified slot into the hotbar or vice-versa.\
Note: *hotbarIndex should be a value between 0 (most left slot) and 8 (most right slot).*

```csharp
Task<bool> ClickHotbarShortcut(int index, int hotbarIndex);
```

### Take

Attempts to transfer items, that match the specified id(s) and where optionalCanBePicked optionally returns true, from the open window to the bot's inventory. You can also optionally specify the max amount of stacks the bot can take in a single function call.\
Note: ***this must be called on the window and not the bot's inventory, otherwise an exception will be thrown.***

```csharp
Task<bool> Take(ushort id , int maxStacks = -1, Func<ISlot, bool> optionalCanBePicked = null);
Task<bool> Take(ushort[] ids = null, int maxStacks = -1, Func<ISlot, bool> optionalCanBePicked = null);
```

### Deposit

Attempts to transfer items, that match the specified id(s) and where optionalCanBePicked optionally returns true, from the bot's inventory to the open window.\
Note: ***this must be called on the window and not the bot's inventory, otherwise an exception will be thrown.***

```csharp
Task<bool> Deposit(ushort id, Func<ISlot, bool> optionalCanPickSlot = null);
Task<bool> Deposit(ushort[] ids = null, Func<ISlot, bool> optionalCanPickSlot = null);
```


# ISlot

Represents an instance of a slot.

Note: *A lot of inventory functions usually have a bool to indicate the tasks success or failure, as the server can reject these actions.*

| Methods               | Properties               |
| --------------------- | ------------------------ |
| HasNbt                | Id                       |
| GetName               | Count                    |
| GetLore               | Damage *(aka. metadata)* |
| HasEnchantment        | ~~Nbt~~ *(legacy)*       |
| GetEnchantmentLevel   |                          |
| GetEnchantments       |                          |
| ~~GetNBT~~ *(legacy)* |                          |
| IsEmpty               |                          |
| IsStackFull           |                          |
| IsStackable           |                          |
| DropStack             |                          |
| Drop                  |                          |
| Eat                   |                          |
| Select                |                          |
| Use                   |                          |
| Transfer              |                          |
| DepositTo             |                          |
| BringToHotbar         |                          |
| IsWearable            |                          |
| PutOn                 |                          |
| TakeOff               |                          |

## Methods

### HasNbt

Returns true if the slot has NBT data, otherwise false. NBT data can store such information as enchantments, the title (custom name) of the item, etc.\
You do not have to access the NBT variable manually, instead functions like GetName(), HasEnchantment(), etc should be used instead.

```csharp
bool HasNbt();
```

### GetName

Returns the title (custom name) of the item. Can be null if there is no NBT data and the item was not renamed by the server/anvil.

```csharp
string GetName();
```

### GetLore

Returns the lore (description) of the item from the NBT data, if there is no NBT data then null is returned.

```csharp
string GetLore();
```

### HasEnchantment

Returns true if the Item has an enchantment with a given id, otherwise false. You can find the enchantment id list [here](https://www.digminecraft.com/lists/enchantment_list_pc.php).

```csharp
bool HasEnchantment(int id);
```

### GetEnchantmentLevel

Returns the enchantment level on this item by enchantment id. You can find the enchantment id list [here](https://www.digminecraft.com/lists/enchantment_list_pc.php).\
Note: *returns -1 if the item does not have an enchantment with the specified id.*

```csharp
int GetEnchantmentLevel(int id);
```

### GetEnchantments

Returns an array of all enchantments on the item. The enchantment class contains the id and level of the enchantment.

```csharp
Enchantment[] GetEnchantments();
```

### ~~GetNBT~~ *(legacy)*

Returns a string representation of the NBT data.

```csharp
string GetNBT();
```

### IsEmpty

Returns true if the slot is empty (non-occupied), otherwise false.

```csharp
bool IsEmpty();
```

### IsStackFull

Returns true if the item stack is full, otherwise false.

```csharp
bool IsStackFull();
```

### IsStackable

Returns true if the item is stackable, otherwise false.

```csharp
bool IsStackable();
```

### DropStack

Attempts to drop the entire stack, returns true if this was successful, otherwise false.

```csharp
Task<bool> DropStack();
```

### Drop

Attempts to drop a single item (1 out of 64) from the item stack. Returns true if successful, otherwise false.

```csharp
Task<bool> Drop();
```

### Eat

Attempts to eat the Item. Returns true if successful, otherwise false.

```csharp
Task<bool> Eat();
```

### Select

Attempts to select (bring to to hotbar and select) the item from this slot. Returns true if successful, otherwise false.

```csharp
Task<bool> Select();
```

### Use

Attempts to use (bring to hotbar, select, and right click it) the item from this slot. Returns true if successful, otherwise false.

```csharp
Task<bool> Use();
```

### Transfer

Attempts to transfer the item to another slot. Returns true if successful, otherwise false.

```csharp
Task<bool> Transfer(ISlot other);
```

### DepositTo

Attempts to deposit an item to the specified window. Returns true if successful, otherwise false.\
You can optionally specify a specific slot index that the item should be placed at using the index parameter. If the index is not specified then it will place the item in the first available slot.&#x20;

```csharp
Task<bool> DepositTo(IWindow window, sbyte index = -1);
```

### BringToHotbar

Attempts to bring the item to the hotbar. Returns true if successful, otherwise false.\
You can optionally specify a hotbar slot index (0-8). If the slot index is not specified then it will place it in the first available slot or the currently selected slot.

```csharp
Task<bool> BringToHotbar(sbyte optionalSlotIndex = -1);
```

### IsWearable

Returns true if the item is wearable (e.g.: armor).

```csharp
bool IsWearable();
```

### PutOn

Attempts to put on (equip) the item. Returns true if successful, otherwise false.

```csharp
Task<bool> PutOn();
```

### TakeOff

Attempts to take off (unequip) the item. Returns true if successful, otherwise false.

```csharp
Task<bool> TakeOff();
```


# Functions

This part refers to the class [**IPlayeFunctions.cs**](https://github.com/OnlyQubes/OQ.MineBot.PluginBase/blob/master/IPlayerFunctions.cs), which can be accessed through **Context.Functions**. This is a legacy system that has many low-level functions. There is no official documentation for this part, however you can find comments on the Github page for most of the functions.


# Utility


# ChestMap

Allows you to easily and efficiently (remember full/empty chests) find and open chests by criteria. Create with 'Context.Functions.CreateChestMap()'.

It is important that you call 'chestmap.UpdateChestList' at least once before calling 'chestmap.Open', otherwise the results and unpredictable. The chest map can be updated many times afterwards, where the main purpose of this is to find newly rendered/placed chests and could be used when the bot is teleported/moved far away.

'chestmap.Open' will attempt to move to the closest chest that meets the specified criteria (e.g.: non-full). If it's successful then IWindow is returned, where it represents the opened chest containers, otherwise null is returned.

### Example usage

In the code below on the start of the plugin we initialize and populate the chest map. Every tick we attempt to open a non-full chest and attempt to store our items in it. You can imagine that Exec() returns true only if the bot's inventory is full and this could be used as a "storage on full" task.

```csharp
private ChestMap chestMap;

public async Task Start() {
    // Create and populate the chestmap. This will keep a reference of all
    // chest positions and their state (full/empty).
    chestMap = Context.Functions.CreateChestMap();
    await chestMap.UpdateChestList();
}

public async Task OnTick() {
    // Attempt to open a non-full chest.
    var openWindow = await chestMap.Open(ChestStatus.NotFull);
    if(openWindow != null) {
        // We have successfully opened a chest, store all items.
        await openWindow.Deposit();
        await openWindow.Close();
    }
}
```


# LocationBlacklistCollection

Allows you to "blacklist" (set as invalid) locations for a certain amount of times. Create with 'LocationBlacklistCollection.CreatePerBot(...)' or 'LocationBlacklistCollection.CreateGlobal(...)'.

### Example usage

The code below finds the closest diamond block and attempts to move to it and then mine it. If the block is unreachable then it's added to the blacklist for 1 hour. The blacklist ensures that the same block is no longer picked in the search with the code `!blacklist.IsBlocked(context, block.GetLocation())`.

*Optionally the code below could also use LocationWhitelistCollection to make sure that multiple bots don't try to move to the same diamond ore block.*

```csharp
private static LocationBlacklistCollection blacklist = 
LocationBlacklistCollection.CreateGlobal(3, // 3 bots need to blacklist to blacklist globally.
                                         13600000, // 1 hour in milliseconds.
                                         2); // block a 2x2 radius around a block as well.

public async Task OnTick() {
    const ushort diamondOre = 56;
    var block = Context.World.FindClosest(128, 64, // search a 256x128 area.
    diamondOre, CpuMode.Medium_Usage, // search for diamond ore blocks.
    block => !blacklist.IsBlocked(context, block.GetLocation())); // do not include blocks that are blacklisted.

    if(block == null) {
        Console.WriteLine("Could not find any reachable diamond ores");
        return;
    }
    
    // Move to the closest diamond ore.
    var moveTask = await block.MoveToInteractionRange().Task;
    if(moveTask.Result != MoveResultType.Completed) {
        Console.WriteLine($"Could not reach ore at {block.GetLocation()}, blacklisting it.");
        blacklist.AddToBlockCounter(context, block.GetLocation());
        return;
    }
    
    // Reached the block, mine it.
    await block.Dig();
}
```


# LocationWhitelistCollection

Allows you to "whitelist" a location for a certain bot, but "blacklist" it for others. Create with 'LocationWhitelistCollection.Create(...)'.

### Example usage

The code below finds the closest diamond block and attempts to move to it and then mine it. When we find a diamond ore we add it to a whitelist, where it's "whitelisted" to the current bot, but it's "blacklisted" from all other bots.

*This may not ensure that two bots don't pick the same block, due to how multi-threading works. To ensure that locking is required.*

```csharp
private static LocationWhitelistCollection whitelist = 
LocationWhitelistCollection.Create(3); // 3 blacklist 3x3 are around the location for other bots.

public async Task OnTick() {
    const ushort diamondOre = 56;
    var block = Context.World.FindClosest(128, 64, // search a 256x128 area.
    diamondOre, CpuMode.Medium_Usage, // search for diamond ore blocks.
    block => !whitelist.IsTaken(context, block.GetLocation())); // do not include blocks that are taken.
    
    if(block == null) {
        Console.WriteLine("Could not find any reachable diamond ores");
        return;
    }
    // Mark this location as taken, so other bots that are 
    // searching for a location don't take the pick this block as well.
    whitelist.Take(context, block.GetLocation());
    
    // Move to the closest diamond ore.
    var moveTask = await block.MoveToInteractionRange().Task;
    if(moveTask.Result != MoveResultType.Completed) {
        Console.WriteLine($"Could not reach ore at {block.GetLocation()}.");
        return;
    }
    
    // Reached the block, mine it.
    await block.Dig();
    
    // We mined the block and no longer care about it, nor do we 
    // have to keep it "blacklisted" from other bots. Therefore we
    // should release our current block.
    whitelist.Release(context);
}
```


