Source code for mc_autofisher.fisher
"""
Automates Minecraft fishing by watching a portion of the screen for the subtitle
text "Fishing Bobber splashes", and double clicking the right mouse button when it
is found, allowing it to reel in and recast the line every time a fish appears.
"""
import sys
import time
import json
import pyscreenshot as ig
import pytesseract as pt
from pynput.keyboard import Key, Listener
from pynput.mouse import Button, Controller
from Levenshtein._levenshtein import distance as levenshtein
def _keyDown(e):
"""Callback for keyboard listener, closes
the listener if the Enter key is pressed
"""
if e == Key.enter:
print('Exiting')
return False
return True
[docs]def match(screenText, targetText="Fishing Bobber", threshold=5):
"""Takes in some text and iterates through it line by line,
checking to see if any of the lines contain something similar
to the target text using Levenshtein distance
Arguments:
screenText (str)
The text to search for a match in
targetText (`string`, optional)
The text to search for, defaults to "Fishing Bobber"
threshold: (`int`, optional)
The maximum acceptable Levenshtein distance to
be considered a match, defaults to 5
Returns:
True if a match was found, False otherwise
Examples:
>>> match("Fishing Bobber")
True
>>> match("Fishing Gobber")
True
>>> match("Fishing")
False
>>> match("Some text Fishing Bobber some more text")
True
"""
ngram_size = len(targetText.split())
for line in screenText.splitlines():
line = line.split()
for i in range(len(line)-ngram_size+1):
ngram = " ".join(line[i:i+ngram_size])
if levenshtein(ngram, targetText) <= threshold:
return True
return False
[docs]def start(bbox, allowed_error=5, tesspath=""):
"""Takes in bounding box coordinates and begins watching
that section of the screen for the text "Fishing Bobber splashes",
double clicking the right mouse button when it sees it to reel in
the fish and recast the line. Press enter to quit.
Arguments:
bbox (list)
A list of 4 numbers (x1, y1, x2, y2) obtained from the screengrabber
program, where (x1, y1) is the top left corner of the bounding box
and (x2, y2) is the lower right corner
allowed_error (`int`, optional)
The margin of error (measured in Levenshtein distance) allowed for
text matching, i.e. 'Fishing Gobber splashes' has an error of 1
tesspath (`str`, optional)
The path to your Tesseract installation, leave blank to use default
"""
if tesspath != "":
pt.pytesseract.tesseract_path = tesspath
mouse = Controller()
listener = Listener(on_press=_keyDown)
listener.start()
timeout = 45 # Fish always appears within 45 seconds, if we wait longer than this then recast the line
cast_time = time.monotonic()
while listener.is_alive():
# Grab portion of screen defined in config file & send it to tesseract
screen = ig.grab(bbox=bbox)
screen_text = pt.image_to_string(screen)
if match(screen_text, threshold=allowed_error) or time.monotonic() - cast_time > timeout:
# Either fish was found or timeout was exceeded, reel in the line and cast it again
mouse.click(Button.right, 2)
cast_time = time.monotonic()
time.sleep(0.25)
listener.join()