Support automatic rod switching

This commit is contained in:
BruceChen 2022-09-12 18:02:46 +08:00
parent 949126c9cb
commit cb22387008
4 changed files with 98 additions and 92 deletions

View file

@ -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()
/// <summary>
/// Called when detected a fish is caught
/// </summary>
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;
}
}
}
/// <summary>
/// Called when detected a fish is caught
/// </summary>
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;
}
}
/// <summary>
/// Check whether the player has a fishing rod in inventory
/// </summary>
/// <returns>TRUE if the player has a fishing rod</returns>
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<int, Item> 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;
}
}
}
}

View file

@ -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

View file

@ -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

View file

@ -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: