From eb517a8e78c8ca7f1fe4d561be14c9b5926af49d Mon Sep 17 00:00:00 2001 From: BruceChen Date: Mon, 12 Sep 2022 02:10:18 +0800 Subject: [PATCH] Upgrade Auto Fishing --- ConsoleInteractive | 2 +- MinecraftClient/ChatBots/AutoFishing.cs | 185 +++++++++++++----- .../Resources/config/MinecraftClient.ini | 4 + MinecraftClient/Resources/lang/en.ini | 8 +- MinecraftClient/Scripting/ChatBot.cs | 9 + MinecraftClient/Settings.cs | 27 ++- 6 files changed, 182 insertions(+), 53 deletions(-) diff --git a/ConsoleInteractive b/ConsoleInteractive index b4fd7da2..7acaa0ab 160000 --- a/ConsoleInteractive +++ b/ConsoleInteractive @@ -1 +1 @@ -Subproject commit b4fd7da2595ad54479880fc1c9c6e14975412d92 +Subproject commit 7acaa0ab31809f0f6512e6a76e53e15441de8e7c diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 961a9527..507a736d 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -13,13 +13,30 @@ namespace MinecraftClient.ChatBots /// class AutoFishing : ChatBot { - private Entity fishingRod; - private Double fishingHookThreshold = 0.2; - private Location LastPos = new Location(); - private DateTime CaughtTime = DateTime.Now; + private int fishCount = 0; private bool inventoryEnabled; + private bool isFishing = false; - private int useItemCounter = 0; + private Entity? fishingBobber; + private Location LastPos = Location.Zero; + private DateTime CaughtTime = DateTime.Now; + + private int counter = 0; + private readonly object stateLock = new(); + private FishingState state = FishingState.WaitJoinGame; + + private int castTimeout = 12; + + private enum FishingState + { + WaitJoinGame, + WaitingToCast, + CastingRod, + WaitingFishingBobber, + WaitingFishBite, + Preparing, + Stopping, + } public override void Initialize() { @@ -32,42 +49,94 @@ namespace MinecraftClient.ChatBots inventoryEnabled = GetInventoryEnabled(); } + public override void AfterGameJoined() + { + double delay = Settings.AutoFishing_FishingDelay; + LogToConsole(Translations.Get("bot.autoFish.start", delay)); + lock (stateLock) + { + counter = (int)(delay * 10); + state = FishingState.WaitingToCast; + } + } + public override void Update() { - if (useItemCounter > 0) + lock (stateLock) { - useItemCounter--; - if (useItemCounter <= 0) + switch (state) { - UseItemInHand(); + case FishingState.WaitJoinGame: + break; + case FishingState.WaitingToCast: + if (--counter < 0) + state = FishingState.CastingRod; + break; + case FishingState.CastingRod: + UseFishRod(); + counter = 0; + state = FishingState.WaitingFishingBobber; + break; + case FishingState.WaitingFishingBobber: + if (++counter > castTimeout) + { + if (castTimeout < 6000) + castTimeout *= 2; + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.cast_timeout", castTimeout / 10.0)); + + counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); + state = FishingState.WaitingToCast; + } + break; + case FishingState.WaitingFishBite: + if (++counter > (int)(Settings.AutoFishing_FishingTimeout * 10)) + { + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.fishing_timeout")); + + counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); + state = FishingState.WaitingToCast; + } + break; + case FishingState.Preparing: + break; + case FishingState.Stopping: + break; } } } public override void OnEntitySpawn(Entity entity) { - if (entity.Type == EntityType.FishingBobber) + if (entity.Type == EntityType.FishingBobber && entity.ObjectData == GetPlayerEntityID()) { - if (GetCurrentLocation().Distance(entity.Location) < 2 && !isFishing) + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.throw")); + lock (stateLock) { - LogToConsoleTranslated("bot.autoFish.throw"); - fishingRod = entity; + fishingBobber = entity; LastPos = entity.Location; isFishing = true; + + castTimeout = 24; + counter = 0; + state = FishingState.WaitingFishBite; } } } public override void OnEntityDespawn(Entity entity) { - if (entity.Type == EntityType.FishingBobber) + if (isFishing && entity.Type == EntityType.FishingBobber && entity.ID == fishingBobber!.ID) { - if(entity.ID == fishingRod.ID) + isFishing = false; + + if (Settings.AutoFishing_Antidespawn) { - isFishing = false; - if (Settings.AutoFishing_Antidespawn) + LogToConsoleTranslated("bot.autoFish.despawn"); + + lock (stateLock) { - useItemCounter = 5; // 500ms + counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); + state = FishingState.WaitingToCast; } } } @@ -75,75 +144,95 @@ namespace MinecraftClient.ChatBots public override void OnEntityMove(Entity entity) { - if (isFishing) + if (isFishing && fishingBobber!.ID == entity.ID) { - if (fishingRod.ID == entity.ID) + Location Pos = entity.Location; + double Dx = LastPos.X - Pos.X; + double Dy = LastPos.Y - Pos.Y; + double Dz = LastPos.Z - Pos.Z; + LastPos = Pos; + + // check if fishing hook is stationary + if (Dx == 0 && Dz == 0) { - Location Pos = entity.Location; - Double Dx = LastPos.X - Pos.X; - Double Dy = LastPos.Y - Pos.Y; - Double Dz = LastPos.Z - Pos.Z; - LastPos = Pos; - // check if fishing hook is stationary - if (Dx == 0 && Dz == 0) + if (Math.Abs(Dy) > Settings.AutoFishing_FishingHookThreshold) { - if (Math.Abs(Dy) > fishingHookThreshold) + // caught + // prevent triggering multiple time + if ((DateTime.Now - CaughtTime).TotalSeconds > 1) { - // caught - // prevent triggering multiple time - if ((DateTime.Now - CaughtTime).TotalSeconds > 1) - { - OnCaughtFish(); - CaughtTime = DateTime.Now; - } + CaughtTime = DateTime.Now; + OnCaughtFish(); } } - fishingRod = entity; } } } public override bool OnDisconnect(DisconnectReason reason, string message) { - fishingRod = null; - LastPos = new Location(); + lock (stateLock) + { + isFishing = false; + + counter = 0; + state = FishingState.Stopping; + } + + fishingBobber = null; + LastPos = Location.Zero; CaughtTime = DateTime.Now; - isFishing = false; - useItemCounter = 0; + return base.OnDisconnect(reason, message); } + private void UseFishRod() + { + UseItemInHand(); + } + /// /// Called when detected a fish is caught /// public void OnCaughtFish() { - LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught")); - // retract fishing rod - UseItemInHand(); + lock (stateLock) + { + state = FishingState.Preparing; + } + + UseFishRod(); + + ++fishCount; + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught", fishCount)); + if (inventoryEnabled) { - if (!hasFishingRod()) + if (!HasFishingRod()) { LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.no_rod")); return; } } - // thread-safe - useItemCounter = 8; // 800ms + + lock (stateLock) + { + counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); + state = FishingState.WaitingToCast; + } } /// /// Check whether the player has a fishing rod in inventory /// /// TRUE if the player has a fishing rod - public bool hasFishingRod() + public bool HasFishingRod() { if (!inventoryEnabled) return false; int start = 36; int end = 44; - Inventory.Container container = GetPlayerInventory(); + Container container = GetPlayerInventory(); foreach (KeyValuePair a in container.Items) { diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 332c00be..bc43d351 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -207,6 +207,10 @@ interaction=Attack # Possible values: Interact, Attack (default) # /!\ Make sure server rules allow automated farming before using this bot enabled=false antidespawn=false +fishing_delay=3.0 # How long after entering the game to start fishing (seconds). +fishing_timeout=600.0 # Fishing timeout (seconds). Timeout will re-cast the rod +fishing_hook_threshold=0.2 # Fish hooks moving on the Y-axis above this threshold will be considered to have caught a fish. +fishing_cast_delay=0.4 # How soon to re-cast after successful fishing. [AutoEat] # Automatically eat food when your Hunger value is low diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 1d0cc4ad..4a30ee1c 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -447,9 +447,13 @@ bot.autoDrop.no_mode=Cannot read drop mode from config. Using include mode. bot.autoDrop.no_inventory=Cannot find inventory {0}! # AutoFish -bot.autoFish.throw=Threw a fishing rod -bot.autoFish.caught=Caught a fish! +bot.autoFish.start=Fishing will start in {0:0.0} second(s). +bot.autoFish.throw=Casting successfully. +bot.autoFish.caught=Caught a fish! (Count: {0}) bot.autoFish.no_rod=No Fishing Rod on hand. Maybe broken? +bot.autoFish.despawn=Fish floating despawn, will re-cast. +bot.autoFish.fishing_timeout=Fishing timeout, will soon re-cast. +bot.autoFish.cast_timeout=Casting timeout and will soon retry. (Timeout increased to {0:0.0} sec). # AutoRelog bot.autoRelog.launch=Launching with {0} reconnection attempts diff --git a/MinecraftClient/Scripting/ChatBot.cs b/MinecraftClient/Scripting/ChatBot.cs index 4fc59e1e..2fccd721 100644 --- a/MinecraftClient/Scripting/ChatBot.cs +++ b/MinecraftClient/Scripting/ChatBot.cs @@ -1113,6 +1113,15 @@ namespace MinecraftClient return Handler.GetUserUuidStr(); } + /// + /// Return the EntityID of the current player + /// + /// EntityID of the current player + protected int GetPlayerEntityID() + { + return Handler.GetPlayerEntityID(); + } + /// /// Return the list of currently online players /// diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index db493953..7f8c71b2 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -203,6 +203,10 @@ namespace MinecraftClient //Auto Fishing public static bool AutoFishing_Enabled = false; public static bool AutoFishing_Antidespawn = false; + public static double AutoFishing_FishingDelay = 3.0; + public static double AutoFishing_FishingTimeout = 600.0; + public static double AutoFishing_FishingHookThreshold = 0.2; + public static double AutoFishing_FishingCastDelay = 0.4; //Auto Eating public static bool AutoEat_Enabled = false; @@ -711,6 +715,10 @@ namespace MinecraftClient { case "enabled": AutoFishing_Enabled = str2bool(argValue); return true; case "antidespawn": AutoFishing_Antidespawn = str2bool(argValue); return true; + case "fishing_delay": AutoFishing_FishingDelay = str2double(argValue); return true; + case "fishing_timeout": AutoFishing_FishingTimeout = str2double(argValue); return true; + case "fishing_hook_threshold": AutoFishing_FishingHookThreshold = str2double(argValue); return true; + case "fishing_cast_delay": AutoFishing_FishingCastDelay = str2double(argValue); return true; } break; @@ -863,8 +871,23 @@ namespace MinecraftClient /// Float number public static float str2float(string str) { - float f; - if (float.TryParse(str.Trim(), out f)) + if (float.TryParse(str.Trim(), out float f)) + return f; + else + { + ConsoleIO.WriteLogLine(Translations.Get("error.setting.str2int", str)); + return 0; + } + } + + /// + /// Convert the specified string to a double number, defaulting to zero if invalid argument + /// + /// String to parse as a float number + /// Double number + public static double str2double(string str) + { + if (double.TryParse(str.Trim(), out double f)) return f; else {