Implement command completion suggestions.

This commit is contained in:
BruceChen 2022-12-06 15:50:17 +08:00
parent 5d2589b10f
commit 84cf749344
115 changed files with 4684 additions and 2695 deletions

View file

@ -1,5 +1,6 @@
using System;
using System.Linq;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots

View file

@ -1,5 +1,8 @@
using System;
using Brigadier.NET;
using MinecraftClient.CommandHandler;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -90,7 +93,7 @@ namespace MinecraftClient.ChatBots
count = 0;
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (Config.Use_Terrain_Handling)
{

View file

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using Brigadier.NET;
using MinecraftClient.CommandHandler;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -109,7 +112,7 @@ namespace MinecraftClient.ChatBots
attackPassive = Config.Attack_Passive;
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!GetEntityHandlingEnabled())
{

View file

@ -2,8 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Inventory;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.AutoCraft.Configs;
@ -11,6 +16,8 @@ namespace MinecraftClient.ChatBots
{
public class AutoCraft : ChatBot
{
public const string CommandName = "autocraft";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -40,7 +47,7 @@ namespace MinecraftClient.ChatBots
Name: "Recipe-Name-2",
Type: CraftTypeConfig.table,
Result: ItemType.StoneBricks,
Slots: new ItemType[9] {
Slots: new ItemType[9] {
ItemType.Stone, ItemType.Stone, ItemType.Null,
ItemType.Stone, ItemType.Stone, ItemType.Null,
ItemType.Null, ItemType.Null, ItemType.Null,
@ -117,7 +124,7 @@ namespace MinecraftClient.ChatBots
public ItemType Result = ItemType.Air;
public ItemType[] Slots = new ItemType[9] {
public ItemType[] Slots = new ItemType[9] {
ItemType.Null, ItemType.Null, ItemType.Null,
ItemType.Null, ItemType.Null, ItemType.Null,
ItemType.Null, ItemType.Null, ItemType.Null,
@ -279,7 +286,7 @@ namespace MinecraftClient.ChatBots
}
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!GetInventoryEnabled())
{
@ -288,81 +295,93 @@ namespace MinecraftClient.ChatBots
UnloadBot();
return;
}
RegisterChatBotCommand("autocraft", Translations.bot_autoCraft_cmd, GetHelp(), CommandHandler);
RegisterChatBotCommand("ac", Translations.bot_autoCraft_alias, GetHelp(), CommandHandler);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
.Then(l => l.Literal("list")
.Executes(r => OnCommandHelp(r.Source, "list")))
.Then(l => l.Literal("start")
.Executes(r => OnCommandHelp(r.Source, "start")))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandHelp(r.Source, "stop")))
.Then(l => l.Literal("help")
.Executes(r => OnCommandHelp(r.Source, "help")))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("list")
.Executes(r => OnCommandList(r.Source)))
.Then(l => l.Literal("start")
.Then(l => l.Argument("RecipeName", MccArguments.AutoCraftRecipeName())
.Executes(r => OnCommandStart(r.Source, Arguments.GetString(r, "RecipeName")))))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandStop(r.Source)))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
public string CommandHandler(string cmd, string[] args)
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
if (args.Length > 0)
{
switch (args[0])
{
case "list":
StringBuilder nameList = new();
foreach (RecipeConfig recipe in Config.Recipes)
nameList.Append(recipe.Name).Append(", ");
return string.Format(Translations.bot_autoCraft_cmd_list, Config.Recipes.Length, nameList.ToString());
case "start":
if (args.Length >= 2)
{
string name = args[1];
bool hasRecipe = false;
RecipeConfig? recipe = null;
foreach (RecipeConfig recipeConfig in Config.Recipes)
{
if (recipeConfig.Name == name)
{
hasRecipe = true;
recipe = recipeConfig;
break;
}
}
if (hasRecipe)
{
ResetVar();
PrepareCrafting(recipe!);
return "";
}
else
return Translations.bot_autoCraft_recipe_not_exist;
}
else
return Translations.bot_autoCraft_no_recipe_name;
case "stop":
StopCrafting();
return Translations.bot_autoCraft_stop;
case "help":
return GetCommandHelp(args.Length >= 2 ? args[1] : "");
default:
return GetHelp();
}
}
else return GetHelp();
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private static string GetHelp()
private int OnCommandHelp(CmdResult r, string? cmd)
{
return string.Format(Translations.bot_autoCraft_available_cmd, "load, list, reload, resetcfg, start, stop, help");
}
private string GetCommandHelp(string cmd)
{
return cmd.ToLower() switch
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
"load" => Translations.bot_autoCraft_help_load,
"list" => Translations.bot_autoCraft_help_list,
"reload" => Translations.bot_autoCraft_help_reload,
"resetcfg" => Translations.bot_autoCraft_help_resetcfg,
"start" => Translations.bot_autoCraft_help_start,
"stop" => Translations.bot_autoCraft_help_stop,
"help" => Translations.bot_autoCraft_help_help,
_ => GetHelp(),
_ => string.Format(Translations.bot_autoCraft_available_cmd, "load, list, reload, resetcfg, start, stop, help")
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
};
});
}
private int OnCommandList(CmdResult r)
{
StringBuilder nameList = new();
foreach (RecipeConfig recipe in Config.Recipes)
nameList.Append(recipe.Name).Append(", ");
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_autoCraft_cmd_list, Config.Recipes.Length, nameList.ToString()));
}
private int OnCommandStart(CmdResult r, string name)
{
bool hasRecipe = false;
RecipeConfig? recipe = null;
foreach (RecipeConfig recipeConfig in Config.Recipes)
{
if (recipeConfig.Name == name)
{
hasRecipe = true;
recipe = recipeConfig;
break;
}
}
if (hasRecipe)
{
ResetVar();
PrepareCrafting(recipe!);
return r.SetAndReturn(CmdResult.Status.Done);
}
else
{
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_autoCraft_recipe_not_exist);
}
}
private int OnCommandStop(CmdResult r)
{
StopCrafting();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoCraft_stop);
}
#region Core part of auto-crafting
@ -442,7 +461,7 @@ namespace MinecraftClient.ChatBots
ItemType ResultItem = recipeConfig.Result;
ContainerType CraftingAreaType =
ContainerType CraftingAreaType =
(recipeConfig.Type == CraftTypeConfig.player) ? ContainerType.PlayerInventory : ContainerType.Crafting;
PrepareCrafting(new Recipe(materials, ResultItem, CraftingAreaType));

View file

@ -1,13 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
public class AutoDig : ChatBot
{
public const string CommandName = "autodig";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -60,7 +67,7 @@ namespace MinecraftClient.ChatBots
{
if (Auto_Start_Delay >= 0)
Auto_Start_Delay = Math.Max(0.1, Auto_Start_Delay);
if (Dig_Timeout >= 0)
Dig_Timeout = Math.Max(0.1, Dig_Timeout);
@ -103,7 +110,7 @@ namespace MinecraftClient.ChatBots
Stopping,
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!GetTerrainEnabled())
{
@ -117,32 +124,67 @@ namespace MinecraftClient.ChatBots
if (!inventoryEnabled && Config.Auto_Tool_Switch)
LogToConsole(Translations.bot_autodig_no_inv_handle);
RegisterChatBotCommand("digbot", Translations.bot_autodig_cmd, GetHelp(), CommandHandler);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
.Then(l => l.Literal("start")
.Executes(r => OnCommandHelp(r.Source, "start")))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandHelp(r.Source, "stop")))
.Then(l => l.Literal("help")
.Executes(r => OnCommandHelp(r.Source, "help")))
)
);
var cmd = 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")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
dispatcher.Register(l => l.Literal("digbot")
.Redirect(cmd)
);
}
public string CommandHandler(string cmd, string[] args)
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
if (args.Length > 0)
dispatcher.Unregister("digbot");
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
switch (args[0])
{
case "start":
lock (stateLock)
{
counter = 0;
state = State.WaitingStart;
}
return Translations.bot_autodig_start;
case "stop":
StopDigging();
return Translations.bot_autodig_stop;
case "help":
return GetCommandHelp(args.Length >= 2 ? args[1] : "");
default:
return GetHelp();
}
#pragma warning disable format // @formatter:off
"start" => Translations.bot_autodig_help_start,
"stop" => Translations.bot_autodig_help_stop,
"help" => Translations.bot_autodig_help_help,
_ => string.Format(Translations.bot_autodig_available_cmd, "start, stop, help")
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
private int OnCommandStart(CmdResult r)
{
lock (stateLock)
{
counter = 0;
state = State.WaitingStart;
}
else return GetHelp();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autodig_start);
}
private int OnCommandStop(CmdResult r)
{
StopDigging();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autodig_stop);
}
private void StartDigging()
@ -240,7 +282,7 @@ namespace MinecraftClient.ChatBots
else if ((Config.List_Type == Configs.ListType.whitelist && Config.Blocks.Contains(block.Type)) ||
(Config.List_Type == Configs.ListType.blacklist && !Config.Blocks.Contains(block.Type)))
{
if (Config.Mode == Configs.ModeType.lookat ||
if (Config.Mode == Configs.ModeType.lookat ||
(Config.Mode == Configs.ModeType.both && Config._Locations.Contains(blockLoc)))
{
if (DigBlock(blockLoc, lookAtBlock: false))
@ -288,8 +330,8 @@ namespace MinecraftClient.ChatBots
foreach (Location location in Config._Locations)
{
Block block = GetWorld().GetBlock(location);
if (block.Type != Material.Air &&
((Config.List_Type == Configs.ListType.whitelist && Config.Blocks.Contains(block.Type)) ||
if (block.Type != Material.Air &&
((Config.List_Type == Configs.ListType.whitelist && Config.Blocks.Contains(block.Type)) ||
(Config.List_Type == Configs.ListType.blacklist && !Config.Blocks.Contains(block.Type))))
{
double distance = current.Distance(location);
@ -401,23 +443,5 @@ namespace MinecraftClient.ChatBots
return base.OnDisconnect(reason, message);
}
private static string GetHelp()
{
return string.Format(Translations.bot_autodig_available_cmd, "start, stop, help");
}
private string GetCommandHelp(string cmd)
{
return cmd.ToLower() switch
{
#pragma warning disable format // @formatter:off
"start" => Translations.bot_autodig_help_start,
"stop" => Translations.bot_autodig_help_stop,
"help" => Translations.bot_autodig_help_help,
_ => GetHelp(),
#pragma warning restore format // @formatter:on
};
}
}
}

View file

@ -1,7 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Inventory;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.AutoDrop.Configs;
@ -9,6 +14,8 @@ namespace MinecraftClient.ChatBots
{
public class AutoDrop : ChatBot
{
public const string CommandName = "autodrop";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -38,111 +45,7 @@ namespace MinecraftClient.ChatBots
private readonly int updateDebounceValue = 2;
private int inventoryUpdated = -1;
public string CommandHandler(string cmd, string[] args)
{
if (args.Length > 0)
{
switch (args[0].ToLower())
{
case "on":
Config.Enabled = true;
inventoryUpdated = 0;
OnUpdateFinish();
return Translations.bot_autoDrop_on;
case "off":
Config.Enabled = false;
return Translations.bot_autoDrop_off;
case "add":
if (args.Length >= 2)
{
if (Enum.TryParse(args[1], true, out ItemType item))
{
Config.Items.Add(item);
return string.Format(Translations.bot_autoDrop_added, item.ToString());
}
else
{
return string.Format(Translations.bot_autoDrop_incorrect_name, args[1]);
}
}
else
{
return Translations.cmd_inventory_help_usage + ": add <item name>";
}
case "remove":
if (args.Length >= 2)
{
if (Enum.TryParse(args[1], true, out ItemType item))
{
if (Config.Items.Contains(item))
{
Config.Items.Remove(item);
return string.Format(Translations.bot_autoDrop_removed, item.ToString());
}
else
{
return Translations.bot_autoDrop_not_in_list;
}
}
else
{
return string.Format(Translations.bot_autoDrop_incorrect_name, args[1]);
}
}
else
{
return Translations.cmd_inventory_help_usage + ": remove <item name>";
}
case "list":
if (Config.Items.Count > 0)
{
return string.Format(Translations.bot_autoDrop_list, Config.Items.Count, string.Join("\n", Config.Items));
}
else
{
return Translations.bot_autoDrop_no_item;
}
case "mode":
if (args.Length >= 2)
{
switch (args[1].ToLower())
{
case "include":
Config.Mode = DropMode.include;
break;
case "exclude":
Config.Mode = DropMode.exclude;
break;
case "everything":
Config.Mode = DropMode.everything;
break;
default:
return Translations.bot_autoDrop_unknown_mode; // Unknwon mode. Available modes: Include, Exclude, Everything
}
inventoryUpdated = 0;
OnUpdateFinish();
return string.Format(Translations.bot_autoDrop_switched, Config.Mode.ToString()); // Switched to {0} mode.
}
else
{
return Translations.bot_autoDrop_unknown_mode;
}
default:
return GetHelp();
}
}
else
{
return GetHelp();
}
}
private static string GetHelp()
{
return string.Format(Translations.general_available_cmd, "on, off, add, remove, list, mode");
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!GetInventoryEnabled())
{
@ -151,8 +54,113 @@ namespace MinecraftClient.ChatBots
UnloadBot();
return;
}
RegisterChatBotCommand("autodrop", Translations.bot_autoDrop_cmd, GetHelp(), CommandHandler);
RegisterChatBotCommand("ad", Translations.bot_autoDrop_alias, GetHelp(), CommandHandler);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
.Then(l => l.Literal("add")
.Executes(r => OnCommandHelp(r.Source, "add")))
.Then(l => l.Literal("remove")
.Executes(r => OnCommandHelp(r.Source, "remove")))
.Then(l => l.Literal("mode")
.Executes(r => OnCommandHelp(r.Source, "mode")))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("on")
.Executes(r => OnCommandEnable(r.Source, true)))
.Then(l => l.Literal("off")
.Executes(r => OnCommandEnable(r.Source, false)))
.Then(l => l.Literal("add")
.Then(l => l.Argument("ItemType", MccArguments.ItemType())
.Executes(r => OnCommandAdd(r.Source, MccArguments.GetItemType(r, "ItemType")))))
.Then(l => l.Literal("remove")
.Then(l => l.Argument("ItemType", MccArguments.ItemType())
.Executes(r => OnCommandRemove(r.Source, MccArguments.GetItemType(r, "ItemType")))))
.Then(l => l.Literal("list")
.Executes(r => OnCommandList(r.Source)))
.Then(l => l.Literal("mode")
.Then(l => l.Literal("include")
.Executes(r => OnCommandMode(r.Source, DropMode.include)))
.Then(l => l.Literal("exclude")
.Executes(r => OnCommandMode(r.Source, DropMode.exclude)))
.Then(l => l.Literal("everything")
.Executes(r => OnCommandMode(r.Source, DropMode.everything))))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
"add" => Translations.cmd_inventory_help_usage + ": add <item name>",
"remove" => Translations.cmd_inventory_help_usage + ": remove <item name>",
"mode" => Translations.bot_autoDrop_unknown_mode,
_ => string.Format(Translations.general_available_cmd, "on, off, add, remove, list, mode")
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
private int OnCommandEnable(CmdResult r, bool enable)
{
if (enable)
{
Config.Enabled = true;
inventoryUpdated = 0;
OnUpdateFinish();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoDrop_on);
}
else
{
Config.Enabled = false;
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoDrop_off);
}
}
private int OnCommandAdd(CmdResult r, ItemType item)
{
Config.Items.Add(item);
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_autoDrop_added, item.ToString()));
}
private int OnCommandRemove(CmdResult r, ItemType item)
{
if (Config.Items.Contains(item))
{
Config.Items.Remove(item);
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_autoDrop_removed, item.ToString()));
}
else
{
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_autoDrop_not_in_list);
}
}
private int OnCommandList(CmdResult r)
{
if (Config.Items.Count > 0)
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_autoDrop_list, Config.Items.Count, string.Join("\n", Config.Items)));
else
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_autoDrop_no_item);
}
private int OnCommandMode(CmdResult r, DropMode mode)
{
Config.Mode = mode;
inventoryUpdated = 0;
OnUpdateFinish();
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_autoDrop_switched, Config.Mode.ToString()));
}
public override void Update()

View file

@ -1,5 +1,6 @@
using System;
using MinecraftClient.Inventory;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots

View file

@ -2,8 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Inventory;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.AutoFishing.Configs;
@ -15,6 +20,8 @@ namespace MinecraftClient.ChatBots
/// </summary>
public class AutoFishing : ChatBot
{
public const string CommandName = "autofishing";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -169,87 +176,119 @@ namespace MinecraftClient.ChatBots
Stopping,
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!GetEntityHandlingEnabled())
{
LogToConsole(Translations.extra_entity_required);
state = FishingState.WaitJoinGame;
}
inventoryEnabled = GetInventoryEnabled();
if (!inventoryEnabled)
LogToConsole(Translations.bot_autoFish_no_inv_handle);
RegisterChatBotCommand("fish", Translations.bot_autoFish_cmd, GetHelp(), CommandHandler);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
.Then(l => l.Literal("start")
.Executes(r => OnCommandHelp(r.Source, "start")))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandHelp(r.Source, "stop")))
.Then(l => l.Literal("status")
.Executes(r => OnCommandHelp(r.Source, "status")))
.Then(l => l.Literal("help")
.Executes(r => OnCommandHelp(r.Source, "help")))
)
);
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("status")
.Executes(r => OnCommandStatus(r.Source))
.Then(l => l.Literal("clear")
.Executes(r => OnCommandStatusClear(r.Source))))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
public string CommandHandler(string cmd, string[] args)
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
if (args.Length >= 1)
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
switch (args[0])
{
case "start":
isFishing = false;
lock (stateLock)
{
isFishing = false;
counter = 0;
state = FishingState.StartMove;
}
return Translations.bot_autoFish_start;
case "stop":
isFishing = false;
lock (stateLock)
{
isFishing = false;
if (state == FishingState.WaitingFishToBite)
UseFishRod();
state = FishingState.Stopping;
}
StopFishing();
return Translations.bot_autoFish_stop;
case "status":
if (args.Length >= 2)
{
if (args[1] == "clear")
{
fishItemCnt = new();
return Translations.bot_autoFish_status_clear;
}
else
{
return GetCommandHelp("status");
}
}
else
{
if (fishItemCnt.Count == 0)
return Translations.bot_autoFish_status_info;
#pragma warning disable format // @formatter:off
"start" => Translations.bot_autoFish_help_start,
"stop" => Translations.bot_autoFish_help_stop,
"status" => Translations.bot_autoFish_help_status,
"help" => Translations.bot_autoFish_help_help,
_ => string.Format(Translations.bot_autoFish_available_cmd, "start, stop, status, help")
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
List<KeyValuePair<ItemType, uint>> orderedList = fishItemCnt.OrderBy(x => x.Value).ToList();
int maxLen = orderedList[^1].Value.ToString().Length;
StringBuilder sb = new();
sb.Append(Translations.bot_autoFish_status_info);
foreach ((ItemType type, uint cnt) in orderedList)
{
sb.Append(Environment.NewLine);
string cntStr = cnt.ToString();
sb.Append(' ', maxLen - cntStr.Length).Append(cntStr);
sb.Append(" x ");
sb.Append(Item.GetTypeString(type));
}
return sb.ToString();
}
case "help":
return GetCommandHelp(args.Length >= 2 ? args[1] : "");
default:
return GetHelp();
}
private int OnCommandStart(CmdResult r)
{
isFishing = false;
lock (stateLock)
{
isFishing = false;
counter = 0;
state = FishingState.StartMove;
}
else
return GetHelp();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoFish_start);
}
private int OnCommandStop(CmdResult r)
{
isFishing = false;
lock (stateLock)
{
isFishing = false;
if (state == FishingState.WaitingFishToBite)
UseFishRod();
state = FishingState.Stopping;
}
StopFishing();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoFish_stop);
}
private int OnCommandStatus(CmdResult r)
{
if (fishItemCnt.Count == 0)
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoFish_status_info);
List<KeyValuePair<ItemType, uint>> orderedList = fishItemCnt.OrderBy(x => x.Value).ToList();
int maxLen = orderedList[^1].Value.ToString().Length;
StringBuilder sb = new();
sb.Append(Translations.bot_autoFish_status_info);
foreach ((ItemType type, uint cnt) in orderedList)
{
sb.Append(Environment.NewLine);
string cntStr = cnt.ToString();
sb.Append(' ', maxLen - cntStr.Length).Append(cntStr);
sb.Append(" x ");
sb.Append(Item.GetTypeString(type));
}
LogToConsole(sb.ToString());
return r.SetAndReturn(CmdResult.Status.Done);
}
private int OnCommandStatusClear(CmdResult r)
{
fishItemCnt = new();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_autoFish_status_clear);
}
private void StartFishing()
@ -386,7 +425,7 @@ namespace MinecraftClient.ChatBots
public override void OnEntitySpawn(Entity entity)
{
if (fishItemCounter < 15 && entity.Type == EntityType.Item && Math.Abs(entity.Location.Y - LastPos.Y) < 2.2 &&
Math.Abs(entity.Location.X - LastPos.X) < 0.12 && Math.Abs(entity.Location.Z - LastPos.Z) < 0.12)
Math.Abs(entity.Location.X - LastPos.X) < 0.12 && Math.Abs(entity.Location.Z - LastPos.Z) < 0.12)
{
if (Config.Log_Fish_Bobber)
LogToConsole(string.Format("Item ({0}) spawn at {1}, distance = {2:0.00}", entity.ID, entity.Location, entity.Location.Distance(LastPos)));
@ -440,7 +479,7 @@ namespace MinecraftClient.ChatBots
public override void OnEntityMove(Entity entity)
{
if (isFishing && entity != null && fishingBobber!.ID == entity.ID &&
if (isFishing && entity != null && fishingBobber!.ID == entity.ID &&
(state == FishingState.WaitingFishToBite || state == FishingState.WaitingFishingBobber))
{
Location Pos = entity.Location;
@ -620,24 +659,5 @@ namespace MinecraftClient.ChatBots
return false;
}
}
private static string GetHelp()
{
return string.Format(Translations.bot_autoFish_available_cmd, "start, stop, status, help");
}
private string GetCommandHelp(string cmd)
{
return cmd.ToLower() switch
{
#pragma warning disable format // @formatter:off
"start" => Translations.bot_autoFish_help_start,
"stop" => Translations.bot_autoFish_help_stop,
"status" => Translations.bot_autoFish_help_status,
"help" => Translations.bot_autoFish_help_help,
_ => GetHelp(),
#pragma warning restore format // @formatter:on
};
}
}
}

View file

@ -1,4 +1,7 @@
using System;
using Brigadier.NET;
using MinecraftClient.CommandHandler;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -43,7 +46,7 @@ namespace MinecraftClient.ChatBots
if (Delay.min > Delay.max)
(Delay.min, Delay.max) = (Delay.max, Delay.min);
if (Retries == -1)
Retries = int.MaxValue;
@ -82,7 +85,12 @@ namespace MinecraftClient.ChatBots
LogDebugToConsole(string.Format(Translations.bot_autoRelog_launch, Config.Retries));
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
Initialize();
}
private void Initialize()
{
McClient.ReconnectionAttemptsLeft = Config.Retries;
if (Config.Ignore_Kick_Message)

View file

@ -4,6 +4,10 @@ using System.Globalization;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using Brigadier.NET;
using MinecraftClient.CommandHandler;
using MinecraftClient.Scripting;
using PInvoke;
using Tomlet.Attributes;
using static MinecraftClient.Settings;
@ -183,7 +187,7 @@ namespace MinecraftClient.ChatBots
/// <summary>
/// Initialize the AutoRespond bot from the matches file
/// </summary>
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (File.Exists(Config.Matches_File))
{
@ -304,12 +308,12 @@ namespace MinecraftClient.ChatBots
{
Dictionary<string, object> localVars = new();
string? toPerform = rule.Match(sender, message, msgType, localVars);
if (!String.IsNullOrEmpty(toPerform))
if (!string.IsNullOrEmpty(toPerform))
{
string? response = null;
CmdResult response = new();
LogToConsole(string.Format(Translations.bot_autoRespond_match_run, toPerform));
PerformInternalCommand(toPerform, ref response, localVars);
if (!String.IsNullOrEmpty(response))
if (response.status != CmdResult.Status.Done || !string.IsNullOrWhiteSpace(response.result))
LogToConsole(response);
}
}

View file

@ -1,5 +1,7 @@
using System;
using System.IO;
using MinecraftClient.CommandHandler;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -115,7 +117,7 @@ namespace MinecraftClient.ChatBots
}
}
public override void OnInternalCommand(string commandName, string commandParams, string result)
public override void OnInternalCommand(string commandName, string commandParams, CmdResult result)
{
if (saveInternal)
{

View file

@ -3,16 +3,23 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Brigadier.NET;
using Brigadier.NET.Builder;
using DSharpPlus;
using DSharpPlus.Entities;
using DSharpPlus.Exceptions;
using Microsoft.Extensions.Logging;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
public class DiscordBridge : ChatBot
{
public const string CommandName = "dscbridge";
private enum BridgeDirection
{
Both = 0,
@ -68,19 +75,75 @@ namespace MinecraftClient.ChatBots
instance = this;
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
RegisterChatBotCommand("dscbridge", "bot.DiscordBridge.desc", "dscbridge direction <both|mc|discord>", OnDscCommand);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("direction")
.Then(l => l.Literal("both")
.Executes(r => OnCommandDirection(r.Source, BridgeDirection.Both)))
.Then(l => l.Literal("mc")
.Executes(r => OnCommandDirection(r.Source, BridgeDirection.Minecraft)))
.Then(l => l.Literal("discord")
.Executes(r => OnCommandDirection(r.Source, BridgeDirection.Discord)))
)
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
Task.Run(async () => await MainAsync());
}
~DiscordBridge()
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
Disconnect();
}
public override void OnUnload()
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
_ => "dscbridge direction <both|mc|discord>"
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
private int OnCommandDirection(CmdResult r, BridgeDirection direction)
{
string bridgeName;
switch (direction)
{
case BridgeDirection.Both:
bridgeName = Translations.bot_DiscordBridge_direction_both;
bridgeDirection = BridgeDirection.Both;
break;
case BridgeDirection.Minecraft:
bridgeName = Translations.bot_DiscordBridge_direction_minecraft;
bridgeDirection = BridgeDirection.Minecraft;
break;
case BridgeDirection.Discord:
bridgeName = Translations.bot_DiscordBridge_direction_discord;
bridgeDirection = BridgeDirection.Discord;
break;
default:
goto case BridgeDirection.Both;
}
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_DiscordBridge_direction, bridgeName));
}
~DiscordBridge()
{
Disconnect();
}
@ -114,47 +177,6 @@ namespace MinecraftClient.ChatBots
return instance;
}
private string OnDscCommand(string cmd, string[] args)
{
if (args.Length == 2)
{
if (args[0].ToLower().Equals("direction"))
{
string direction = args[1].ToLower().Trim();
string bridgeName;
switch (direction)
{
case "b":
case "both":
bridgeName = Translations.bot_DiscordBridge_direction_both;
bridgeDirection = BridgeDirection.Both;
break;
case "mc":
case "minecraft":
bridgeName = Translations.bot_DiscordBridge_direction_minecraft;
bridgeDirection = BridgeDirection.Minecraft;
break;
case "d":
case "dcs":
case "discord":
bridgeName = Translations.bot_DiscordBridge_direction_discord;
bridgeDirection = BridgeDirection.Discord;
break;
default:
return Translations.bot_DiscordBridge_invalid_direction;
}
return string.Format(Translations.bot_DiscordBridge_direction, bridgeName);
};
}
return "dscbridge direction <both|mc|discord>";
}
public override void GetText(string text)
{
if (!CanSendMessages())
@ -369,9 +391,8 @@ namespace MinecraftClient.ChatBots
message = message[1..];
await e.Message.CreateReactionAsync(DiscordEmoji.FromName(discordBotClient, ":gear:"));
string? result = "";
CmdResult result = new();
PerformInternalCommand(message, ref result);
result = string.IsNullOrEmpty(result) ? "-" : result;
await e.Message.DeleteOwnReactionAsync(DiscordEmoji.FromName(discordBotClient, ":gear:"));
await e.Message.CreateReactionAsync(DiscordEmoji.FromName(discordBotClient, ":white_check_mark:"));

View file

@ -3,34 +3,22 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Inventory;
using MinecraftClient.Mapping;
using MinecraftClient.Protocol.Handlers;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
enum State
{
SearchingForCropsToBreak = 0,
SearchingForFarmlandToPlant,
PlantingCrops,
BonemealingCrops
}
enum CropType
{
Beetroot,
Carrot,
Melon,
Netherwart,
Pumpkin,
Potato,
Wheat
}
public class Farmer : ChatBot
{
public const string CommandName = "farmer";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -42,15 +30,34 @@ namespace MinecraftClient.ChatBots
public bool Enabled = false;
[TomlInlineComment("$config.ChatBot.Farmer.Delay_Between_Tasks$")]
public int Delay_Between_Tasks = 1;
public double Delay_Between_Tasks = 1.0;
public void OnSettingUpdate()
{
if (Delay_Between_Tasks <= 0)
Delay_Between_Tasks = 1;
if (Delay_Between_Tasks < 1.0)
Delay_Between_Tasks = 1.0;
}
}
public enum State
{
SearchingForCropsToBreak = 0,
SearchingForFarmlandToPlant,
PlantingCrops,
BonemealingCrops
}
public enum CropType
{
Beetroot,
Carrot,
Melon,
Netherwart,
Pumpkin,
Potato,
Wheat
}
private State state = State.SearchingForCropsToBreak;
private CropType cropType = CropType.Wheat;
private int farmingRadius = 30;
@ -59,9 +66,11 @@ namespace MinecraftClient.ChatBots
private bool allowTeleport = false;
private bool debugEnabled = false;
public int Delay_Between_Tasks_Millisecond => (int)Math.Round(Config.Delay_Between_Tasks * 1000);
private const string commandDescription = "farmer <start <crop type> [radius:<radius = 30>] [unsafe:<true/false>] [teleport:<true/false>] [debug:<true/false>]|stop>";
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (GetProtocolVersion() < Protocol18Handler.MC_1_13_Version)
{
@ -81,130 +90,152 @@ namespace MinecraftClient.ChatBots
return;
}
RegisterChatBotCommand("farmer", "bot.farmer.desc", commandDescription, OnFarmCommand);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("stop")
.Executes(r => OnCommandStop(r.Source)))
.Then(l => l.Literal("start")
.Then(l => l.Argument("CropType", MccArguments.FarmerCropType())
.Executes(r => OnCommandStart(r.Source, MccArguments.GetFarmerCropType(r, "CropType"), null))
.Then(l => l.Argument("OtherArgs", Arguments.GreedyString())
.Executes(r => OnCommandStart(r.Source, MccArguments.GetFarmerCropType(r, "CropType"), Arguments.GetString(r, "OtherArgs"))))))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
private string OnFarmCommand(string cmd, string[] args)
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
if (args.Length > 0)
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
if (args[0].Equals("stop", StringComparison.OrdinalIgnoreCase))
{
if (!running)
return Translations.bot_farmer_already_stopped;
#pragma warning disable format // @formatter:off
_ => Translations.bot_farmer_desc + ": " + commandDescription
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
running = false;
return Translations.bot_farmer_stopping;
}
private int OnCommandStop(CmdResult r)
{
if (!running)
{
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_farmer_already_stopped);
}
else
{
running = false;
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_farmer_stopping);
}
}
if (args[0].Equals("start", StringComparison.OrdinalIgnoreCase))
private int OnCommandStart(CmdResult r, CropType whatToFarm, string? otherArgs)
{
if (running)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_farmer_already_running);
int radius = 30;
state = State.SearchingForFarmlandToPlant;
cropType = whatToFarm;
allowUnsafe = false;
allowTeleport = false;
debugEnabled = false;
if (!string.IsNullOrWhiteSpace(otherArgs))
{
string[] args = otherArgs.ToLower().Split(' ', StringSplitOptions.TrimEntries);
foreach (string currentArg in args)
{
if (args.Length >= 2)
if (!currentArg.Contains(':'))
{
if (running)
return Translations.bot_farmer_already_running;
LogToConsole("§x§1§0" + string.Format(Translations.bot_farmer_warining_invalid_parameter, currentArg));
continue;
}
if (!Enum.TryParse(args[1], true, out CropType whatToFarm))
return Translations.bot_farmer_invalid_crop_type;
string[] parts = currentArg.Split(":", StringSplitOptions.TrimEntries);
int radius = 30;
if (parts.Length != 2)
{
LogToConsole("§x§1§0" + string.Format(Translations.bot_farmer_warining_invalid_parameter, currentArg));
continue;
}
state = State.SearchingForFarmlandToPlant;
cropType = whatToFarm;
allowUnsafe = false;
allowTeleport = false;
debugEnabled = false;
switch (parts[0])
{
case "r":
case "radius":
if (!int.TryParse(parts[1], NumberStyles.Any, CultureInfo.CurrentCulture, out radius))
LogToConsole("§x§1§0" + Translations.bot_farmer_invalid_radius);
if (args.Length >= 3)
{
for (int i = 2; i < args.Length; i++)
if (radius <= 0)
{
string currentArg = args[i].Trim().ToLower();
if (!currentArg.Contains(':'))
{
LogToConsole("§x§1§0" + string.Format(Translations.bot_farmer_warining_invalid_parameter, currentArg));
continue;
}
string[] parts = currentArg.Split(":", StringSplitOptions.TrimEntries);
if (parts.Length != 2)
{
LogToConsole("§x§1§0" + string.Format(Translations.bot_farmer_warining_invalid_parameter, currentArg));
continue;
}
switch (parts[0])
{
case "r":
case "radius":
if (!int.TryParse(parts[1], NumberStyles.Any, CultureInfo.CurrentCulture, out radius))
LogToConsole("§x§1§0" + Translations.bot_farmer_invalid_radius);
if (radius <= 0)
{
LogToConsole("§x§1§0" + Translations.bot_farmer_invalid_radius);
radius = 30;
}
break;
case "f":
case "unsafe":
if (allowUnsafe)
break;
if (parts[1].Equals("true") || parts[1].Equals("1"))
{
LogToConsole("§x§1§0" + Translations.bot_farmer_warining_force_unsafe);
allowUnsafe = true;
}
else allowUnsafe = false;
break;
case "t":
case "teleport":
if (allowTeleport)
break;
if (parts[1].Equals("true") || parts[1].Equals("1"))
{
LogToConsole("§w§1§f" + Translations.bot_farmer_warining_allow_teleport);
allowTeleport = true;
}
else allowTeleport = false;
break;
case "d":
case "debug":
if (debugEnabled)
break;
if (parts[1].Equals("true") || parts[1].Equals("1"))
{
LogToConsole("Debug enabled!");
debugEnabled = true;
}
else debugEnabled = false;
break;
}
LogToConsole("§x§1§0" + Translations.bot_farmer_invalid_radius);
radius = 30;
}
}
farmingRadius = radius;
running = true;
new Thread(() => MainPorcess()).Start();
break;
return "";
case "f":
case "unsafe":
if (allowUnsafe)
break;
if (parts[1].Equals("true") || parts[1].Equals("1"))
{
LogToConsole("§x§1§0" + Translations.bot_farmer_warining_force_unsafe);
allowUnsafe = true;
}
else allowUnsafe = false;
break;
case "t":
case "teleport":
if (allowTeleport)
break;
if (parts[1].Equals("true") || parts[1].Equals("1"))
{
LogToConsole("§w§1§f" + Translations.bot_farmer_warining_allow_teleport);
allowTeleport = true;
}
else allowTeleport = false;
break;
case "d":
case "debug":
if (debugEnabled)
break;
if (parts[1].Equals("true") || parts[1].Equals("1"))
{
LogToConsole("Debug enabled!");
debugEnabled = true;
}
else debugEnabled = false;
break;
}
}
}
return Translations.bot_farmer_desc + ": " + commandDescription;
farmingRadius = radius;
running = true;
new Thread(() => MainPorcess()).Start();
return r.SetAndReturn(CmdResult.Status.Done);
}
public override void AfterGameJoined()
@ -230,7 +261,7 @@ namespace MinecraftClient.ChatBots
if (AutoEat.Eating)
{
LogDebug("Eating...");
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -246,7 +277,7 @@ namespace MinecraftClient.ChatBots
{
LogDebug("No seeds, trying to find some crops to break");
state = State.SearchingForCropsToBreak;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -256,7 +287,7 @@ namespace MinecraftClient.ChatBots
{
LogDebug("Could not find any farmland, trying to find some crops to break");
state = State.SearchingForCropsToBreak;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -272,7 +303,7 @@ namespace MinecraftClient.ChatBots
{
LogDebug("Ran out of seeds, looking for crops to break...");
state = State.SearchingForCropsToBreak;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
}
@ -321,7 +352,7 @@ namespace MinecraftClient.ChatBots
{
LogToConsole("No crops to break, trying to bonemeal ungrown ones");
state = State.BonemealingCrops;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -367,7 +398,7 @@ namespace MinecraftClient.ChatBots
if (cropType == CropType.Netherwart)
{
state = State.SearchingForFarmlandToPlant;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -376,7 +407,7 @@ namespace MinecraftClient.ChatBots
{
LogDebug("No bonemeal, searching for some farmland to plant seeds on");
state = State.SearchingForFarmlandToPlant;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -386,7 +417,7 @@ namespace MinecraftClient.ChatBots
{
LogDebug("No crops to bonemeal, searching for farmland to plant seeds on");
state = State.SearchingForFarmlandToPlant;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
@ -402,7 +433,7 @@ namespace MinecraftClient.ChatBots
{
LogDebug("Ran out of Bone Meal, looking for farmland to plant on...");
state = State.SearchingForFarmlandToPlant;
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
Thread.Sleep(Delay_Between_Tasks_Millisecond);
continue;
}
}
@ -438,8 +469,8 @@ namespace MinecraftClient.ChatBots
break;
}
LogDebug("Waiting for " + Config.Delay_Between_Tasks + " seconds for next cycle.");
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
LogDebug(string.Format("Waiting for {0:0.00} seconds for next cycle.", Config.Delay_Between_Tasks));
Thread.Sleep(Delay_Between_Tasks_Millisecond);
}
LogToConsole(Translations.bot_farmer_stopped);
@ -815,6 +846,7 @@ namespace MinecraftClient.ChatBots
{
return GetPlayerInventory().SearchItem(itemType).Length > 0;
}
private void LogDebug(object text)
{
if (debugEnabled)

View file

@ -1,12 +1,19 @@
using System;
using System.Linq;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
public class FollowPlayer : ChatBot
{
public const string CommandName = "follow";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -37,7 +44,7 @@ namespace MinecraftClient.ChatBots
private int _updateCounter = 0;
private bool _unsafeEnabled = false;
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!GetEntityHandlingEnabled())
{
@ -55,58 +62,85 @@ namespace MinecraftClient.ChatBots
return;
}
RegisterChatBotCommand("follow", "cmd.follow.desc", "follow <player name|stop>", OnFollowCommand);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("start")
.Then(l => l.Argument("PlayerName", MccArguments.PlayerName())
.Executes(r => OnCommandStart(r.Source, Arguments.GetString(r, "PlayerName"), takeRisk: false))
.Then(l => l.Literal("-f")
.Executes(r => OnCommandStart(r.Source, Arguments.GetString(r, "PlayerName"), takeRisk: true)))))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandStop(r.Source)))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
private string OnFollowCommand(string cmd, string[] args)
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
if (args.Length > 0)
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
if (args[0].Equals("stop", StringComparison.OrdinalIgnoreCase))
{
if (_playerToFollow == null)
return Translations.cmd_follow_already_stopped;
#pragma warning disable format // @formatter:off
_ => Translations.cmd_follow_desc + ": " + Translations.cmd_follow_usage
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
_playerToFollow = null;
return Translations.cmd_follow_stopping;
}
else
{
if (!IsValidName(args[0]))
return Translations.cmd_follow_invalid_name;
private int OnCommandStart(CmdResult r, string name, bool takeRisk)
{
if (!IsValidName(name))
return r.SetAndReturn(CmdResult.Status.Fail, Translations.cmd_follow_invalid_name);
Entity? player = GetEntities().Values.ToList().Find(entity =>
entity.Type == EntityType.Player && !string.IsNullOrEmpty(entity.Name) && entity.Name.Equals(args[0], StringComparison.OrdinalIgnoreCase));
Entity? player = GetEntities().Values.ToList().Find(entity =>
entity.Type == EntityType.Player
&& !string.IsNullOrEmpty(entity.Name)
&& entity.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (player == null)
return Translations.cmd_follow_invalid_player;
if (player == null)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.cmd_follow_invalid_player);
if (!CanMoveThere(player.Location))
return Translations.cmd_follow_cant_reach_player;
if (!CanMoveThere(player.Location))
return r.SetAndReturn(CmdResult.Status.Fail, Translations.cmd_follow_cant_reach_player);
if (_playerToFollow != null && _playerToFollow.Equals(args[0], StringComparison.OrdinalIgnoreCase))
return string.Format(Translations.cmd_follow_already_following, _playerToFollow);
if (_playerToFollow != null && _playerToFollow.Equals(name, StringComparison.OrdinalIgnoreCase))
return r.SetAndReturn(CmdResult.Status.Fail, string.Format(Translations.cmd_follow_already_following, _playerToFollow));
string result;
if (_playerToFollow != null)
result = string.Format(Translations.cmd_follow_switched, player.Name!);
else
result = string.Format(Translations.cmd_follow_started, player.Name!);
_playerToFollow = args[0].Trim().ToLower();
string result;
if (_playerToFollow != null)
result = string.Format(Translations.cmd_follow_switched, player.Name!);
else
result = string.Format(Translations.cmd_follow_started, player.Name!);
_playerToFollow = name.ToLower();
LogToConsole(Translations.cmd_follow_note);
if (args.Length == 2 && args[1].Equals("-f", StringComparison.OrdinalIgnoreCase))
{
_unsafeEnabled = true;
LogToConsole(Translations.cmd_follow_unsafe_enabled);
}
return result;
}
if (takeRisk)
{
_unsafeEnabled = true;
return r.SetAndReturn(CmdResult.Status.Done, Translations.cmd_follow_note + '\n' + Translations.cmd_follow_unsafe_enabled);
}
else
return r.SetAndReturn(CmdResult.Status.Done, Translations.cmd_follow_note);
}
return Translations.cmd_follow_desc + ": " + Translations.cmd_follow_usage;
private int OnCommandStop(CmdResult r)
{
if (_playerToFollow == null)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.cmd_follow_already_stopped);
_playerToFollow = null;
return r.SetAndReturn(CmdResult.Status.Done, Translations.cmd_follow_stopping);
}
public override void Update()

View file

@ -1,5 +1,6 @@
using System;
using System.Text;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots

View file

@ -3,6 +3,11 @@ using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -12,6 +17,8 @@ namespace MinecraftClient.ChatBots
/// </summary>
public class Mailer : ChatBot
{
public const string CommandName = "mailer";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -216,7 +223,7 @@ namespace MinecraftClient.ChatBots
/// <summary>
/// Initialization of the Mailer bot
/// </summary>
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
LogDebugToConsole(Translations.bot_mailer_init);
LogDebugToConsole(Translations.bot_mailer_init_db + Config.DatabaseFile);
@ -251,7 +258,123 @@ namespace MinecraftClient.ChatBots
mailDbFileMonitor = new FileMonitor(Path.GetDirectoryName(Config.DatabaseFile)!, Path.GetFileName(Config.DatabaseFile), FileMonitorCallback);
ignoreListFileMonitor = new FileMonitor(Path.GetDirectoryName(Config.IgnoreListFile)!, Path.GetFileName(Config.IgnoreListFile), FileMonitorCallback);
RegisterChatBotCommand("mailer", Translations.bot_mailer_cmd, "mailer <getmails|addignored|getignored|removeignored>", ProcessInternalCommand);
dispatcher.Register(l =>
l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(string.Empty))
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp(string.Empty)))
)
);
dispatcher.Register(l =>
l.Literal(CommandName)
.Executes(r => OnCommandHelp(string.Empty))
.Then(l => l.Literal("getmails")
.Executes(r => OnCommandGetMails())
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp("getmails")))
)
.Then(l => l.Literal("getignored")
.Executes(r => OnCommandGetIgnored())
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp("getignored")))
)
.Then(l => l.Literal("addignored")
.Executes(r => OnCommandHelp("addignored"))
.Then(l => l.Argument("username", Arguments.String())
.Executes(r => OnCommandAddIgnored(Arguments.GetString(r, "username")))
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp("addignored")))
)
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp("addignored")))
)
.Then(l => l.Literal("removeignored")
.Executes(r => OnCommandHelp("removeignored"))
.Then(l => l.Argument("username", Arguments.String())
.Executes(r => OnCommandRemoveIgnored(Arguments.GetString(r, "username")))
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp("removeignored")))
)
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp("removeignored")))
)
.Then(l => l.Literal("_help")
.Executes(r => OnCommandHelp(string.Empty))
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName))
)
.Then(l => l.Argument("any", Arguments.GreedyString()).Executes(r => OnCommandHelp(string.Empty)))
);
}
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(string cmd)
{
LogToConsole(cmd switch
{
#pragma warning disable format // @formatter:off
_ => Translations.bot_mailer_cmd_help + ": /mailer <getmails|addignored|getignored|removeignored>"
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
return 1;
}
private int OnCommandGetMails()
{
LogToConsole(string.Format(Translations.bot_mailer_cmd_getmails, string.Join("\n", mailDatabase)));
return 1;
}
private int OnCommandGetIgnored()
{
LogToConsole(string.Format(Translations.bot_mailer_cmd_getignored, string.Join("\n", ignoreList)));
return 1;
}
private int OnCommandAddIgnored(string username)
{
if (IsValidName(username))
{
username = username.ToLower();
lock (readWriteLock)
{
if (!ignoreList.Contains(username))
{
ignoreList.Add(username);
ignoreList.SaveToFile(Config.IgnoreListFile);
}
}
LogToConsole(string.Format(Translations.bot_mailer_cmd_ignore_added, username));
return 1;
}
else
{
LogToConsole(string.Format(Translations.bot_mailer_cmd_ignore_invalid, "addignored"));
return 0;
}
}
private int OnCommandRemoveIgnored(string username)
{
if (IsValidName(username))
{
username = username.ToLower();
lock (readWriteLock)
{
if (ignoreList.Contains(username))
{
ignoreList.Remove(username);
ignoreList.SaveToFile(Config.IgnoreListFile);
}
}
LogToConsole(string.Format(Translations.bot_mailer_cmd_ignore_removed, username));
return 1;
}
else
{
LogToConsole(string.Format(Translations.bot_mailer_cmd_ignore_invalid, "removeignored"));
return 0;
}
}
/// <summary>
@ -365,57 +488,5 @@ namespace MinecraftClient.ChatBots
ignoreList = IgnoreList.FromFile(Config.IgnoreListFile);
}
}
/// <summary>
/// Interprets local commands.
/// </summary>
private string ProcessInternalCommand(string cmd, string[] args)
{
if (args.Length > 0)
{
string commandName = args[0].ToLower();
switch (commandName)
{
case "getmails": // Sorry, I (ReinforceZwei) replaced "=" to "-" because it would affect the parsing of translation file (key=value)
return string.Format(Translations.bot_mailer_cmd_getmails, string.Join("\n", mailDatabase));
case "getignored":
return string.Format(Translations.bot_mailer_cmd_getignored, string.Join("\n", ignoreList));
case "addignored":
case "removeignored":
if (args.Length > 1 && IsValidName(args[1]))
{
string username = args[1].ToLower();
if (commandName == "addignored")
{
lock (readWriteLock)
{
if (!ignoreList.Contains(username))
{
ignoreList.Add(username);
ignoreList.SaveToFile(Config.IgnoreListFile);
}
}
return string.Format(Translations.bot_mailer_cmd_ignore_added, args[1]);
}
else
{
lock (readWriteLock)
{
if (ignoreList.Contains(username))
{
ignoreList.Remove(username);
ignoreList.SaveToFile(Config.IgnoreListFile);
}
}
return string.Format(Translations.bot_mailer_cmd_ignore_removed, args[1]);
}
}
else return string.Format(Translations.bot_mailer_cmd_ignore_invalid, commandName);
}
}
return Translations.bot_mailer_cmd_help + ": /help mailer";
}
}
}

View file

@ -1,18 +1,24 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Brigadier.NET;
using Brigadier.NET.Builder;
using ImageMagick;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Mapping;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
{
public class Map : ChatBot
{
public const string CommandName = "maps";
public static Configs Config = new();
public struct QueuedMap
@ -63,25 +69,89 @@ namespace MinecraftClient.ChatBots
private readonly string baseDirectory = @"Rendered_Maps";
private readonly Dictionary<int, McMap> cachedMaps = new();
internal readonly Dictionary<int, McMap> cachedMaps = new();
private readonly Queue<QueuedMap> discordQueue = new();
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
if (!Directory.Exists(baseDirectory))
Directory.CreateDirectory(baseDirectory);
DeleteRenderedMaps();
RegisterChatBotCommand("maps", "bot.map.cmd.desc", "maps list|render <id> or maps l|r <id>", OnMapCommand);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Executes(r => OnCommandList(r.Source))
.Then(l => l.Literal("list")
.Executes(r => OnCommandList(r.Source)))
.Then(l => l.Literal("render")
.Then(l => l.Argument("MapID", MccArguments.MapBotMapId())
.Executes(r => OnCommandRender(r.Source, Arguments.GetInteger(r, "MapID")))))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
public override void OnUnload()
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
DeleteRenderedMaps();
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
_ => Translations.error_usage + ": /maps <list/render <id>>"
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
private int OnCommandList(CmdResult r)
{
if (cachedMaps.Count == 0)
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_map_no_maps);
LogToConsole(Translations.bot_map_received);
foreach (var (key, value) in new SortedDictionary<int, McMap>(cachedMaps))
LogToConsole(string.Format(Translations.bot_map_list_item, key, value.LastUpdated));
return r.SetAndReturn(CmdResult.Status.Done);
}
private int OnCommandRender(CmdResult r, int mapId)
{
if (!cachedMaps.ContainsKey(mapId))
return r.SetAndReturn(CmdResult.Status.Fail, string.Format(Translations.bot_map_cmd_not_found, mapId));
try
{
McMap map = cachedMaps[mapId];
if (Config.Save_To_File)
SaveToFile(map);
if (Config.Render_In_Console)
RenderInConsole(map);
return r.SetAndReturn(CmdResult.Status.Done);
}
catch (Exception e)
{
LogDebugToConsole(e.StackTrace!);
return r.SetAndReturn(CmdResult.Status.Fail, string.Format(Translations.bot_map_failed_to_render, mapId));
}
}
private void DeleteRenderedMaps()
{
if (Config.Delete_All_On_Unload)
@ -94,56 +164,6 @@ namespace MinecraftClient.ChatBots
}
}
public string OnMapCommand(string command, string[] args)
{
if (args.Length == 0 || (args.Length == 1 && (args[0].ToLower().Equals("list") || args[0].ToLower().Equals("l"))))
{
if (cachedMaps.Count == 0)
return Translations.bot_map_no_maps;
LogToConsole(Translations.bot_map_received);
foreach (var (key, value) in new SortedDictionary<int, McMap>(cachedMaps))
LogToConsole(string.Format(Translations.bot_map_list_item, key, value.LastUpdated));
return "";
}
if (args.Length > 1)
{
if (args[0].ToLower().Equals("render") || args[0].ToLower().Equals("r"))
{
if (args.Length < 2)
return "maps <list/render <id>> | maps <l/r <id>>";
if (int.TryParse(args[1], NumberStyles.Any, CultureInfo.CurrentCulture, out int mapId))
{
if (!cachedMaps.ContainsKey(mapId))
return string.Format(Translations.bot_map_cmd_not_found, mapId);
try
{
McMap map = cachedMaps[mapId];
if (Config.Save_To_File)
SaveToFile(map);
if (Config.Render_In_Console)
RenderInConsole(map);
return "";
}
catch (Exception e)
{
LogDebugToConsole(e.StackTrace!);
return string.Format(Translations.bot_map_failed_to_render, mapId);
}
}
return Translations.bot_map_cmd_invalid_id;
}
}
return "";
}
public override void OnMapData(int mapid, byte scale, bool trackingPosition, bool locked, List<MapIcon> icons, byte columnsUpdated, byte rowsUpdated, byte mapCoulmnX, byte mapRowZ, byte[]? colors)
{
if (columnsUpdated == 0 && cachedMaps.ContainsKey(mapid))
@ -320,7 +340,7 @@ namespace MinecraftClient.ChatBots
}
}
private void RenderInConsole(McMap map)
private static void RenderInConsole(McMap map)
{
StringBuilder sb = new();
@ -406,7 +426,7 @@ namespace MinecraftClient.ChatBots
public DateTime LastUpdated { get; set; }
}
class MapColors
internal class MapColors
{
// When colors are updated in a new update, you can get them using the game code: net\minecraft\world\level\material\MaterialColor.java
public static Dictionary<byte, byte[]> Colors = new()

View file

@ -1,5 +1,6 @@
using System;
using System.Text;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots

View file

@ -1,4 +1,6 @@
using System;
using MinecraftClient.CommandHandler;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -32,17 +34,9 @@ namespace MinecraftClient.ChatBots
string command = "", sender = "";
if (IsPrivateMessage(text, ref command, ref sender) && Settings.Config.Main.Advanced.BotOwners.Contains(sender.ToLower().Trim()))
{
string? response = "";
CmdResult response = new();
PerformInternalCommand(command, ref response);
response = GetVerbatim(response);
foreach (char disallowedChar in McClient.GetDisallowedChatCharacters())
{
response = response.Replace(disallowedChar.ToString(), String.Empty);
}
if (response.Length > 0)
{
SendPrivateMessage(sender, response);
}
SendPrivateMessage(sender, response.ToString());
}
else if (Config.AutoTpaccept
&& IsTeleportRequest(text, ref sender)

View file

@ -1,6 +1,11 @@
using System;
using System.Collections.Generic;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Protocol;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
namespace MinecraftClient.ChatBots
@ -10,6 +15,8 @@ namespace MinecraftClient.ChatBots
/// </summary>
public class ReplayCapture : ChatBot
{
public const string CommandName = "replay";
public static Configs Config = new();
[TomlDoNotInlineObject]
@ -33,14 +40,80 @@ namespace MinecraftClient.ChatBots
private ReplayHandler? replay;
private int backupCounter = -1;
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
SetNetworkPacketEventEnabled(true);
replay = new ReplayHandler(GetProtocolVersion());
replay.MetaData.serverName = GetServerHost() + GetServerPort();
backupCounter = Settings.DoubleToTick(Config.Backup_Interval);
RegisterChatBotCommand("replay", Translations.bot_replayCapture_cmd, "replay <save|stop>", Command);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("save")
.Executes(r => OnCommandSave(r.Source)))
.Then(l => l.Literal("stop")
.Executes(r => OnCommandStop(r.Source)))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
}
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
}
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
_ => string.Format(Translations.general_available_cmd, "save, stop")
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
private int OnCommandSave(CmdResult r)
{
try
{
if (replay!.RecordRunning)
{
replay.CreateBackupReplay(@"replay_recordings\" + replay.GetReplayDefaultName());
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_replayCapture_created);
}
else
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_replayCapture_restart);
}
catch (Exception e)
{
return r.SetAndReturn(CmdResult.Status.Fail, e.Message);
}
}
private int OnCommandStop(CmdResult r)
{
try
{
if (replay!.RecordRunning)
{
replay.OnShutDown();
return r.SetAndReturn(CmdResult.Status.Done, Translations.bot_replayCapture_stopped);
}
else
return r.SetAndReturn(CmdResult.Status.Fail, Translations.bot_replayCapture_restart);
}
catch (Exception e)
{
return r.SetAndReturn(CmdResult.Status.Fail, e.Message);
}
}
public override void OnNetworkPacket(int packetID, List<byte> packetData, bool isLogin, bool isInbound)
@ -66,37 +139,5 @@ namespace MinecraftClient.ChatBots
replay!.OnShutDown();
return base.OnDisconnect(reason, message);
}
public string Command(string cmd, string[] args)
{
try
{
if (replay!.RecordRunning)
{
if (args.Length > 0)
{
switch (args[0].ToLower())
{
case "save":
{
replay.CreateBackupReplay(@"replay_recordings\" + replay.GetReplayDefaultName());
return Translations.bot_replayCapture_created;
}
case "stop":
{
replay.OnShutDown();
return Translations.bot_replayCapture_stopped;
}
}
}
return string.Format(Translations.general_available_cmd, "save, stop");
}
else return Translations.bot_replayCapture_restart;
}
catch (Exception e)
{
return e.Message;
}
}
}
}

View file

@ -5,6 +5,9 @@ using System.IO;
using System.Reflection;
using System.Text;
using System.Threading;
using Brigadier.NET;
using MinecraftClient.CommandHandler;
using MinecraftClient.Scripting;
namespace MinecraftClient.ChatBots
{
@ -124,7 +127,7 @@ namespace MinecraftClient.ChatBots
return false;
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
//Load the given file from the startup parameters
if (LookForScript(ref file!))

View file

@ -1,4 +1,5 @@
using System;
using MinecraftClient.Scripting;
using Tomlet.Attributes;
using static MinecraftClient.ChatBots.ScriptScheduler.Configs;

View file

@ -3,6 +3,11 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Brigadier.NET;
using Brigadier.NET.Builder;
using MinecraftClient.CommandHandler;
using MinecraftClient.CommandHandler.Patch;
using MinecraftClient.Scripting;
using Telegram.Bot;
using Telegram.Bot.Exceptions;
using Telegram.Bot.Polling;
@ -16,6 +21,8 @@ namespace MinecraftClient.ChatBots
{
public class TelegramBridge : ChatBot
{
public const string CommandName = "tgbridge";
private enum BridgeDirection
{
Both = 0,
@ -68,19 +75,74 @@ namespace MinecraftClient.ChatBots
instance = this;
}
public override void Initialize()
public override void Initialize(CommandDispatcher<CmdResult> dispatcher)
{
RegisterChatBotCommand("tgbridge", "bot.TelegramBridge.desc", "tgbridge direction <both|mc|telegram>", OnTgCommand);
dispatcher.Register(l => l.Literal("help")
.Then(l => l.Literal(CommandName)
.Executes(r => OnCommandHelp(r.Source, string.Empty))
)
);
dispatcher.Register(l => l.Literal(CommandName)
.Then(l => l.Literal("direction")
.Then(l => l.Literal("both")
.Executes(r => OnCommandDirection(r.Source, BridgeDirection.Both)))
.Then(l => l.Literal("mc")
.Executes(r => OnCommandDirection(r.Source, BridgeDirection.Minecraft)))
.Then(l => l.Literal("telegram")
.Executes(r => OnCommandDirection(r.Source, BridgeDirection.Telegram))))
.Then(l => l.Literal("_help")
.Redirect(dispatcher.GetRoot().GetChild("help").GetChild(CommandName)))
);
Task.Run(async () => await MainAsync());
}
~TelegramBridge()
public override void OnUnload(CommandDispatcher<CmdResult> dispatcher)
{
dispatcher.Unregister(CommandName);
dispatcher.GetRoot().GetChild("help").RemoveChild(CommandName);
Disconnect();
}
public override void OnUnload()
private int OnCommandHelp(CmdResult r, string? cmd)
{
return r.SetAndReturn(cmd switch
{
#pragma warning disable format // @formatter:off
_ => Translations.error_usage + ": /tgbridge direction <both|mc|telegram>"
+ '\n' + McClient.dispatcher.GetAllUsageString(CommandName, false),
#pragma warning restore format // @formatter:on
});
}
private int OnCommandDirection(CmdResult r, BridgeDirection direction)
{
string bridgeName;
switch (direction)
{
case BridgeDirection.Both:
bridgeName = Translations.bot_TelegramBridge_direction_both;
bridgeDirection = BridgeDirection.Both;
break;
case BridgeDirection.Minecraft:
bridgeName = Translations.bot_TelegramBridge_direction_minecraft;
bridgeDirection = BridgeDirection.Minecraft;
break;
case BridgeDirection.Telegram:
bridgeName = Translations.bot_TelegramBridge_direction_Telegram;
bridgeDirection = BridgeDirection.Telegram;
break;
default:
goto case BridgeDirection.Both;
}
return r.SetAndReturn(CmdResult.Status.Done, string.Format(Translations.bot_TelegramBridge_direction, bridgeName));
}
~TelegramBridge()
{
Disconnect();
}
@ -110,47 +172,6 @@ namespace MinecraftClient.ChatBots
return instance;
}
private string OnTgCommand(string cmd, string[] args)
{
if (args.Length == 2)
{
if (args[0].ToLower().Equals("direction"))
{
string direction = args[1].ToLower().Trim();
string bridgeName;
switch (direction)
{
case "b":
case "both":
bridgeName = Translations.bot_TelegramBridge_direction_both;
bridgeDirection = BridgeDirection.Both;
break;
case "mc":
case "minecraft":
bridgeName = Translations.bot_TelegramBridge_direction_minecraft;
bridgeDirection = BridgeDirection.Minecraft;
break;
case "t":
case "tg":
case "telegram":
bridgeName = Translations.bot_TelegramBridge_direction_Telegram;
bridgeDirection = BridgeDirection.Telegram;
break;
default:
return Translations.bot_TelegramBridge_invalid_direction;
}
return string.Format(Translations.bot_TelegramBridge_direction, bridgeName);
};
}
return "dscbridge direction <both|mc|discord>";
}
public override void GetText(string text)
{
if (!CanSendMessages())
@ -324,9 +345,8 @@ namespace MinecraftClient.ChatBots
{
var command = text[1..];
string? result = "";
CmdResult result = new();
PerformInternalCommand(command, ref result);
result = string.IsNullOrEmpty(result) ? "-" : result;
await botClient.SendTextMessageAsync(
chatId: chatId,

View file

@ -1,4 +1,6 @@
namespace MinecraftClient.ChatBots
using MinecraftClient.Scripting;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// Example of message receiving.