mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2026-08-15 13:04:36 +00:00
feat: Improved Auto Fishing detection
This commit is contained in:
commit
ee48c24f69
8 changed files with 380 additions and 17 deletions
|
|
@ -62,6 +62,21 @@ namespace MinecraftClient.ChatBots
|
|||
[TomlInlineComment("$ChatBot.AutoFishing.Hook_Threshold$")]
|
||||
public double Hook_Threshold = 0.2;
|
||||
|
||||
[TomlInlineComment("$ChatBot.AutoFishing.Enable_Velocity_Detection$")]
|
||||
public bool Enable_Velocity_Detection = true;
|
||||
|
||||
[TomlInlineComment("$ChatBot.AutoFishing.Velocity_Hook_Threshold$")]
|
||||
public double Velocity_Hook_Threshold = -0.2;
|
||||
|
||||
[TomlInlineComment("$ChatBot.AutoFishing.Enable_Sound_Detection$")]
|
||||
public bool Enable_Sound_Detection = true;
|
||||
|
||||
[TomlInlineComment("$ChatBot.AutoFishing.Sound_Distance$")]
|
||||
public double Sound_Distance = 5.0;
|
||||
|
||||
[TomlInlineComment("$ChatBot.AutoFishing.Detection_Warmup$")]
|
||||
public double Detection_Warmup = 1.0;
|
||||
|
||||
[TomlInlineComment("$ChatBot.AutoFishing.Log_Fish_Bobber$")]
|
||||
public bool Log_Fish_Bobber = false;
|
||||
|
||||
|
|
@ -97,6 +112,15 @@ namespace MinecraftClient.ChatBots
|
|||
|
||||
if (Hook_Threshold < 0)
|
||||
Hook_Threshold = -Hook_Threshold;
|
||||
|
||||
if (Velocity_Hook_Threshold > 0)
|
||||
Velocity_Hook_Threshold = -Velocity_Hook_Threshold;
|
||||
|
||||
if (Sound_Distance < 0)
|
||||
Sound_Distance = -Sound_Distance;
|
||||
|
||||
if (Detection_Warmup < 0)
|
||||
Detection_Warmup = 0;
|
||||
}
|
||||
|
||||
public struct LocationConfig
|
||||
|
|
@ -171,6 +195,7 @@ namespace MinecraftClient.ChatBots
|
|||
private Entity? fishingBobber;
|
||||
private Location LastPos = Location.Zero;
|
||||
private DateTime CaughtTime = DateTime.Now;
|
||||
private DateTime BobberSpawnTime = DateTime.MinValue;
|
||||
private int fishItemCounter = 15;
|
||||
private Dictionary<ItemType, uint> fishItemCnt = new();
|
||||
private Entity fishItem = new(-1, EntityType.Item, Location.Zero);
|
||||
|
|
@ -464,6 +489,7 @@ namespace MinecraftClient.ChatBots
|
|||
fishingBobber = entity;
|
||||
LastPos = entity.Location;
|
||||
isFishing = true;
|
||||
BobberSpawnTime = DateTime.Now;
|
||||
|
||||
castTimeout = 24;
|
||||
counter = 0;
|
||||
|
|
@ -500,7 +526,7 @@ namespace MinecraftClient.ChatBots
|
|||
public override void OnEntityMove(Entity entity)
|
||||
{
|
||||
if (isFishing && entity is not null && fishingBobber!.ID == entity.ID &&
|
||||
(state == FishingState.WaitingFishToBite || state == FishingState.WaitingFishingBobber))
|
||||
state == FishingState.WaitingFishToBite)
|
||||
{
|
||||
Location Pos = entity.Location;
|
||||
double Dx = LastPos.X - Pos.X;
|
||||
|
|
@ -515,13 +541,7 @@ namespace MinecraftClient.ChatBots
|
|||
Math.Abs(Dz) < Math.Abs(Config.Stationary_Threshold) &&
|
||||
Math.Abs(Dy) > Math.Abs(Config.Hook_Threshold))
|
||||
{
|
||||
// prevent triggering multiple time
|
||||
if ((DateTime.Now - CaughtTime).TotalSeconds > 1)
|
||||
{
|
||||
isFishing = false;
|
||||
CaughtTime = DateTime.Now;
|
||||
OnCaughtFish();
|
||||
}
|
||||
TryCatchFish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -540,6 +560,38 @@ namespace MinecraftClient.ChatBots
|
|||
}
|
||||
}
|
||||
|
||||
public override void OnEntityVelocity(Entity entity, double velocityX, double velocityY, double velocityZ)
|
||||
{
|
||||
if (!Config.Enable_Velocity_Detection || !CanUseAdvancedDetection())
|
||||
return;
|
||||
|
||||
if (fishingBobber is null || entity.ID != fishingBobber.ID)
|
||||
return;
|
||||
|
||||
if (velocityY <= Config.Velocity_Hook_Threshold)
|
||||
TryCatchFish();
|
||||
}
|
||||
|
||||
public override void OnSoundEffect(string? soundName, Location? location, int category, float volume, float pitch,
|
||||
Entity? sourceEntity)
|
||||
{
|
||||
if (!Config.Enable_Sound_Detection || !CanUseAdvancedDetection())
|
||||
return;
|
||||
|
||||
if (!IsFishingBobberSplashSound(soundName))
|
||||
return;
|
||||
|
||||
Location? soundLocation = location;
|
||||
if (soundLocation is null && sourceEntity is not null)
|
||||
soundLocation = sourceEntity.Location;
|
||||
|
||||
if (soundLocation is null || fishingBobber is null)
|
||||
return;
|
||||
|
||||
if (soundLocation.Value.Distance(fishingBobber.Location) <= Config.Sound_Distance)
|
||||
TryCatchFish();
|
||||
}
|
||||
|
||||
public override void AfterGameJoined()
|
||||
{
|
||||
StartFishing();
|
||||
|
|
@ -562,10 +614,42 @@ namespace MinecraftClient.ChatBots
|
|||
fishingBobber = null;
|
||||
LastPos = Location.Zero;
|
||||
CaughtTime = DateTime.Now;
|
||||
BobberSpawnTime = DateTime.MinValue;
|
||||
|
||||
return base.OnDisconnect(reason, message);
|
||||
}
|
||||
|
||||
private bool CanUseAdvancedDetection()
|
||||
{
|
||||
if (!isFishing || fishingBobber is null || state != FishingState.WaitingFishToBite)
|
||||
return false;
|
||||
|
||||
return (DateTime.Now - BobberSpawnTime).TotalSeconds >= Config.Detection_Warmup;
|
||||
}
|
||||
|
||||
private void TryCatchFish()
|
||||
{
|
||||
if (!CanUseAdvancedDetection())
|
||||
return;
|
||||
|
||||
// Prevent repeated catches from multiple packets of the same bite.
|
||||
if ((DateTime.Now - CaughtTime).TotalSeconds <= 1)
|
||||
return;
|
||||
|
||||
isFishing = false;
|
||||
CaughtTime = DateTime.Now;
|
||||
OnCaughtFish();
|
||||
}
|
||||
|
||||
private static bool IsFishingBobberSplashSound(string? soundName)
|
||||
{
|
||||
return string.Equals(soundName, "minecraft:entity.fishing_bobber.splash",
|
||||
StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(soundName, "entity.fishing_bobber.splash", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(soundName, "minecraft:entity.bobber.splash", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(soundName, "entity.bobber.splash", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when detected a fish is caught
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -3798,6 +3798,44 @@ namespace MinecraftClient
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when an entity velocity update is received.
|
||||
/// </summary>
|
||||
/// <param name="entityID">Entity ID</param>
|
||||
/// <param name="velocityX">Velocity on X axis (blocks/tick)</param>
|
||||
/// <param name="velocityY">Velocity on Y axis (blocks/tick)</param>
|
||||
/// <param name="velocityZ">Velocity on Z axis (blocks/tick)</param>
|
||||
public void OnEntityVelocity(int entityID, double velocityX, double velocityY, double velocityZ)
|
||||
{
|
||||
if (entities.TryGetValue(entityID, out Entity? entity))
|
||||
DispatchBotEvent(bot => bot.OnEntityVelocity(entity, velocityX, velocityY, velocityZ));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when a sound packet is received.
|
||||
/// </summary>
|
||||
/// <param name="soundName">Sound key when available, otherwise null</param>
|
||||
/// <param name="location">Sound location when available</param>
|
||||
/// <param name="category">Sound category id from packet</param>
|
||||
/// <param name="volume">Sound volume</param>
|
||||
/// <param name="pitch">Sound pitch</param>
|
||||
/// <param name="entityID">Source entity id for entity sound packets, if any</param>
|
||||
public void OnSoundEffect(string? soundName, Location? location, int category, float volume, float pitch,
|
||||
int? entityID)
|
||||
{
|
||||
Entity? sourceEntity = null;
|
||||
Location? resolvedLocation = location;
|
||||
|
||||
if (entityID is int id && entities.TryGetValue(id, out Entity? entity))
|
||||
{
|
||||
sourceEntity = entity;
|
||||
resolvedLocation ??= entity.Location;
|
||||
}
|
||||
|
||||
DispatchBotEvent(bot => bot.OnSoundEffect(soundName, resolvedLocation, category, volume, pitch,
|
||||
sourceEntity));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when received entity properties from server.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -1054,20 +1054,44 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
}
|
||||
}
|
||||
|
||||
private static bool HasLpVec3Continuation(int firstByte) => (firstByte & 4) == 4;
|
||||
|
||||
private static double UnpackLpVec3(long packedAxis)
|
||||
{
|
||||
return Math.Min((double)(packedAxis & 32767L), 32766.0) * 2.0 / 32766.0 - 1.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an LpVec3 (low-precision vec3) from the cache (1.21.9+).
|
||||
/// Variable-length encoding: first byte 0 = zero vector; otherwise
|
||||
/// 2 bytes + 4 bytes (6 total), plus an optional VarInt continuation.
|
||||
/// Read and decode an LpVec3 (low-precision vec3) from the cache (1.21.9+).
|
||||
/// Returned vector is expressed in blocks per tick.
|
||||
/// </summary>
|
||||
public void ReadNextLpVec3(Queue<byte> cache)
|
||||
public (double X, double Y, double Z) ReadNextLpVec3Values(Queue<byte> cache)
|
||||
{
|
||||
int first = ReadNextByte(cache);
|
||||
if (first == 0)
|
||||
return;
|
||||
ReadNextByte(cache); // second byte
|
||||
ReadData(4, cache); // uint32
|
||||
if ((first & 4) == 4) // continuation bit set
|
||||
ReadNextVarInt(cache);
|
||||
return (0.0, 0.0, 0.0);
|
||||
|
||||
int second = ReadNextByte(cache);
|
||||
uint high = (uint)ReadNextInt(cache);
|
||||
long packed = ((long)high << 16) | (long)(second << 8) | (uint)first;
|
||||
|
||||
long scale = first & 3;
|
||||
if (HasLpVec3Continuation(first))
|
||||
scale |= ((long)ReadNextVarInt(cache) & 0xFFFFFFFFL) << 2;
|
||||
|
||||
return (
|
||||
UnpackLpVec3(packed >> 3) * scale,
|
||||
UnpackLpVec3(packed >> 18) * scale,
|
||||
UnpackLpVec3(packed >> 33) * scale
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read an LpVec3 (low-precision vec3) from the cache (1.21.9+) and discard it.
|
||||
/// </summary>
|
||||
public void ReadNextLpVec3(Queue<byte> cache)
|
||||
{
|
||||
ReadNextLpVec3Values(cache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -2642,6 +2642,27 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
handler.OnEntityRotation(entityId, yaw, pitch, isOnGround);
|
||||
}
|
||||
|
||||
break;
|
||||
case PacketTypesIn.EntityVelocity:
|
||||
if (handler.GetEntityHandlingEnabled())
|
||||
{
|
||||
var entityId = dataTypes.ReadNextVarInt(packetData);
|
||||
double velocityX, velocityY, velocityZ;
|
||||
|
||||
if (protocolVersion >= MC_1_21_9_Version)
|
||||
{
|
||||
(velocityX, velocityY, velocityZ) = dataTypes.ReadNextLpVec3Values(packetData);
|
||||
}
|
||||
else
|
||||
{
|
||||
velocityX = dataTypes.ReadNextShort(packetData) / 8000.0D;
|
||||
velocityY = dataTypes.ReadNextShort(packetData) / 8000.0D;
|
||||
velocityZ = dataTypes.ReadNextShort(packetData) / 8000.0D;
|
||||
}
|
||||
|
||||
handler.OnEntityVelocity(entityId, velocityX, velocityY, velocityZ);
|
||||
}
|
||||
|
||||
break;
|
||||
case PacketTypesIn.EntityProperties:
|
||||
if (handler.GetEntityHandlingEnabled())
|
||||
|
|
@ -2892,6 +2913,65 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
|
||||
handler.OnExplosion(explosionLocation, explosionStrength, explosionBlockCount);
|
||||
break;
|
||||
case PacketTypesIn.NamedSoundEffect:
|
||||
{
|
||||
string? soundName = dataTypes.ReadNextString(packetData);
|
||||
int category = dataTypes.ReadNextVarInt(packetData);
|
||||
double x = dataTypes.ReadNextInt(packetData) / 8.0D;
|
||||
double y = dataTypes.ReadNextInt(packetData) / 8.0D;
|
||||
double z = dataTypes.ReadNextInt(packetData) / 8.0D;
|
||||
float volume = dataTypes.ReadNextFloat(packetData);
|
||||
float pitch = dataTypes.ReadNextFloat(packetData);
|
||||
|
||||
handler.OnSoundEffect(soundName, new Location(x, y, z), category, volume, pitch, null);
|
||||
break;
|
||||
}
|
||||
case PacketTypesIn.SoundEffect:
|
||||
{
|
||||
string? soundName;
|
||||
if (protocolVersion >= MC_1_19_Version)
|
||||
soundName = ReadSoundEventHolderName(packetData);
|
||||
else
|
||||
{
|
||||
dataTypes.ReadNextVarInt(packetData); // Sound id
|
||||
soundName = null;
|
||||
}
|
||||
|
||||
int category = dataTypes.ReadNextVarInt(packetData);
|
||||
double x = dataTypes.ReadNextInt(packetData) / 8.0D;
|
||||
double y = dataTypes.ReadNextInt(packetData) / 8.0D;
|
||||
double z = dataTypes.ReadNextInt(packetData) / 8.0D;
|
||||
float volume = dataTypes.ReadNextFloat(packetData);
|
||||
float pitch = dataTypes.ReadNextFloat(packetData);
|
||||
|
||||
if (protocolVersion >= MC_1_19_Version)
|
||||
dataTypes.ReadNextLong(packetData); // Seed
|
||||
|
||||
handler.OnSoundEffect(soundName, new Location(x, y, z), category, volume, pitch, null);
|
||||
break;
|
||||
}
|
||||
case PacketTypesIn.EntitySoundEffect:
|
||||
{
|
||||
string? soundName;
|
||||
if (protocolVersion >= MC_1_19_Version)
|
||||
soundName = ReadSoundEventHolderName(packetData);
|
||||
else
|
||||
{
|
||||
dataTypes.ReadNextVarInt(packetData); // Sound id
|
||||
soundName = null;
|
||||
}
|
||||
|
||||
int category = dataTypes.ReadNextVarInt(packetData);
|
||||
int entityId = dataTypes.ReadNextVarInt(packetData);
|
||||
float volume = dataTypes.ReadNextFloat(packetData);
|
||||
float pitch = dataTypes.ReadNextFloat(packetData);
|
||||
|
||||
if (protocolVersion >= MC_1_19_Version)
|
||||
dataTypes.ReadNextLong(packetData); // Seed
|
||||
|
||||
handler.OnSoundEffect(soundName, null, category, volume, pitch, entityId);
|
||||
break;
|
||||
}
|
||||
case PacketTypesIn.HeldItemChange:
|
||||
case PacketTypesIn.SetHeldSlot:
|
||||
handler.OnHeldItemChange(dataTypes.ReadNextByte(packetData)); // Slot
|
||||
|
|
@ -3154,6 +3234,23 @@ namespace MinecraftClient.Protocol.Handlers
|
|||
return true; //Packet processed
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read a Holder<SoundEvent> from packet data and return its key when inline.
|
||||
/// Returns null when the holder is a registry reference.
|
||||
/// </summary>
|
||||
private string? ReadSoundEventHolderName(Queue<byte> packetData)
|
||||
{
|
||||
int soundHolderId = dataTypes.ReadNextVarInt(packetData);
|
||||
if (soundHolderId != 0)
|
||||
return null;
|
||||
|
||||
string soundName = dataTypes.ReadNextString(packetData);
|
||||
bool hasFixedRange = dataTypes.ReadNextBool(packetData);
|
||||
if (hasFixedRange)
|
||||
dataTypes.ReadNextFloat(packetData);
|
||||
return soundName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the Statistics packet for pre-1.12 legacy achievements.
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -295,6 +295,16 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="onGround">TRUE if on ground</param>
|
||||
void OnEntityTeleport(int entityID, Double x, Double y, Double z, bool onGround);
|
||||
|
||||
/// <summary>
|
||||
/// Called when an entity velocity update packet is received.
|
||||
/// Velocity values are in blocks per tick.
|
||||
/// </summary>
|
||||
/// <param name="entityID">Entity ID</param>
|
||||
/// <param name="velocityX">Velocity X</param>
|
||||
/// <param name="velocityY">Velocity Y</param>
|
||||
/// <param name="velocityZ">Velocity Z</param>
|
||||
void OnEntityVelocity(int entityID, double velocityX, double velocityY, double velocityZ);
|
||||
|
||||
/// <summary>
|
||||
/// Called when additional properties have been received for an entity
|
||||
/// </summary>
|
||||
|
|
@ -371,6 +381,17 @@ namespace MinecraftClient.Protocol
|
|||
/// <param name="affectedBlocks">Amount of affected blocks</param>
|
||||
void OnExplosion(Location location, float strength, int affectedBlocks);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a sound packet is received.
|
||||
/// </summary>
|
||||
/// <param name="soundName">Sound key if available, otherwise null</param>
|
||||
/// <param name="location">Sound location for world sounds, or null if unavailable</param>
|
||||
/// <param name="category">Sound category id</param>
|
||||
/// <param name="volume">Sound volume</param>
|
||||
/// <param name="pitch">Sound pitch</param>
|
||||
/// <param name="entityID">Source entity id for entity-sound packets, if any</param>
|
||||
void OnSoundEffect(string? soundName, Location? location, int category, float volume, float pitch, int? entityID);
|
||||
|
||||
/// <summary>
|
||||
/// Called when a player's game mode has changed
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -311,6 +311,21 @@ You can use "/fish" to control the bot manually.
|
|||
<data name="ChatBot.AutoFishing.Hook_Threshold" xml:space="preserve">
|
||||
<value>A "stationary" hook that moves above this threshold in the Y-axis will be considered to have caught a fish.</value>
|
||||
</data>
|
||||
<data name="ChatBot.AutoFishing.Enable_Velocity_Detection" xml:space="preserve">
|
||||
<value>Enable fish bite detection using fishing bobber velocity packets.</value>
|
||||
</data>
|
||||
<data name="ChatBot.AutoFishing.Velocity_Hook_Threshold" xml:space="preserve">
|
||||
<value>Velocity Y threshold (blocks/tick). Values below this are treated as a bite. Keep this value negative.</value>
|
||||
</data>
|
||||
<data name="ChatBot.AutoFishing.Enable_Sound_Detection" xml:space="preserve">
|
||||
<value>Enable fish bite detection using splash sounds near the fishing bobber.</value>
|
||||
</data>
|
||||
<data name="ChatBot.AutoFishing.Sound_Distance" xml:space="preserve">
|
||||
<value>Maximum distance (blocks) between splash sound and bobber to treat it as a bite.</value>
|
||||
</data>
|
||||
<data name="ChatBot.AutoFishing.Detection_Warmup" xml:space="preserve">
|
||||
<value>Delay (seconds) after bobber spawn before bite detection starts. Helps ignore cast-entry splash/motion.</value>
|
||||
</data>
|
||||
<data name="ChatBot.AutoFishing.Log_Fish_Bobber" xml:space="preserve">
|
||||
<value>Used to adjust the above two thresholds, which when enabled will print the change in the position of the fishhook entity upon receipt of its movement packet.</value>
|
||||
</data>
|
||||
|
|
|
|||
|
|
@ -199,6 +199,29 @@ namespace MinecraftClient.Scripting
|
|||
/// <param name="entity">Entity with updated location</param>
|
||||
public virtual void OnEntityMove(Entity entity) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when a tracked entity receives a velocity update packet.
|
||||
/// Velocity is expressed in blocks per tick.
|
||||
/// </summary>
|
||||
/// <param name="entity">Entity with updated velocity</param>
|
||||
/// <param name="velocityX">Velocity on X axis (blocks/tick)</param>
|
||||
/// <param name="velocityY">Velocity on Y axis (blocks/tick)</param>
|
||||
/// <param name="velocityZ">Velocity on Z axis (blocks/tick)</param>
|
||||
public virtual void OnEntityVelocity(Entity entity, double velocityX, double velocityY, double velocityZ) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when a sound packet is received.
|
||||
/// The sound name is null when the protocol provides only a registry id.
|
||||
/// </summary>
|
||||
/// <param name="soundName">Sound key when available, otherwise null</param>
|
||||
/// <param name="location">Sound position when available</param>
|
||||
/// <param name="category">Sound category id from packet</param>
|
||||
/// <param name="volume">Sound volume</param>
|
||||
/// <param name="pitch">Sound pitch</param>
|
||||
/// <param name="sourceEntity">Source entity for entity-sound packets when tracked</param>
|
||||
public virtual void OnSoundEffect(string? soundName, Location? location, int category, float volume, float pitch,
|
||||
Entity? sourceEntity) { }
|
||||
|
||||
/// <summary>
|
||||
/// Called when an entity rotates
|
||||
/// </summary>
|
||||
|
|
|
|||
|
|
@ -927,6 +927,7 @@ redirectFrom:
|
|||
- **Description:**
|
||||
|
||||
Automatically catch fish using a fishing rod.
|
||||
Bite detection combines bobber movement, bobber velocity, and splash sounds.
|
||||
|
||||
<div class="custom-container note"><p class="custom-container-title">Note</p>
|
||||
|
||||
|
|
@ -1103,6 +1104,66 @@ redirectFrom:
|
|||
|
||||
- **Default:** `0.2`
|
||||
|
||||
#### `Enable_Velocity_Detection`
|
||||
|
||||
- **Description:**
|
||||
|
||||
Enables bite detection using the fishing bobber velocity packet.
|
||||
|
||||
This improves reliability when bobber X/Z movement is constrained (for example by blocks near the water surface).
|
||||
|
||||
- **Available values:** `true` and `false`.
|
||||
|
||||
- **Type:** `boolean`
|
||||
|
||||
- **Default:** `true`
|
||||
|
||||
#### `Velocity_Hook_Threshold`
|
||||
|
||||
- **Description:**
|
||||
|
||||
Velocity Y threshold in blocks/tick for velocity-based bite detection.
|
||||
|
||||
Values below this threshold are considered a bite. Keep this value negative.
|
||||
|
||||
- **Type:** `float`
|
||||
|
||||
- **Default:** `-0.2`
|
||||
|
||||
#### `Enable_Sound_Detection`
|
||||
|
||||
- **Description:**
|
||||
|
||||
Enables bite detection using nearby splash sounds (`entity.fishing_bobber.splash`).
|
||||
|
||||
- **Available values:** `true` and `false`.
|
||||
|
||||
- **Type:** `boolean`
|
||||
|
||||
- **Default:** `true`
|
||||
|
||||
#### `Sound_Distance`
|
||||
|
||||
- **Description:**
|
||||
|
||||
Maximum distance in blocks between a splash sound and the tracked bobber to treat it as a bite.
|
||||
|
||||
- **Type:** `float`
|
||||
|
||||
- **Default:** `5.0`
|
||||
|
||||
#### `Detection_Warmup`
|
||||
|
||||
- **Description:**
|
||||
|
||||
Delay in seconds after bobber spawn before bite detection starts.
|
||||
|
||||
This helps ignore the initial cast-entry splash/motion.
|
||||
|
||||
- **Type:** `float`
|
||||
|
||||
- **Default:** `1.0`
|
||||
|
||||
#### `Log_Fish_Bobber`
|
||||
|
||||
- **Description:**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue