Skip to content

Commit

Permalink
Items Collector Chat Bot
Browse files Browse the repository at this point in the history
Items Collector Chat Bot
  • Loading branch information
milutinke authored May 21, 2023
2 parents a4fb677 + cfc2baa commit 1bba41c
Show file tree
Hide file tree
Showing 7 changed files with 1,545 additions and 1,873 deletions.
208 changes: 208 additions & 0 deletions MinecraftClient/ChatBots/ItemsCollector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Inventory;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;

namespace MinecraftClient.ChatBots;

public class ItemsCollector : ChatBot
{
public const string CommandName = "itemscollector";
public static Configs Config = new();

[TomlDoNotInlineObject]
public class Configs
{
[NonSerialized] private const string BotName = "ItemsCollector";

public bool Enabled = false;

[TomlInlineComment("$ChatBot.ItemsCollector.Collect_All_Item_Types$")]
public bool Collect_All_Item_Types = true;

[TomlInlineComment("$ChatBot.ItemsCollector.Items_Whitelist$")]
public List<ItemType> Items_Whitelist = new() { ItemType.Diamond, ItemType.NetheriteIngot };

[TomlInlineComment("$ChatBot.ItemsCollector.Delay_Between_Tasks$")]
public int Delay_Between_Tasks = 300;

[TomlInlineComment("$ChatBot.ItemsCollector.Collection_Radius$")]
public double Collection_Radius = 30.0;

[TomlInlineComment("$ChatBot.ItemsCollector.Always_Return_To_Start$")]
public bool Always_Return_To_Start = true;

[TomlInlineComment("$ChatBot.ItemsCollector.Prioritize_Clusters$")]
public bool Prioritize_Clusters = false;

public void OnSettingUpdate()
{
if (Delay_Between_Tasks < 100)
Delay_Between_Tasks = 100;
}
}

private bool running = false;
private Thread? mainProcessThread;

public override void Initialize()
{
if (!GetEntityHandlingEnabled())
{
LogToConsole(Translations.extra_entity_required);
LogToConsole(Translations.general_bot_unload);
UnloadBot();
return;
}

if (!GetTerrainEnabled())
{
LogToConsole(Translations.extra_terrainandmovement_required);
LogToConsole(Translations.general_bot_unload);
UnloadBot();
return;
}

McClient.dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty)))
);

McClient.dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("start")
.Executes(r => OnCommandStart(r.Source)))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandStop(r.Source)))
.Then(l => l.Literal("_help")
.Executes(r => OnCommandHelp(r.Source, string.Empty))
.Redirect(McClient.dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}

public override void OnUnload()
{
McClient.dispatcher.Unregister(CommandName);
McClient.dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}

private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
_ => Translations.cmd_items_collector_desc + ": " + Translations.cmd_items_collector_usage
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}

private int OnCommandStart(CmdResult r)
{
if (running)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.cmd_items_collector_already_collecting);

StartTheMainProcess();
return r.SetAndReturn(CmdResult.Status.Done, Translations.cmd_items_collector_started);
}

private int OnCommandStop(CmdResult r)
{
if (!running)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.cmd_items_collector_already_not_collecting);

StopTheMainProcess();
return r.SetAndReturn(CmdResult.Status.Done, Translations.cmd_items_collector_stopping);
}

private void StartTheMainProcess()
{
running = true;
mainProcessThread = new Thread(MainProcess);
mainProcessThread.Start();
}

private void StopTheMainProcess()
{
running = false;
}

private void MainProcess()
{
var startingLocation = GetCurrentLocation();

while (running)
{
var currentLocation = GetCurrentLocation();
var items = GetEntities()
.Where(x =>
x.Value.Type == EntityType.Item &&
x.Value.Location.Distance(currentLocation) <= Config.Collection_Radius &&
(Config.Collect_All_Item_Types || Config.Items_Whitelist.Contains(x.Value.Item.Type)))
.Select(x => x.Value)
.ToList();

if (Config.Prioritize_Clusters && items.Count > 1)
{
var centroid = new Location(
items.Average(x => x.Location.X),
items.Average(x => x.Location.Y),
items.Average(x => x.Location.Z)
);

items = items.OrderBy(x => x.Location.Distance(centroid) / items.Count).ToList();
}
else items = items.OrderBy(x => x.Location.Distance(currentLocation)).ToList();

if (items.Any())
{
foreach (var entity in items)
{
if (!running)
break;

WaitForMoveToLocation(entity.Location);
}
}
else
{
if (startingLocation.Distance(currentLocation) > 2f && Config.Always_Return_To_Start)
WaitForMoveToLocation(startingLocation);
}

if (!running)
break;

Thread.Sleep(Config.Delay_Between_Tasks);
}

LogToConsole(Translations.cmd_items_collector_stopped);
}

public override void AfterGameJoined()
{
StopTheMainProcess();
}

public override bool OnDisconnect(DisconnectReason reason, string message)
{
StopTheMainProcess();
return true;
}

private bool WaitForMoveToLocation(Location location, float tolerance = 1f)
{
if (!MoveToLocation(location)) return false;
while (GetCurrentLocation().Distance(location) > tolerance)
Thread.Sleep(200);

return true;
}
}
5 changes: 4 additions & 1 deletion MinecraftClient/McClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ private void RegisterBots(bool reload = false)
if (Config.ChatBot.ReplayCapture.Enabled && reload) { BotLoad(new ReplayCapture()); }
if (Config.ChatBot.ScriptScheduler.Enabled) { BotLoad(new ScriptScheduler()); }
if (Config.ChatBot.TelegramBridge.Enabled) { BotLoad(new TelegramBridge()); }
if (Config.ChatBot.ItemsCollector.Enabled) { BotLoad(new ItemsCollector()); }
//Add your ChatBot here by uncommenting and adapting
//BotLoad(new ChatBots.YourBot());
}
Expand Down Expand Up @@ -3405,7 +3406,9 @@ public void OnEntityMetadata(int entityID, Dictionary<int, object?> metadata)
{
Entity entity = entities[entityID];
entity.Metadata = metadata;
if (entity.Type.ContainsItem() && metadata.TryGetValue(7, out object? itemObj) && itemObj != null && itemObj.GetType() == typeof(Item))
int itemEntityMetadataFieldIndex = protocolversion < Protocol18Handler.MC_1_17_Version ? 7 : 8;

if (entity.Type.ContainsItem() && metadata.TryGetValue(itemEntityMetadataFieldIndex, out object? itemObj) && itemObj != null && itemObj.GetType() == typeof(Item))
{
Item item = (Item)itemObj;
if (item == null)
Expand Down
Loading

0 comments on commit 1bba41c

Please sign in to comment.