From cb2238700802e67fce880d09831311302bb66f3e Mon Sep 17 00:00:00 2001 From: BruceChen Date: Mon, 12 Sep 2022 18:02:46 +0800 Subject: [PATCH] Support automatic rod switching --- MinecraftClient/ChatBots/AutoFishing.cs | 179 +++++++++--------- .../Resources/config/MinecraftClient.ini | 2 + MinecraftClient/Resources/lang/en.ini | 3 +- MinecraftClient/Settings.cs | 6 +- 4 files changed, 98 insertions(+), 92 deletions(-) diff --git a/MinecraftClient/ChatBots/AutoFishing.cs b/MinecraftClient/ChatBots/AutoFishing.cs index 69617b36..98cf53d5 100644 --- a/MinecraftClient/ChatBots/AutoFishing.cs +++ b/MinecraftClient/ChatBots/AutoFishing.cs @@ -17,7 +17,7 @@ namespace MinecraftClient.ChatBots private bool inventoryEnabled; private int castTimeout = 12; - private bool isFishing = false; + private bool isFishing = false, isWaitingRod = false; private Entity? fishingBobber; private Location LastPos = Location.Zero; private DateTime CaughtTime = DateTime.Now; @@ -36,8 +36,9 @@ namespace MinecraftClient.ChatBots CastingRod, WaitingFishingBobber, WaitingFishToBite, + StartMove, + WaitingMovement, DurabilityCheck, - ChangeLocation, Stopping, } @@ -62,7 +63,7 @@ namespace MinecraftClient.ChatBots lock (stateLock) { counter = (int)(delay * 10); - state = FishingState.DurabilityCheck; + state = FishingState.StartMove; } } @@ -75,14 +76,12 @@ namespace MinecraftClient.ChatBots } } - public override void AfterGameJoined() + private void UseFishRod() { - StartFishing(); - } - - public override void OnRespawn() - { - StartFishing(); + if (Settings.AutoFishing_Mainhand) + UseItemInHand(); + else + UseItemInLeftHand(); } public override void Update() @@ -124,18 +123,36 @@ namespace MinecraftClient.ChatBots state = FishingState.WaitingToCast; } break; - case FishingState.DurabilityCheck: + case FishingState.StartMove: if (--counter < 0) { - DurabilityCheckAndMove(); + double[,]? locationList = Settings.AutoFishing_Location; + if (locationList != null) + { + UpdateLocation(locationList); + state = FishingState.WaitingMovement; + } + else + { + counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); + state = FishingState.DurabilityCheck; + goto case FishingState.DurabilityCheck; + } } break; - case FishingState.ChangeLocation: + case FishingState.WaitingMovement: if (!ClientIsMoving()) { LookAtLocation(nextYaw, nextPitch); LogToConsole(Translations.Get("bot.autoFish.update_lookat", nextYaw, nextPitch)); + state = FishingState.DurabilityCheck; + goto case FishingState.DurabilityCheck; + } + break; + case FishingState.DurabilityCheck: + if (DurabilityCheck()) + { counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); state = FishingState.WaitingToCast; } @@ -211,6 +228,16 @@ namespace MinecraftClient.ChatBots } } + public override void AfterGameJoined() + { + StartFishing(); + } + + public override void OnRespawn() + { + StartFishing(); + } + public override void OnDeath() { StopFishing(); @@ -227,14 +254,26 @@ namespace MinecraftClient.ChatBots return base.OnDisconnect(reason, message); } - private void UseFishRod() + /// + /// Called when detected a fish is caught + /// + public void OnCaughtFish() { - if (Settings.AutoFishing_Mainhand) - UseItemInHand(); + ++fishCount; + if (Settings.AutoFishing_Location != null) + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught_at", + fishingBobber!.Location.X, fishingBobber!.Location.Y, fishingBobber!.Location.Z, fishCount)); else - UseItemInLeftHand(); - } + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught", fishCount)); + lock (stateLock) + { + UseFishRod(); + + counter = 0; + state = FishingState.StartMove; + } + } private void UpdateLocation(double[,] locationList) { if (curLocationIdx >= locationList.GetLength(0)) @@ -298,86 +337,46 @@ namespace MinecraftClient.ChatBots } - private void DurabilityCheckAndMove() - { - if (inventoryEnabled) - { - if (!HasFishingRod()) - { - LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.no_rod")); - - lock (stateLock) - { - state = FishingState.Stopping; - } - - return; - } - } - - double[,]? locationList = Settings.AutoFishing_Location; - if (locationList != null) - { - UpdateLocation(locationList); - lock (stateLock) - { - state = FishingState.ChangeLocation; - } - } - else - { - lock (stateLock) - { - counter = (int)(Settings.AutoFishing_FishingCastDelay * 10); - state = FishingState.WaitingToCast; - } - } - } - - /// - /// Called when detected a fish is caught - /// - public void OnCaughtFish() - { - ++fishCount; - if (Settings.AutoFishing_Location != null) - LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught_at", - fishingBobber!.Location.X, fishingBobber!.Location.Y, fishingBobber!.Location.Z, fishCount)); - else - LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught", fishCount)); - - lock (stateLock) - { - UseFishRod(); - - counter = 0; - state = FishingState.DurabilityCheck; - } - } - - /// - /// Check whether the player has a fishing rod in inventory - /// - /// TRUE if the player has a fishing rod - public bool HasFishingRod() + private bool DurabilityCheck() { if (!inventoryEnabled) - return false; + return true; - int start = 36; - int end = 44; + bool useMainHand = Settings.AutoFishing_Mainhand; Container container = GetPlayerInventory(); - foreach (KeyValuePair a in container.Items) + int itemSolt = useMainHand ? GetCurrentSlot() + 36 : 45; + + if (container.Items.TryGetValue(itemSolt, out Item? handItem) && + handItem.Type == ItemType.FishingRod && (64 - handItem.Damage) >= Settings.AutoFishing_DurabilityLimit) { - if (a.Key < start || a.Key > end) - continue; - - if (a.Value.Type == ItemType.FishingRod) - return true; + isWaitingRod = false; + return true; } + else + { + if (!isWaitingRod) + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.no_rod")); - return false; + if (Settings.AutoFishing_AutoRodSwitch) + { + foreach ((int slot, Item item) in container.Items) + { + if (item.Type == ItemType.FishingRod && (64 - item.Damage) >= Settings.AutoFishing_DurabilityLimit) + { + WindowAction(0, slot, WindowActionType.LeftClick); + WindowAction(0, itemSolt, WindowActionType.LeftClick); + WindowAction(0, slot, WindowActionType.LeftClick); + LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.switch", slot, (64 - item.Damage))); + isWaitingRod = false; + return true; + } + } + } + + isWaitingRod = true; + return false; + } } } } diff --git a/MinecraftClient/Resources/config/MinecraftClient.ini b/MinecraftClient/Resources/config/MinecraftClient.ini index 4632cd00..d5453f82 100644 --- a/MinecraftClient/Resources/config/MinecraftClient.ini +++ b/MinecraftClient/Resources/config/MinecraftClient.ini @@ -212,6 +212,8 @@ fishing_delay=3.0 # How long after entering the game to start f fishing_timeout=300.0 # Fishing timeout (seconds). Timeout will trigger a re-cast. 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. +durability_limit=2 # Will not use rods with less durability than this (full durability is 64). Set to zero to disable this feature. +auto_rod_switch=true # Switch to a new rod from inventory after the current rod is unavailable. location= # Some plugins do not allow the player to fish in one place. This allows the player to change position/angle after each fish caught. # Floating point numbers can be used for both coordinates and angles. Leave blank to disable this function. # Change the angle only (recommended): location=yaw_1,pitch_1;yaw_2,pitch_2;...;yaw_n,pitch_n diff --git a/MinecraftClient/Resources/lang/en.ini b/MinecraftClient/Resources/lang/en.ini index 15b6d2e9..637c40bd 100644 --- a/MinecraftClient/Resources/lang/en.ini +++ b/MinecraftClient/Resources/lang/en.ini @@ -454,11 +454,12 @@ 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.caught_at=Caught a fish at ({0:0.0},{1:0.0},{2:0.0})! (Count: {3}) -bot.autoFish.no_rod=No Fishing Rod on hand. Maybe broken? +bot.autoFish.no_rod=Current fishing rod is not available. Maybe broken or low durability? 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). bot.autoFish.update_lookat=Update yaw = {0:0.00}, pitch = {1:0.00}. +bot.autoFish.switch=Switch to the rod in slot {0}, durability {1}/64. # AutoRelog bot.autoRelog.launch=Launching with {0} reconnection attempts diff --git a/MinecraftClient/Settings.cs b/MinecraftClient/Settings.cs index 30e46cc0..0a14b1a6 100644 --- a/MinecraftClient/Settings.cs +++ b/MinecraftClient/Settings.cs @@ -208,6 +208,8 @@ namespace MinecraftClient public static double AutoFishing_FishingTimeout = 600.0; public static double AutoFishing_FishingHookThreshold = 0.2; public static double AutoFishing_FishingCastDelay = 0.4; + public static double AutoFishing_DurabilityLimit = 2; + public static bool AutoFishing_AutoRodSwitch = true; public static double[,]? AutoFishing_Location = null; //Auto Eating @@ -721,8 +723,10 @@ namespace MinecraftClient 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; + case "durability_limit": AutoFishing_DurabilityLimit = str2int(argValue); return true; + case "auto_rod_switch": AutoFishing_AutoRodSwitch = str2bool(argValue); return true; case "location": AutoFishing_Location = str2locationList(argValue); return true; - } + } break; case Section.AutoEat: