mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Added Farmer Bot. Fixed a bug in the configuration. Moved Reload and Bots command to the Commands folder.
This commit is contained in:
parent
77500deef2
commit
6524fe1734
6 changed files with 208 additions and 59 deletions
|
|
@ -1,74 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace MinecraftClient.Commands
|
||||
{
|
||||
class BotsCommand : Command
|
||||
{
|
||||
public override string CmdName { get { return "bots"; } }
|
||||
public override string CmdUsage { get { return "bots [list|unload <bot name|all>]"; } }
|
||||
public override string CmdDesc { get { return "cmd.bots.desc"; } }
|
||||
|
||||
public override string Run(McClient handler, string command, Dictionary<string, object>? localVars)
|
||||
{
|
||||
if (HasArg(command))
|
||||
{
|
||||
string[] args = GetArgs(command);
|
||||
|
||||
if (args.Length == 1)
|
||||
{
|
||||
if (args[0].Equals("list", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
StringBuilder sb = new();
|
||||
|
||||
int length = handler.GetLoadedChatBots().Count;
|
||||
|
||||
if (length == 0)
|
||||
return Translations.TryGet("cmd.bots.noloaded");
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
sb.Append(handler.GetLoadedChatBots()[i].GetType().Name);
|
||||
|
||||
if (i != length - 1)
|
||||
sb.Append(" ,");
|
||||
|
||||
}
|
||||
|
||||
return Translations.Get("cmd.bots.list") + ": " + sb.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
else if (args.Length == 2)
|
||||
{
|
||||
if (args[0].Equals("unload", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
string botName = args[1].Trim();
|
||||
|
||||
if (botName.ToLower().Equals("all", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (handler.GetLoadedChatBots().Count == 0)
|
||||
return Translations.TryGet("cmd.bots.noloaded");
|
||||
|
||||
handler.UnloadAllBots();
|
||||
return Translations.TryGet("cmd.bots.unloaded_all");
|
||||
}
|
||||
else
|
||||
{
|
||||
ChatBot? bot = handler.GetLoadedChatBots().Find(bot => bot.GetType().Name.ToLower() == botName.ToLower());
|
||||
|
||||
if (bot == null)
|
||||
return Translations.TryGet("cmd.bots.notfound", botName);
|
||||
|
||||
handler.BotUnLoad(bot);
|
||||
return Translations.TryGet("cmd.bots.unloaded", botName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GetCmdDescTranslated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -42,6 +42,7 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
public bool Enabled = false;
|
||||
|
||||
[TomlInlineComment("$config.ChatBot.Farmer.Delay_Between_Tasks$")]
|
||||
public int Delay_Between_Tasks = 1;
|
||||
|
||||
public void OnSettingUpdate()
|
||||
|
|
@ -55,12 +56,17 @@ namespace MinecraftClient.ChatBots
|
|||
private CropType cropType = CropType.Wheat;
|
||||
private int farmingRadius = 30;
|
||||
private bool running = false;
|
||||
private bool allowUnsafe = false;
|
||||
private bool allowTeleport = false;
|
||||
private bool debugEnabled = false;
|
||||
|
||||
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()
|
||||
{
|
||||
if (GetProtocolVersion() < Protocol18Handler.MC_1_13_Version)
|
||||
{
|
||||
LogToConsole("Not implemented bellow 1.13!");
|
||||
LogToConsole(Translations.TryGet("bot.farmer.not_implemented"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -76,7 +82,7 @@ namespace MinecraftClient.ChatBots
|
|||
return;
|
||||
}
|
||||
|
||||
RegisterChatBotCommand("farmer", "cmd.farmer.desc", "farmer <start <crop type> <radius>|stop>", OnFarmCommand);
|
||||
RegisterChatBotCommand("farmer", "bot.farmer.desc", commandDescription, OnFarmCommand);
|
||||
}
|
||||
|
||||
private string OnFarmCommand(string cmd, string[] args)
|
||||
|
|
@ -86,38 +92,120 @@ namespace MinecraftClient.ChatBots
|
|||
if (args[0].Equals("stop", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!running)
|
||||
return Translations.TryGet("cmd.farmer.already_stopped");
|
||||
return Translations.TryGet("bot.farmer.already_stopped");
|
||||
|
||||
running = false;
|
||||
return Translations.TryGet("cmd.farmer.stopping");
|
||||
return Translations.TryGet("bot.farmer.stopping");
|
||||
}
|
||||
|
||||
if (args[0].Equals("start", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (args.Length == 3)
|
||||
if (args.Length >= 2)
|
||||
{
|
||||
if (running)
|
||||
return Translations.TryGet("cmd.farmer.already_running");
|
||||
return Translations.TryGet("bot.farmer.already_running");
|
||||
|
||||
if (!Enum.TryParse(args[1], true, out CropType whatToFarm))
|
||||
return Translations.TryGet("cmd.farmer.invalid_crop_type");
|
||||
return Translations.TryGet("bot.farmer.invalid_crop_type");
|
||||
|
||||
if (!int.TryParse(args[2], NumberStyles.Any, CultureInfo.CurrentCulture, out int radius))
|
||||
return Translations.TryGet("cmd.farmer.invalid_radius");
|
||||
int radius = 30;
|
||||
|
||||
state = State.SearchingForFarmlandToPlant;
|
||||
cropType = whatToFarm;
|
||||
farmingRadius = radius <= 0 ? 30 : radius;
|
||||
allowUnsafe = false;
|
||||
allowTeleport = false;
|
||||
debugEnabled = false;
|
||||
|
||||
if (args.Length >= 3)
|
||||
{
|
||||
for (int i = 2; i < args.Length; i++)
|
||||
{
|
||||
string currentArg = args[i].Trim().ToLower();
|
||||
|
||||
if (!currentArg.Contains(':'))
|
||||
{
|
||||
LogToConsole("§x§1§0" + Translations.TryGet("bot.farmer.warining_invalid_parameter", currentArg));
|
||||
continue;
|
||||
}
|
||||
|
||||
string[] parts = currentArg.Split(":", StringSplitOptions.TrimEntries);
|
||||
|
||||
if (parts.Length != 2)
|
||||
{
|
||||
LogToConsole("§x§1§0" + Translations.TryGet("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.TryGet("bot.farmer.invalid_radius"));
|
||||
|
||||
if (radius <= 0)
|
||||
{
|
||||
LogToConsole("§x§1§0" + Translations.TryGet("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.TryGet("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.TryGet("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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
farmingRadius = radius;
|
||||
running = true;
|
||||
new Thread(() => MainPorcess()).Start();
|
||||
|
||||
return Translations.TryGet("cmd.farmer.staring", args[1], farmingRadius);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Translations.TryGet("cmd.farmer.desc") + ": " + Translations.TryGet("cmd.farmer.usage");
|
||||
return Translations.TryGet("bot.farmer.desc") + ": " + commandDescription;
|
||||
}
|
||||
|
||||
public override void AfterGameJoined()
|
||||
|
|
@ -133,14 +221,16 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
private void MainPorcess()
|
||||
{
|
||||
LogToConsole("Started");
|
||||
LogToConsole("§y§1§f" + Translations.TryGet("bot.farmer.started"));
|
||||
LogToConsole("§y§1§f " + Translations.TryGet("bot.farmer.crop_type") + ": " + cropType);
|
||||
LogToConsole("§y§1§f " + Translations.TryGet("bot.farmer.radius") + ": " + farmingRadius);
|
||||
|
||||
while (running)
|
||||
{
|
||||
// Don't do anything if the bot is currently eating, we wait for 1 second
|
||||
if (AutoEat.Eating)
|
||||
{
|
||||
LogToConsole("Eating.");
|
||||
LogDebug("Eating...");
|
||||
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -148,12 +238,14 @@ namespace MinecraftClient.ChatBots
|
|||
switch (state)
|
||||
{
|
||||
case State.SearchingForFarmlandToPlant:
|
||||
LogToConsole("Looking for farmland");
|
||||
LogDebug("Looking for farmland...");
|
||||
|
||||
ItemType cropTypeToPlant = GetSeedItemTypeForCropType(cropType);
|
||||
|
||||
// If we don't have any seeds on our hotbar, skip this step and try collecting some
|
||||
if (!SwitchToItem(GetSeedItemTypeForCropType(cropType)))
|
||||
if (!SwitchToItem(cropTypeToPlant))
|
||||
{
|
||||
LogToConsole("No seeds, trying to find some crops to break");
|
||||
LogDebug("No seeds, trying to find some crops to break");
|
||||
state = State.SearchingForCropsToBreak;
|
||||
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
|
||||
continue;
|
||||
|
|
@ -163,7 +255,7 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
if (farmlandToPlantOn.Count == 0)
|
||||
{
|
||||
LogToConsole("Could not find any farmland, trying to find some crops to break");
|
||||
LogDebug("Could not find any farmland, trying to find some crops to break");
|
||||
state = State.SearchingForCropsToBreak;
|
||||
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
|
||||
continue;
|
||||
|
|
@ -175,40 +267,39 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
double yValue = Math.Floor(location.Y) + 1;
|
||||
|
||||
if (cropType == CropType.Netherwart)
|
||||
yValue = (double)(Math.Floor(location.Y) - 1.0) + (double)0.87500;
|
||||
// TODO: Figure out why this is not working.
|
||||
// Why we need this: sometimes the server kicks the player for "invalid movement" packets.
|
||||
/*if (cropType == CropType.Netherwart)
|
||||
yValue = (double)(Math.Floor(location.Y) - 1.0) + (double)0.87500;*/
|
||||
|
||||
Location location2 = new Location(Math.Floor(location.X), yValue, Math.Floor(location.Z));
|
||||
Location location2 = new Location(Math.Floor(location.X) + 0.5, yValue, Math.Floor(location.Z) + 0.5);
|
||||
|
||||
if (WaitForMoveToLocation(location2))
|
||||
{
|
||||
LogToConsole("Moving to: " + location2);
|
||||
LogDebug("Moving to: " + location2);
|
||||
|
||||
// Stop if we do not have any more seeds left
|
||||
if (!SwitchToItem(GetSeedItemTypeForCropType(cropType)))
|
||||
{
|
||||
LogToConsole("No seeds, trying to find some crops to break");
|
||||
LogDebug("No seeds, trying to find some crops to break");
|
||||
break;
|
||||
}
|
||||
|
||||
Location loc = new Location(Math.Floor(location.X), Math.Floor(location2.Y), Math.Floor(location.Z));
|
||||
LogToConsole("Sending placeblock to: " + loc);
|
||||
LogDebug("Sending placeblock to: " + loc);
|
||||
|
||||
SendPlaceBlock(loc, Direction.Up);
|
||||
Thread.Sleep(300);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogToConsole("Can't move to: " + location2);
|
||||
}
|
||||
else LogDebug("Can't move to: " + location2);
|
||||
}
|
||||
|
||||
LogToConsole("Finished planting");
|
||||
LogDebug("Finished planting crops!");
|
||||
state = State.SearchingForCropsToBreak;
|
||||
break;
|
||||
|
||||
case State.SearchingForCropsToBreak:
|
||||
LogToConsole("Searching for crops to break");
|
||||
LogDebug("Searching for crops to break...");
|
||||
|
||||
List<Location> cropsToCollect = findCrops(farmingRadius, cropType, true);
|
||||
|
||||
|
|
@ -220,13 +311,31 @@ namespace MinecraftClient.ChatBots
|
|||
continue;
|
||||
}
|
||||
|
||||
// Switch to an axe for faster breaking if the bot has one in his inventory
|
||||
if (cropType == CropType.Melon || cropType == CropType.Pumpkin)
|
||||
{
|
||||
// Start from Diamond axe, if not found, try a tier lower axe
|
||||
bool switched = SwitchToItem(ItemType.DiamondAxe);
|
||||
|
||||
if (!switched)
|
||||
switched = SwitchToItem(ItemType.IronAxe);
|
||||
|
||||
if (!switched)
|
||||
switched = SwitchToItem(ItemType.GoldenAxe);
|
||||
|
||||
if (!switched)
|
||||
SwitchToItem(ItemType.StoneAxe);
|
||||
}
|
||||
|
||||
foreach (Location location in cropsToCollect)
|
||||
{
|
||||
if (!running) break;
|
||||
|
||||
// God damn C# rounding Y to (Y - 1) + 0.94
|
||||
// God damn C# rounding it to 0.94
|
||||
// This will be needed when bot bonemeals carrots or potatoes which are at the first stage of growth,
|
||||
// because sometimes the bot walks over crops and breaks them
|
||||
// TODO: Figure out a fix
|
||||
// new Location(Math.Floor(location.X) + 0.5, (double)((double)(location.Y - 1) + (double)0.93750), Math.Floor(location.Z) + 0.5)
|
||||
// new Location(Math.Floor(location.X) + 0.5, (double)((location.Y - 1) + (double)0.93750), Math.Floor(location.Z) + 0.5)
|
||||
|
||||
if (WaitForMoveToLocation(location))
|
||||
WaitForDigBlock(location);
|
||||
|
|
@ -235,7 +344,7 @@ namespace MinecraftClient.ChatBots
|
|||
Thread.Sleep(cropType == CropType.Melon || cropType == CropType.Pumpkin ? 400 : 200);
|
||||
}
|
||||
|
||||
LogToConsole("Finished breaking crops");
|
||||
LogDebug("Finished breaking crops!");
|
||||
state = State.BonemealingCrops;
|
||||
break;
|
||||
|
||||
|
|
@ -251,7 +360,7 @@ namespace MinecraftClient.ChatBots
|
|||
// If we don't have any bonemeal on our hotbar, skip this step
|
||||
if (!SwitchToItem(ItemType.BoneMeal))
|
||||
{
|
||||
LogToConsole("No bonemeal, searching for some farmland to plant seeds on");
|
||||
LogDebug("No bonemeal, searching for some farmland to plant seeds on");
|
||||
state = State.SearchingForFarmlandToPlant;
|
||||
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
|
||||
continue;
|
||||
|
|
@ -261,7 +370,7 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
if (cropsToBonemeal.Count == 0)
|
||||
{
|
||||
LogToConsole("No crops to bonemeal, searching for farmland to plant seeds on");
|
||||
LogDebug("No crops to bonemeal, searching for farmland to plant seeds on");
|
||||
state = State.SearchingForFarmlandToPlant;
|
||||
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
|
||||
continue;
|
||||
|
|
@ -269,39 +378,42 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
foreach (Location location in cropsToBonemeal)
|
||||
{
|
||||
if (!running) break;
|
||||
|
||||
if (WaitForMoveToLocation(location))
|
||||
{
|
||||
if (!running) break;
|
||||
|
||||
// Stop if we do not have any more bonemeal left
|
||||
if (!SwitchToItem(ItemType.BoneMeal))
|
||||
{
|
||||
LogToConsole("No bonemeal, searching for some farmland to plant seeds on");
|
||||
LogDebug("No bonemeal, searching for some farmland to plant seeds on...");
|
||||
break;
|
||||
}
|
||||
|
||||
// Send like 5 bonemeal attempts, it should do the job with 2-3, but sometimes doesn't do
|
||||
Location location2 = new Location(Math.Floor(location.X) + 0.5, location.Y, Math.Floor(location.Z) + 0.5);
|
||||
LogDebug("Trying to bonemeal: " + location2);
|
||||
|
||||
// Send like 4 bonemeal attempts, it should do the job with 2-3, but sometimes doesn't do
|
||||
for (int boneMealTimes = 0; boneMealTimes < 4; boneMealTimes++)
|
||||
{
|
||||
// TODO: Do a check if the carrot/potato is on the first growth stage
|
||||
// if so, use: new Location(location.X, (double)(location.Y - 1) + (double)0.93750, location.Z)
|
||||
SendPlaceBlock(location, Direction.Down);
|
||||
SendPlaceBlock(location2, Direction.Down);
|
||||
}
|
||||
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
LogToConsole("Finished bonemealing crops");
|
||||
LogDebug("Finished bonemealing crops!");
|
||||
state = State.SearchingForFarmlandToPlant;
|
||||
break;
|
||||
}
|
||||
|
||||
LogToConsole("Waiting for " + Config.Delay_Between_Tasks + " seconds for next cycle.");
|
||||
LogDebug("Waiting for " + Config.Delay_Between_Tasks + " seconds for next cycle.");
|
||||
Thread.Sleep(Config.Delay_Between_Tasks * 1000);
|
||||
}
|
||||
|
||||
LogToConsole("Stopped farming!");
|
||||
LogToConsole(Translations.TryGet("bot.farmer.stopped"));
|
||||
}
|
||||
|
||||
private Material GetMaterialForCropType(CropType type)
|
||||
|
|
@ -604,9 +716,8 @@ namespace MinecraftClient.ChatBots
|
|||
return false;
|
||||
}
|
||||
|
||||
// Yoinked from ReinforceZwei's AutoTree
|
||||
// TODO: Rewrite to support the whole inventory and moving to the hotbar
|
||||
public bool SwitchToItem(ItemType itemType)
|
||||
// Yoinked from ReinforceZwei's AutoTree and adapted to search the whole of inventory in additon to the hotbar
|
||||
private bool SwitchToItem(ItemType itemType)
|
||||
{
|
||||
Container playerInventory = GetPlayerInventory();
|
||||
|
||||
|
|
@ -614,31 +725,41 @@ namespace MinecraftClient.ChatBots
|
|||
&& playerInventory.Items[GetCurrentSlot() - 36].Type == itemType)
|
||||
return true; // Already selected
|
||||
|
||||
// Search for the seed in the hotbar
|
||||
List<int> result = new List<int>(playerInventory.SearchItem(itemType))
|
||||
.Where(slot => slot >= 36 && slot <= 44)
|
||||
.ToList();
|
||||
// Search the full inventory
|
||||
List<int> fullInventorySearch = new List<int>(playerInventory.SearchItem(itemType));
|
||||
|
||||
if (result.Count <= 0)
|
||||
// Search for the seed in the hotbar
|
||||
List<int> hotbarSerch = fullInventorySearch.Where(slot => slot >= 36 && slot <= 44).ToList();
|
||||
|
||||
if (hotbarSerch.Count > 0)
|
||||
{
|
||||
ChangeSlot((short)(hotbarSerch[0] - 36));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fullInventorySearch.Count == 0)
|
||||
return false;
|
||||
|
||||
ChangeSlot((short)(result[0] - 36));
|
||||
ItemMovingHelper movingHelper = new ItemMovingHelper(playerInventory, Handler);
|
||||
movingHelper.Swap(fullInventorySearch[0], 36);
|
||||
ChangeSlot(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Yoinked from Daenges's Sugarcane Farmer
|
||||
private bool WaitForMoveToLocation(Location pos, float tolerance = 2f)
|
||||
{
|
||||
if (MoveToLocation(pos))
|
||||
if (MoveToLocation(location: pos, allowUnsafe: allowUnsafe, allowDirectTeleport: allowTeleport))
|
||||
{
|
||||
LogToConsole("Moving to: " + pos);
|
||||
LogDebug("Moving to: " + pos);
|
||||
|
||||
while (GetCurrentLocation().Distance(pos) > tolerance)
|
||||
Thread.Sleep(200);
|
||||
|
||||
return true;
|
||||
}
|
||||
else LogToConsole("Can't move to: " + pos);
|
||||
else LogDebug("Can't move to: " + pos);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -660,5 +781,12 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void LogDebug(object text)
|
||||
{
|
||||
if (debugEnabled)
|
||||
LogToConsole(text);
|
||||
else LogDebugToConsole(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
namespace MinecraftClient.Commands
|
||||
{
|
||||
class Reload : Command
|
||||
{
|
||||
public override string CmdName { get { return "reload"; } }
|
||||
public override string CmdUsage { get { return "reload"; } }
|
||||
public override string CmdDesc { get { return "cmd.reload.desc"; } }
|
||||
|
||||
public override string Run(McClient handler, string command, Dictionary<string, object>? localVars)
|
||||
{
|
||||
handler.Log.Info(Translations.TryGet("cmd.reload.started"));
|
||||
handler.ReloadSettings();
|
||||
handler.Log.Warn(Translations.TryGet("cmd.reload.warning1"));
|
||||
handler.Log.Warn(Translations.TryGet("cmd.reload.warning2"));
|
||||
handler.Log.Warn(Translations.TryGet("cmd.reload.warning3"));
|
||||
handler.Log.Warn(Translations.TryGet("cmd.reload.warning4"));
|
||||
|
||||
return Translations.TryGet("cmd.reload.finished");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue