mirror of
https://github.com/fishyboteso/fishyboteso.git
synced 2024-08-30 18:32:13 +00:00
states for when playing/recording is running, added error message when window is not found in full auto, added beep sound when hotkey is pressed, made hotkey callable Optional
This commit is contained in:
@ -6,6 +6,7 @@ include fishy/ProvisionsChalutier.zip
|
||||
include fishy/FooAddon.zip
|
||||
include fishy/fishybot_logo.png
|
||||
include fishy/sound.mp3
|
||||
include fishy/beep.wav
|
||||
|
||||
recursive-include tests *
|
||||
recursive-exclude * __pycache__
|
||||
|
BIN
fishy/beep.wav
Normal file
BIN
fishy/beep.wav
Normal file
Binary file not shown.
@ -1,36 +1,46 @@
|
||||
import logging
|
||||
|
||||
from fishy.helper import hotkey
|
||||
from fishy.helper import hotkey, helper
|
||||
|
||||
from fishy.engine.fullautofisher.engine import FullAuto
|
||||
from fishy.helper.config import config
|
||||
from fishy.helper.hotkey import Key
|
||||
|
||||
|
||||
def get_controls(engine: FullAuto):
|
||||
from fishy.engine.fullautofisher.calibrate import Calibrate
|
||||
from fishy.engine.fullautofisher.recorder import Recorder
|
||||
from fishy.engine.fullautofisher.player import Player
|
||||
|
||||
controls = [
|
||||
# ("MAIN", {
|
||||
# Key.RIGHT: Player(engine).start_route,
|
||||
# Key.UP: Calibrate(engine).callibrate,
|
||||
# Key.LEFT: Recorder(engine).start_recording,
|
||||
# Key.DOWN: change_state
|
||||
# }),
|
||||
# ("COODS", {
|
||||
# Key.RIGHT: print_coods,
|
||||
# Key.UP: engine.update_crop,
|
||||
# Key.LEFT: toggle_show,
|
||||
# Key.DOWN: change_state
|
||||
# }),
|
||||
# ("TEST1", {
|
||||
# Key.RIGHT: set_target,
|
||||
# Key.UP: rotate_to_90,
|
||||
# Key.LEFT: move_to_target,
|
||||
# Key.DOWN: change_state
|
||||
# })
|
||||
("MODE_SELECT", {
|
||||
Key.RIGHT: (lambda: engine.controls.select_mode("CALIBRATE"), "calibrate mode"),
|
||||
Key.UP: (lambda: engine.controls.select_mode("PLAY"), "play mode"),
|
||||
Key.LEFT: (lambda: engine.controls.select_mode("RECORD"), "record mode"),
|
||||
Key.DOWN: (lambda: engine.controls.select_mode("TEST"), "test mode")
|
||||
}),
|
||||
("CALIBRATE", {
|
||||
Key.RIGHT: (engine.calibrate.update_crop, "cropping"),
|
||||
Key.UP: (engine.calibrate.walk_calibrate, "walking"),
|
||||
Key.LEFT: (engine.calibrate.rotate_calibrate, "rotation"),
|
||||
Key.DOWN: (engine.calibrate.time_to_reach_bottom_callibrate, "look up down")
|
||||
}),
|
||||
("PLAY/RECORD", {
|
||||
Key.RIGHT: (Player(engine).toggle_move, "start/stop play"),
|
||||
Key.UP: (Recorder(engine).toggle_recording, "start/stop record"),
|
||||
Key.LEFT: (None, "not implemented"),
|
||||
Key.DOWN: (None, "not implemented")
|
||||
}),
|
||||
("TEST1", {
|
||||
Key.RIGHT: (engine.test.print_coods, "print coordinates"),
|
||||
Key.UP: (engine.test.look_for_hole, "look for hole up down"),
|
||||
Key.LEFT: (None, "not implemented"),
|
||||
Key.DOWN: (lambda: engine.controls.select_mode("TEST2"), "show next")
|
||||
}),
|
||||
("TEST2", {
|
||||
Key.RIGHT: (engine.test.set_target, "set target"),
|
||||
Key.UP: (engine.test.move_to_target, "move to target"),
|
||||
Key.LEFT: (engine.test.rotate_to_target, "rotate to target"),
|
||||
Key.DOWN: (lambda: engine.controls.select_mode("TEST1"), "show previous")
|
||||
})
|
||||
]
|
||||
|
||||
return controls
|
||||
@ -41,15 +51,20 @@ class Controls:
|
||||
self.current_menu = first - 1
|
||||
self.controls = controls
|
||||
|
||||
def change_state(self):
|
||||
self.current_menu += 1
|
||||
if self.current_menu == len(self.controls):
|
||||
self.current_menu = 0
|
||||
def initialize(self):
|
||||
self.select_mode("MODE_SELECT")
|
||||
|
||||
def select_mode(self, mode):
|
||||
self.current_menu = 0
|
||||
for i, control in enumerate(self.controls):
|
||||
if mode == control[0]:
|
||||
self.current_menu = i
|
||||
|
||||
help_str = F"CONTROLS: {self.controls[self.current_menu][0]}"
|
||||
for key, func in self.controls[self.current_menu][1].items():
|
||||
for key, meta in self.controls[self.current_menu][1].items():
|
||||
func, name = meta
|
||||
hotkey.set_hotkey(key, func)
|
||||
help_str += f"\n{key.value}: {func.__name__}"
|
||||
help_str += f"\n{key.value}: {name}"
|
||||
logging.info(help_str)
|
||||
|
||||
def unassign_keys(self):
|
||||
@ -57,4 +72,4 @@ class Controls:
|
||||
for c in self.controls:
|
||||
for k in c[1].keys():
|
||||
if k not in keys:
|
||||
hotkey.free_key(k)
|
||||
hotkey.free_key(k)
|
||||
|
@ -1,7 +1,9 @@
|
||||
import math
|
||||
import os
|
||||
import tempfile
|
||||
import traceback
|
||||
import uuid
|
||||
from enum import Enum
|
||||
from zipfile import ZipFile
|
||||
|
||||
import cv2
|
||||
@ -42,8 +44,16 @@ def image_pre_process(img):
|
||||
return img
|
||||
|
||||
|
||||
class State(Enum):
|
||||
NONE = 0
|
||||
PLAYING = 1
|
||||
RECORDING = 2
|
||||
OTHER = 3
|
||||
|
||||
|
||||
class FullAuto(IEngine):
|
||||
rotate_by = 30
|
||||
state = State.NONE
|
||||
|
||||
def __init__(self, gui_ref):
|
||||
from fishy.engine.fullautofisher.controls import Controls
|
||||
@ -56,9 +66,9 @@ class FullAuto(IEngine):
|
||||
self._curr_rotate_y = 0
|
||||
|
||||
self.fisher = SemiFisherEngine(None)
|
||||
self.controls = Controls(controls.get_controls(self))
|
||||
self.calibrate = Calibrate(self)
|
||||
self.test = Test(self)
|
||||
self.controls = Controls(controls.get_controls(self))
|
||||
|
||||
@property
|
||||
def show_crop(self):
|
||||
@ -75,24 +85,31 @@ class FullAuto(IEngine):
|
||||
self.fisher.toggle_start()
|
||||
|
||||
self.window = WindowClient(color=cv2.COLOR_RGB2GRAY, show_name="Full auto debug")
|
||||
if self.calibrate.crop is None:
|
||||
self.calibrate.update_crop(enable_crop=False)
|
||||
self.window.crop = self.calibrate.crop
|
||||
|
||||
if not is_tesseract_installed():
|
||||
logging.info("tesseract not found")
|
||||
downlaoad_and_extract_tesseract()
|
||||
try:
|
||||
if self.calibrate.crop is None:
|
||||
self.calibrate.update_crop(enable_crop=False)
|
||||
self.window.crop = self.calibrate.crop
|
||||
|
||||
self.controls.change_state()
|
||||
while self.start and WindowClient.running():
|
||||
self.window.show(self.show_crop, func=image_pre_process)
|
||||
if not self.show_crop:
|
||||
time.sleep(0.1)
|
||||
if not is_tesseract_installed():
|
||||
logging.info("tesseract not found")
|
||||
downlaoad_and_extract_tesseract()
|
||||
|
||||
self.controls.initialize()
|
||||
while self.start and WindowClient.running():
|
||||
self.window.show(self.show_crop, func=image_pre_process)
|
||||
if not self.show_crop:
|
||||
time.sleep(0.1)
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
if not self.window.get_capture():
|
||||
logging.error("Game window not found")
|
||||
|
||||
self.gui.bot_started(False)
|
||||
self.controls.unassign_keys()
|
||||
self.window.show(False)
|
||||
logging.info("Quit")
|
||||
logging.info("Quitting")
|
||||
self.window.destory()
|
||||
self.fisher.toggle_start()
|
||||
|
||||
|
@ -4,63 +4,59 @@ from pprint import pprint
|
||||
|
||||
from fishy.engine.semifisher import fishing_event, fishing_mode
|
||||
|
||||
from fishy.engine.fullautofisher.engine import FullAuto
|
||||
from fishy.engine.fullautofisher.engine import FullAuto, State
|
||||
|
||||
from fishy.helper import hotkey, helper
|
||||
from fishy.helper import helper
|
||||
from fishy.helper.config import config
|
||||
from fishy.helper.hotkey import Key
|
||||
|
||||
|
||||
def _get_rec_file():
|
||||
file = config.get("full_auto_rec_file")
|
||||
|
||||
if not file:
|
||||
logging.error("Please select a fishy file first from config")
|
||||
return None
|
||||
|
||||
file = open(file, 'rb')
|
||||
data = pickle.load(file)
|
||||
file.close()
|
||||
pprint(data)
|
||||
if "full_auto_path" not in data:
|
||||
logging.error("invalid file")
|
||||
return None
|
||||
return data["full_auto_path"]
|
||||
|
||||
|
||||
class Player:
|
||||
def __init__(self, engine: 'FullAuto'):
|
||||
self.recording = False
|
||||
self.engine = engine
|
||||
self.timeline = []
|
||||
self.hole_complete_flag = False
|
||||
self.start_moving_flag = False
|
||||
|
||||
def _mark_hole(self):
|
||||
coods = self.engine.get_coods()
|
||||
self.timeline.append(("check_fish", coods))
|
||||
def toggle_move(self):
|
||||
if FullAuto.state != State.PLAYING and FullAuto.state != State.NONE:
|
||||
return
|
||||
|
||||
def _start_moving(self):
|
||||
self.start_moving_flag = not self.start_moving_flag
|
||||
|
||||
def _stop_recording(self):
|
||||
self.recording = False
|
||||
if self.start_moving_flag:
|
||||
self._start_route()
|
||||
|
||||
def _hole_complete_callback(self, e):
|
||||
if e == fishing_event.State.IDLE:
|
||||
self.hole_complete_flag = True
|
||||
|
||||
def start_route(self):
|
||||
file = config.get("full_auto_rec_file")
|
||||
|
||||
if not file:
|
||||
logging.error("Please select a fishy file first from config")
|
||||
def _start_route(self):
|
||||
FullAuto.state = State.PLAYING
|
||||
timeline = _get_rec_file()
|
||||
if not timeline:
|
||||
return
|
||||
|
||||
file = open(file, 'rb')
|
||||
data = pickle.load(file)
|
||||
file.close()
|
||||
pprint(data)
|
||||
if "full_auto_path" not in data:
|
||||
logging.error("invalid file")
|
||||
return
|
||||
self.timeline = data["full_auto_path"]
|
||||
|
||||
# wait until f8 is pressed
|
||||
logging.info("press f8 to start")
|
||||
|
||||
self.start_moving_flag = False
|
||||
hotkey.set_hotkey(Key.F8, self._start_moving)
|
||||
helper.wait_until(lambda: self.start_moving_flag)
|
||||
|
||||
logging.info("starting, press f8 to stop")
|
||||
forward = True
|
||||
i = 0
|
||||
while self.start_moving_flag:
|
||||
action = self.timeline[i]
|
||||
action = timeline[i]
|
||||
|
||||
if action[0] == "move_to":
|
||||
self.engine.move_to(action[1])
|
||||
@ -84,11 +80,12 @@ class Player:
|
||||
fishing_mode.subscribers.remove(self._hole_complete_callback)
|
||||
|
||||
i += 1 if forward else -1
|
||||
if i >= len(self.timeline):
|
||||
if i >= len(timeline):
|
||||
forward = False
|
||||
i = len(self.timeline) - 1
|
||||
i = len(timeline) - 1
|
||||
elif i < 0:
|
||||
forward = True
|
||||
i = 0
|
||||
|
||||
logging.info("stopped")
|
||||
FullAuto.state = State.NONE
|
||||
|
@ -4,7 +4,7 @@ import time
|
||||
from pprint import pprint
|
||||
from tkinter.filedialog import asksaveasfile
|
||||
|
||||
from fishy.engine.fullautofisher.engine import FullAuto
|
||||
from fishy.engine.fullautofisher.engine import FullAuto, State
|
||||
|
||||
from fishy.helper import hotkey
|
||||
from fishy.helper.hotkey import Key
|
||||
@ -12,6 +12,7 @@ from fishy.helper.hotkey import Key
|
||||
|
||||
class Recorder:
|
||||
recording_fps = 1
|
||||
mark_hole_key = Key.F8
|
||||
|
||||
def __init__(self, engine: FullAuto):
|
||||
self.recording = False
|
||||
@ -23,15 +24,19 @@ class Recorder:
|
||||
self.timeline.append(("check_fish", coods))
|
||||
logging.info("check_fish")
|
||||
|
||||
def _stop_recording(self):
|
||||
self.recording = False
|
||||
def toggle_recording(self):
|
||||
if FullAuto.state != State.RECORDING and FullAuto.state != State.NONE:
|
||||
return
|
||||
|
||||
def start_recording(self):
|
||||
logging.info("f7 for marking hole, f8 to stop recording")
|
||||
hotkey.set_hotkey(Key.F7, self._mark_hole)
|
||||
hotkey.set_hotkey(Key.F8, self._stop_recording)
|
||||
self.recording = not self.recording
|
||||
if self.recording:
|
||||
self._start_recording()
|
||||
|
||||
def _start_recording(self):
|
||||
FullAuto.state = State.RECORDING
|
||||
logging.info("f8 to stop recording")
|
||||
hotkey.set_hotkey(Recorder.mark_hole_key, self._mark_hole)
|
||||
|
||||
self.recording = True
|
||||
self.timeline = []
|
||||
|
||||
while self.recording:
|
||||
@ -47,6 +52,8 @@ class Recorder:
|
||||
else:
|
||||
logging.warning("Took too much time to record")
|
||||
|
||||
hotkey.free_key(Recorder.mark_hole_key)
|
||||
|
||||
files = [('Fishy File', '*.fishy')]
|
||||
file = None
|
||||
while not file:
|
||||
@ -55,4 +62,5 @@ class Recorder:
|
||||
pprint(data)
|
||||
pickle.dump(data, file)
|
||||
file.close()
|
||||
FullAuto.state = State.NONE
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
from enum import Enum
|
||||
from threading import Thread
|
||||
from typing import Dict, Callable
|
||||
from typing import Dict, Callable, Optional
|
||||
|
||||
import keyboard
|
||||
from playsound import playsound
|
||||
|
||||
from fishy.helper import helper
|
||||
|
||||
@ -18,22 +19,28 @@ class Key(Enum):
|
||||
RIGHT = "right"
|
||||
|
||||
|
||||
_hotkeys: Dict[Key, Callable] = {}
|
||||
_hotkeys: Dict[Key, Optional[Callable]] = {}
|
||||
|
||||
|
||||
def _run_callback(k):
|
||||
return lambda: Thread(target=_hotkeys[k]).start()
|
||||
def _get_callback(k):
|
||||
def callback():
|
||||
if not _hotkeys[k]:
|
||||
return
|
||||
|
||||
playsound(helper.manifest_file("beep.wav"), False)
|
||||
Thread(target=_hotkeys[k]).start()
|
||||
return callback
|
||||
|
||||
|
||||
def initalize():
|
||||
for k in Key:
|
||||
_hotkeys[k] = helper.empty_function
|
||||
keyboard.add_hotkey(k.value, _run_callback(k))
|
||||
_hotkeys[k] = None
|
||||
keyboard.add_hotkey(k.value, _get_callback(k))
|
||||
|
||||
|
||||
def set_hotkey(key: Key, func: Callable):
|
||||
def set_hotkey(key: Key, func: Optional[Callable]):
|
||||
_hotkeys[key] = func
|
||||
|
||||
|
||||
def free_key(k: Key):
|
||||
set_hotkey(k, helper.empty_function)
|
||||
set_hotkey(k, None)
|
||||
|
Reference in New Issue
Block a user