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: