Minecraft-Console-Client/MinecraftClient/ChatBots/AutoFishing.cs

250 lines
7.9 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MinecraftClient.Mapping;
using MinecraftClient.Inventory;
namespace MinecraftClient.ChatBots
{
/// <summary>
/// The AutoFishing bot semi-automates fishing.
/// The player needs to have a fishing rod in hand, then manually send it using the UseItem command.
/// </summary>
class AutoFishing : ChatBot
{
2022-09-12 02:10:18 +08:00
private int fishCount = 0;
2020-03-26 15:01:42 +08:00
private bool inventoryEnabled;
2022-09-12 02:10:18 +08:00
private bool isFishing = false;
2022-09-12 02:10:18 +08:00
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()
{
if (!GetEntityHandlingEnabled())
{
LogToConsoleTranslated("extra.entity_required");
LogToConsoleTranslated("general.bot_unload");
UnloadBot();
}
2020-03-26 15:01:42 +08:00
inventoryEnabled = GetInventoryEnabled();
}
2022-09-12 02:10:18 +08:00
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;
}
}
2020-05-22 08:58:30 +08:00
public override void Update()
{
2022-09-12 02:10:18 +08:00
lock (stateLock)
2020-05-22 08:58:30 +08:00
{
2022-09-12 02:10:18 +08:00
switch (state)
2020-05-22 08:58:30 +08:00
{
2022-09-12 02:10:18 +08:00
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;
2020-05-22 08:58:30 +08:00
}
}
}
public override void OnEntitySpawn(Entity entity)
{
2022-09-12 02:10:18 +08:00
if (entity.Type == EntityType.FishingBobber && entity.ObjectData == GetPlayerEntityID())
{
2022-09-12 02:10:18 +08:00
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.throw"));
lock (stateLock)
{
2022-09-12 02:10:18 +08:00
fishingBobber = entity;
LastPos = entity.Location;
isFishing = true;
2022-09-12 02:10:18 +08:00
castTimeout = 24;
counter = 0;
state = FishingState.WaitingFishBite;
}
}
}
public override void OnEntityDespawn(Entity entity)
{
2022-09-12 02:10:18 +08:00
if (isFishing && entity.Type == EntityType.FishingBobber && entity.ID == fishingBobber!.ID)
{
2022-09-12 02:10:18 +08:00
isFishing = false;
if (Settings.AutoFishing_Antidespawn)
{
2022-09-12 02:10:18 +08:00
LogToConsoleTranslated("bot.autoFish.despawn");
lock (stateLock)
2020-05-22 08:58:30 +08:00
{
2022-09-12 02:10:18 +08:00
counter = (int)(Settings.AutoFishing_FishingCastDelay * 10);
state = FishingState.WaitingToCast;
2020-05-22 08:58:30 +08:00
}
}
}
}
public override void OnEntityMove(Entity entity)
{
2022-09-12 02:10:18 +08:00
if (isFishing && fishingBobber!.ID == entity.ID)
{
2022-09-12 02:10:18 +08:00
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)
{
2022-09-12 02:10:18 +08:00
if (Math.Abs(Dy) > Settings.AutoFishing_FishingHookThreshold)
{
2022-09-12 02:10:18 +08:00
// caught
// prevent triggering multiple time
if ((DateTime.Now - CaughtTime).TotalSeconds > 1)
{
2022-09-12 02:10:18 +08:00
CaughtTime = DateTime.Now;
OnCaughtFish();
}
}
}
}
}
2020-12-30 21:43:37 +08:00
public override bool OnDisconnect(DisconnectReason reason, string message)
{
2022-09-12 02:10:18 +08:00
lock (stateLock)
{
isFishing = false;
counter = 0;
state = FishingState.Stopping;
}
fishingBobber = null;
LastPos = Location.Zero;
2020-12-30 21:43:37 +08:00
CaughtTime = DateTime.Now;
2022-09-12 02:10:18 +08:00
2020-12-30 21:43:37 +08:00
return base.OnDisconnect(reason, message);
}
2022-09-12 02:10:18 +08:00
private void UseFishRod()
{
UseItemInHand();
}
/// <summary>
/// Called when detected a fish is caught
/// </summary>
public void OnCaughtFish()
{
2022-09-12 02:10:18 +08:00
lock (stateLock)
{
state = FishingState.Preparing;
}
UseFishRod();
++fishCount;
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.caught", fishCount));
2020-03-26 15:01:42 +08:00
if (inventoryEnabled)
{
2022-09-12 02:10:18 +08:00
if (!HasFishingRod())
2020-03-26 15:01:42 +08:00
{
LogToConsole(GetTimestamp() + ": " + Translations.Get("bot.autoFish.no_rod"));
2020-03-26 15:01:42 +08:00
return;
}
}
2022-09-12 02:10:18 +08:00
lock (stateLock)
{
counter = (int)(Settings.AutoFishing_FishingCastDelay * 10);
state = FishingState.WaitingToCast;
}
}
2020-03-26 15:01:42 +08:00
/// <summary>
/// Check whether the player has a fishing rod in inventory
/// </summary>
/// <returns>TRUE if the player has a fishing rod</returns>
2022-09-12 02:10:18 +08:00
public bool HasFishingRod()
2020-03-26 15:01:42 +08:00
{
if (!inventoryEnabled)
return false;
2020-03-26 15:01:42 +08:00
int start = 36;
int end = 44;
2022-09-12 02:10:18 +08:00
Container container = GetPlayerInventory();
foreach (KeyValuePair<int, Item> a in container.Items)
2020-03-26 15:01:42 +08:00
{
if (a.Key < start || a.Key > end)
continue;
if (a.Value.Type == ItemType.FishingRod)
return true;
2020-03-26 15:01:42 +08:00
}
2020-03-26 15:01:42 +08:00
return false;
}
}
}