-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautofisher.py
196 lines (172 loc) · 6.83 KB
/
autofisher.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# import required libraries
import argparse
import signal
from threading import Timer
from time import time
from pprint import pprint
import cv2
import numpy as np
from numpy.core.fromnumeric import std
from numpy.lib.function_base import average
import pyautogui
from vidgear.gears import ScreenGear
# Setup globals
holdoff_good = True
running = True
def cast():
pyautogui.click(button='right')
def holdoff_good_callback():
global holdoff_good
holdoff_good = True
def signal_handler(sig, frame):
global running
running = False
def main():
# Stores if we are waiting for the holdoff timer to return
global holdoff_good
# Stores if ctrl + c has been pressed
global running
# define dimensions of screen w.r.t to given monitor to be captured
options = {
'top': args.top,
'left': args.left,
'width': args.width,
'height': args.length
}
# open video stream with defined parameters
stream = ScreenGear(
monitor=args.monitor,
logging=True,
**options
).start()
# Setup SIGINT handler for ctrl + c in a slightly more elegant way than
# try/except with KeyboardInterrupt
signal.signal(signal.SIGINT, signal_handler)
catch_times = []
previous_catch = time()
# Loop until ctrl + c is pressed
while running:
# read frames from stream
frame = stream.read()
# check for frame if Nonetype
if frame is None:
print('Error grabing frame data! Exiting.')
break
# Knock out the color from the image to make thresholding easier
frame[:,:,0] = np.zeros([frame.shape[0], frame.shape[1]])
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Set all pixles dimmer than args.threshold to 0
_, frame = cv2.threshold(frame, args.threshold, 255, cv2.THRESH_BINARY)
# If we are still inside the holdoff period we skip the frame summing
# and checking
if holdoff_good:
# Sum up all pixles in the frame, when the bobber is underwater
# the scene should be all 0s.
frame_sum = frame.sum()
if frame_sum == 0 :
Timer(args.delay, holdoff_good_callback).start()
if not args.debug:
Timer(args.recast, cast).start()
holdoff_good = False
if args.debug:
print('Caught!')
else:
pyautogui.click(button='right')
cur_catch = time()
catch_times.append(cur_catch - previous_catch)
previous_catch = cur_catch
print(f'Total Catches {len(catch_times)}, Avg Catch Time: {round(average(catch_times), 5)}, STD: {round(std(catch_times), 5)}, Min: {round(min(catch_times), 5)}, Max: {round(max(catch_times), 5)}', end='\r')
# Show output window if we are in debug mode
if args.debug or args.show:
cv2.imshow("Output Frame", frame)
# check for 'q' key if pressed
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
print('')
break
# close output window
cv2.destroyAllWindows()
# safely close video stream
stream.stop()
if __name__ == "__main__":
parser = argparse.ArgumentParser(
'AutoFisher',
description='A program for automatically realling and casting a '
'fishing poll in Minecraft based on screen capture. '
'Be sure to turn off your HUD with F1 and with your '
'fishing rod already cast.'
)
parser.add_argument('--debug',
help='Disable casting of rod and show the captured region of the screen'
' after thresholding and RGB->BW color cut. Useful for debugging'
' undesired casts.',
action='store_true'
)
parser.add_argument('-t', '--threshold',
help='Sets the cutoff point where when below, a captured pixel '
'will be set to 0. Will likely need to be adjusted based on '
'background content of scene. Defaults to 150 out of 255',
type=int,
default=127,
choices=range(0,256),
metavar="[0-255]"
)
parser.add_argument('-d', '--delay',
help='Sets the holdoff between when the program detects a bite and '
'when it starts looking again in seconds. Defaults to 3.0 '
'seconds',
type=float,
default=3.0
)
parser.add_argument('-m', '--monitor',
help='The monitor number Minecraft is running on. Defaults to 2 '
'because thats the one that displays it on my system.',
type=int,
default=2
)
parser.add_argument('-y', '--top',
help='The number of pixles down from the top of the screen to start '
'capturing from. Defaults to 500 as that is a reasonable value '
'for fullscreen minecraft running on a 1920x1080 monitor.',
type=int,
default=500
)
parser.add_argument('-x', '--left',
help='The number of pixles down from the left of the screen to start '
'capturing from. Defaults to 900 as that is a reasonable value '
'for fullscreen minecraft running on a 1920x1080 monitor.',
type=int,
default=900
)
parser.add_argument('-l', '--length',
help='The number of pixles down from y to start capturing from. '
'Defaults to 500 as gives enough length to track the bobber even '
'if it comes in contact with a fish on re-cast. This value may '
'require fiddling depending on how you are casting and your '
'surroundings',
type=int,
default=500
)
parser.add_argument('-w', '--width',
help='The number of pixles left of x to start capturing from. '
'Defaults to 100 as gives enough length to track the bobber even '
'when it varies side to side while cutting down on noise. This '
'value may require fiddling depending on how you are casting and '
'your surroundings',
type=int,
default=200
)
parser.add_argument('-r', '--recast',
help='The delay in seconds between realing the rod in and casting it '
'again in seconds. Defaults to 1.0',
type=float,
default=1.0
)
parser.add_argument('-s', '--show',
help='Show the output window after thresholding and RGB->BW color '
'cut. Useful for debugging undesired casts.',
action='store_true',
default=False
)
args = parser.parse_args()
main()