Merge pull request #57 from fishyboteso/detect_with_rgb

Change colors to rgb and read saved-variables from Chalutier Addon for color detection (0.4.6)
This commit is contained in:
Adam Saudagar 2021-05-07 20:52:53 +05:30 committed by GitHub
commit ac83c9c427
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 130 additions and 22 deletions

View File

@ -1,5 +1,5 @@
apiversion = 2 apiversion = 2
chalutier = ("Chalutier", "https://github.com/fishyboteso/Chalutier/raw/619b4ab0b8ff91746afda855542e886d27b7a794/Chalutier_1.1.2.zip", 112) chalutier = ("Chalutier", "https://www.esoui.com/downloads/dl2934/Chalutier_1.1.4.zip", 114)
lam2 = ("LibAddonMenu-2.0", "https://www.esoui.com/downloads/dl7/LibAddonMenu-2.0r32.zip", 32) lam2 = ("LibAddonMenu-2.0", "https://www.esoui.com/downloads/dl7/LibAddonMenu-2.0r32.zip", 32)
fishyqr = ("FishyQR", "https://github.com/fishyboteso/FishyQR/files/6329586/FishyQR.zip", 100) fishyqr = ("FishyQR", "https://github.com/fishyboteso/FishyQR/files/6329586/FishyQR.zip", 100)

View File

@ -60,8 +60,6 @@ def loop():
temp_screen = np.array(ImageGrab.grab(bbox=bbox)) temp_screen = np.array(ImageGrab.grab(bbox=bbox))
temp_screen = cv2.cvtColor(temp_screen, cv2.COLOR_BGR2RGB)
rect = win32gui.GetWindowRect(WindowServer.hwnd) rect = win32gui.GetWindowRect(WindowServer.hwnd)
crop = ( crop = (
rect[0] + WindowServer.windowOffset, rect[1] + WindowServer.titleOffset, rect[2] - WindowServer.windowOffset, rect[0] + WindowServer.windowOffset, rect[1] + WindowServer.titleOffset, rect[2] - WindowServer.windowOffset,

View File

@ -10,12 +10,14 @@ import logging
from fishy.engine.semifisher.fishing_event import FishEvent from fishy.engine.semifisher.fishing_event import FishEvent
from fishy.engine.common.window import WindowClient from fishy.engine.common.window import WindowClient
from fishy.engine.semifisher.fishing_mode import FishingMode from fishy.engine.semifisher.fishing_mode import Colors, FishingMode
from fishy.engine.common.IEngine import IEngine from fishy.engine.common.IEngine import IEngine
from fishy.engine.semifisher import fishing_mode, fishing_event from fishy.engine.semifisher import fishing_mode, fishing_event
from fishy.engine.semifisher.pixel_loc import PixelLoc from fishy.engine.semifisher.pixel_loc import PixelLoc
from fishy.helper.luaparser import sv_color_extract
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from fishy.gui import GUI from fishy.gui import GUI
@ -31,11 +33,13 @@ class SemiFisherEngine(IEngine):
code explained in comments in detail code explained in comments in detail
""" """
fishing_event.init() fishing_event.init()
self.fishPixWindow = WindowClient(color=cv2.COLOR_RGB2HSV) self.fishPixWindow = WindowClient()
# check for game window and stuff # check for game window and stuff
self.gui.bot_started(True) self.gui.bot_started(True)
sv_color_extract(Colors)
if self.get_gui: if self.get_gui:
logging.info("Starting the bot engine, look at the fishing hole to start fishing") logging.info("Starting the bot engine, look at the fishing hole to start fishing")
Thread(target=self._wait_and_check).start() Thread(target=self._wait_and_check).start()

View File

@ -98,11 +98,14 @@ def fisher_callback(event: State):
State.FIGHT: on_fight, State.FIGHT: on_fight,
State.DEAD: on_dead State.DEAD: on_dead
} }
try: try:
callbacks_map[event]() callbacks_map[event]()
FishEvent.previousState = event FishEvent.previousState = event
except KeyError as ex: except KeyError as ex:
pass logging.error("KeyError: State " + str(event) + " is not known.")
except TypeError as ex:
logging.error("TypeError when reading state: " + str(event))
def on_idle(): def on_idle():

View File

@ -5,17 +5,32 @@ subscribers = []
class State(Enum): class State(Enum):
IDLE = [ 0, 0, 255] IDLE = 0
LOOKAWAY = [150, 255, 76] LOOKAWAY = 1
LOOKING = [100, 255, 101] LOOKING = 2
DEPLETED = [ 30, 255, 76] DEPLETED = 3
NOBAIT = [ 96, 255, 255] NOBAIT = 5
FISHING = [ 18, 165, 213] FISHING = 6
REELIN = [ 60, 255, 204] REELIN = 7
LOOT = [ 0, 255, 204] LOOT = 8
INVFULL = [ 0, 255, 51] INVFULL = 9
FIGHT = [120, 255, 204] FIGHT = 14
DEAD = [ 0, 0, 51] DEAD = 15
Colors = {
State.IDLE : [255, 255, 255],
State.LOOKAWAY : [ 76, 0, 76],
State.LOOKING : [101, 69, 0],
State.DEPLETED : [ 0, 76, 76],
State.NOBAIT : [255, 204, 0],
State.FISHING : [ 75, 156, 213],
State.REELIN : [ 0, 204, 0],
State.LOOT : [ 0, 0, 204],
State.INVFULL : [ 0, 0, 51],
State.FIGHT : [204, 0, 0],
State.DEAD : [ 51, 51, 51]
}
def _notify(event): def _notify(event):
for subscriber in subscribers: for subscriber in subscribers:
@ -27,16 +42,16 @@ class FishingMode:
PrevMode = State.IDLE PrevMode = State.IDLE
def loop(hsv): def loop(rgb):
""" """
Executed in the start of the main loop in fishy.py Executed in the start of the main loop in fishy.py
Changes modes, calls mode events (callbacks) when mode is changed Changes modes, calls mode events (callbacks) when mode is changed
:param hsv: hsv read by the bot :param rgb: rgb read by the bot
""" """
FishingMode.CurrentMode = State.IDLE FishingMode.CurrentMode = State.IDLE
for s in State: for s in State:
if all(hsv == s.value): if all(rgb == Colors[s]):
FishingMode.CurrentMode = s FishingMode.CurrentMode = s
if FishingMode.CurrentMode != FishingMode.PrevMode: if FishingMode.CurrentMode != FishingMode.PrevMode:

View File

@ -1,4 +1,6 @@
from .auto_update import auto_upgrade, upgrade_avail, versions from .auto_update import auto_upgrade, upgrade_avail, versions
from .config import Config from .config import Config
from .helper import open_web, initialize_uid, install_thread_excepthook, unhandled_exception_logging, manifest_file, \ from .helper import open_web, initialize_uid, install_thread_excepthook, unhandled_exception_logging, manifest_file, \
create_shortcut_first, addon_exists, get_addonversion, install_addon, remove_addon, restart, create_shortcut, not_implemented, update create_shortcut_first, addon_exists, get_addonversion, install_addon, remove_addon, restart, create_shortcut, \
not_implemented, update, get_savedvarsdir
from .luaparser import sv_color_extract

View File

@ -145,11 +145,18 @@ def create_shortcut(anti_ghosting: bool):
logging.error("Couldn't create shortcut") logging.error("Couldn't create shortcut")
def get_savedvarsdir():
# noinspection PyUnresolvedReferences
from win32com.shell import shell, shellcon
documents = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0)
return os.path.join(documents, "Elder Scrolls Online", "live", "SavedVariables")
def get_addondir(): def get_addondir():
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from win32com.shell import shell, shellcon from win32com.shell import shell, shellcon
documents = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0) documents = shell.SHGetFolderPath(0, shellcon.CSIDL_PERSONAL, None, 0)
return os.path.join(documents, "Elder Scrolls Online", "live", "Addons") return os.path.join(documents, "Elder Scrolls Online", "live", "Addons")
def addon_exists(name, url=None, v=None): def addon_exists(name, url=None, v=None):

79
fishy/helper/luaparser.py Normal file
View File

@ -0,0 +1,79 @@
import os
import logging
from math import floor
from .helper import get_savedvarsdir
def _sv_parser(path):
try:
with open(path, "r") as f:
lua = f.read()
"""
bring lua saved-var file into a useable format:
- one line per expression (add \n where needed)
- remove all redundant characters
- make lowercase, split into list of expressions
- remove empty expressions
EXPRESSIONS: A) List-Start "name=", B) Variable assignment "name=val", C) List End "}"
"""
for old, new in ((",","\n"), ("{","{\n"), ("}","}\n"), ("{",""), (",", ""), ("[", ""), ("]", ""), ('"', ""), (" ", "")):
lua = lua.replace(old, new)
lua = lua.lower().split("\n")
lua = [expression for expression in lua if expression]
"""
the lua saved-var file is parsed to a tree of dicts
each line represents either one node in the tree or the end of a subtree
the last symbol of each line decides the type of the node (branch vertex or leaf)
"""
stack = []
root = (dict(),"root")
stack.append(root)
for line in lua:
if line == "":
break
if line[-1] == '=': #subtree start
t = dict()
tname = line.split("=")[0]
stack.append((t,tname))
elif line[-1] == '}': #subtree end
t = stack.pop()
tp = stack.pop()
tp[0][t[1]] = t[0]
stack.append(tp)
else: #new element in tree
name,val = line.split("=")
t = stack.pop()
t[0][name] = val
stack.append(t)
return root[0]
except Exception as ex:
logging.error("Error: '" + str(ex) + "' occured, while parsing ESO variables.")
return None
def sv_color_extract(Colors):
root = _sv_parser(os.path.join(get_savedvarsdir(), "Chalutier.lua"))
if root == None:
return Colors
for i in range(4):
name, root = root.popitem()
colors = []
for i in root["colors"]:
"""
ingame representation of colors range from 0 to 1 in float
these values are scaled by 255
"""
rgb=[
floor(float(root["colors"][i]["r"])*255),
floor(float(root["colors"][i]["g"])*255),
floor(float(root["colors"][i]["b"])*255)
]
colors.append(rgb)
for i,c in enumerate(Colors):
Colors[c] = colors[i]
return Colors