diff --git a/config/game.ini b/config/game.ini index 57e00a1..19cbf23 100644 --- a/config/game.ini +++ b/config/game.ini @@ -250,7 +250,7 @@ dia_b_layout_bold=1129,148, 1129,148, 1129,148, 1129,148, 1129,148, 1129,148 dia_c_layout_bold=1112,503, 1112,503, 1112,503, 1112,503, 1112,503, 1112,503, 1112,503, 1112,503 ; Andariel (A1 Catacombs) - placeholder, fill in real coords later a1_andy_level3_enter=0,0 -a1_andy_level4_enter=0,0,0 +a1_andy_level4_enter=0,0 a1_andy_safe_dist=0,0 ; Countess (A1 Forgotten Tower) - placeholder, fill in real coords later a1_tower_level2_enter=0,0 diff --git a/config/params.ini b/config/params.ini index 37fa78f..dad7885 100644 --- a/config/params.ini +++ b/config/params.ini @@ -138,7 +138,6 @@ atk_len_cs_trashmobs=2.0 atk_len_diablo_deseis=5.0 atk_len_diablo_infector=4.0 atk_len_diablo_vizier=2.0 -atk_len_diablo=3.0 cs_mob_detect=0 ; cs_town_visits is currently broken, ignore for now cs_town_visits=0 diff --git a/src/bnip/lexer.py b/src/bnip/lexer.py index 5e7f63e..89beb83 100644 --- a/src/bnip/lexer.py +++ b/src/bnip/lexer.py @@ -16,7 +16,10 @@ from bnip.BNipExceptions import BNipSyntaxError from enum import Enum import re -from rapidfuzz.string_metric import levenshtein +try: + from rapidfuzz.string_metric import levenshtein +except ImportError: + from rapidfuzz.distance import Levenshtein as levenshtein WHITESPACE = " \t\n\r\v\f" DIGITS = "0123456789.-" # ! Put % back in here when ready to use percentages. diff --git a/src/d2r_image/bnip_helpers.py b/src/d2r_image/bnip_helpers.py index 0bce62c..6e6f032 100644 --- a/src/d2r_image/bnip_helpers.py +++ b/src/d2r_image/bnip_helpers.py @@ -2,7 +2,10 @@ from d2r_image.d2data_lookup import find_base_item_from_magic_item_text, find_pa from d2r_image.data_models import HoveredItem, ItemQuality from d2r_image.bnip_data import BNIP_ALIAS_STAT_PATTERNS, NTIP_ALIAS_QUALITY_MAP, PROPS_TO_SKILLID, BNIP_ALIAS_STAT_PATTERNS_NO_INTS, BNIP_ITEM_TYPE_DATA from d2r_image.processing_data import Runeword -from rapidfuzz.string_metric import levenshtein +try: + from rapidfuzz.string_metric import levenshtein +except ImportError: + from rapidfuzz.distance import Levenshtein as levenshtein from bnip.NTIPAliasType import NTIPAliasType as NTIP_TYPES from bnip.NTIPAliasStat import NTIPAliasStat as NTIP_STATS from logger import Logger diff --git a/src/screen.py b/src/screen.py index 95896e9..147ff91 100644 --- a/src/screen.py +++ b/src/screen.py @@ -1,13 +1,15 @@ import numpy as np -from mss import mss +import os from logger import Logger from utils.misc import WindowSpec, find_d2r_window, wait from config import Config import threading import time -sct = mss() -monitor_roi = sct.monitors[0] +# Defer mss() and monitor setup until first grab() so the module can import +# on headless Linux (no X display) without crashing. +sct = None +monitor_roi = {"top": 0, "left": 0, "width": 1280, "height": 720} found_offsets = False monitor_x_range = None monitor_y_range = None @@ -72,6 +74,15 @@ def grab(force_new: bool = False) -> np.ndarray: global monitor_roi global cached_img global last_grab + global sct + if sct is None: + from mss import mss as mss_factory + sct = mss_factory() + m0 = sct.monitors[0] + monitor_roi["left"] = m0["left"] + monitor_roi["top"] = m0["top"] + monitor_roi["width"] = m0["width"] + monitor_roi["height"] = m0["height"] # with 25fps we have 40ms per frame. If we check for 20ms range to make sure we can still get each frame if we want. with cached_img_lock: if not force_new and cached_img is not None and last_grab is not None and (time.perf_counter() - last_grab) < 0.02: diff --git a/src/utils/custom_mouse.py b/src/utils/custom_mouse.py index f3e55a7..ca95d84 100644 --- a/src/utils/custom_mouse.py +++ b/src/utils/custom_mouse.py @@ -1,6 +1,14 @@ # Mostly copied from: https://github.com/patrikoss/pyclick import mouse as _mouse -from mouse import _winmouse +import os +if os.name == 'nt': + from mouse import _winmouse +else: + # Linux stub — _winmouse is only used in _move_to() which wraps calls in os.name checks + class _winmouse: + @staticmethod + def move_to(x, y): + _mouse.move(x, y) import pytweening import numpy as np import random diff --git a/src/utils/misc.py b/src/utils/misc.py index 6724bfa..21d94ca 100644 --- a/src/utils/misc.py +++ b/src/utils/misc.py @@ -15,14 +15,50 @@ import cv2 import os from math import cos, sin, dist import subprocess -from win32con import HWND_TOPMOST, SWP_NOMOVE, SWP_NOSIZE, HWND_NOTOPMOST -from win32gui import GetWindowText, SetWindowPos, EnumWindows, GetClientRect, ClientToScreen -from win32api import GetMonitorInfo, MonitorFromWindow -from win32process import GetWindowThreadProcessId import psutil +if os.name == 'nt': + from win32con import HWND_TOPMOST, SWP_NOMOVE, SWP_NOSIZE, HWND_NOTOPMOST + from win32gui import GetWindowText, SetWindowPos, EnumWindows, GetClientRect, ClientToScreen + from win32api import GetMonitorInfo, MonitorFromWindow + from win32process import GetWindowThreadProcessId +else: + # Linux stubs — these functions are never called outside os.name == 'nt' blocks, + # but they must exist for the module to import cleanly on non-Windows systems. + HWND_TOPMOST = None + SWP_NOMOVE = None + SWP_NOSIZE = None + HWND_NOTOPMOST = None + + def GetWindowText(hwnd): + return None + + def SetWindowPos(hwnd, flags, x, y, w, h, extra): + pass + + def EnumWindows(callback, lParam): + pass + + def GetClientRect(hwnd): + return (0, 0, 0, 0) + + def ClientToScreen(hwnd, pt): + return pt + + def GetMonitorInfo(hwnd, info): + return None + + def MonitorFromWindow(hwnd, flags): + return None + + def GetWindowThreadProcessId(hwnd): + return (0, 0) + from rapidfuzz.process import extractOne -from rapidfuzz.string_metric import levenshtein +try: + from rapidfuzz.string_metric import levenshtein +except ImportError: + from rapidfuzz.distance import Levenshtein as levenshtein def close_down_d2(): subprocess.call(["taskkill","/F","/IM","D2R.exe"], stderr=subprocess.DEVNULL)