From 3476f9a4a352a9a7ce6af006bac8d66bc698c576 Mon Sep 17 00:00:00 2001 From: brockdarnold Date: Mon, 15 Jun 2026 02:56:08 +0000 Subject: [PATCH] publish eve_orehold_watcher.py --- eve_orehold_watcher.py | 91 +++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 19 deletions(-) diff --git a/eve_orehold_watcher.py b/eve_orehold_watcher.py index 5bcf0a7..acfc84d 100644 --- a/eve_orehold_watcher.py +++ b/eve_orehold_watcher.py @@ -293,13 +293,77 @@ def parse_orehold_text(text): return cur, cap +def capture_window(cls="triuiScreen"): + """Capture the EVE client window via PrintWindow — gets EVE's pixels even when it's + behind Discord/unfocused/moved (no overlap, no screen-position dependence). Returns a + PIL Image (window-relative, e.g. 3840x2160) or None. Frees GDI handles each call.""" + if os.name != "nt": + return None + import ctypes + import ctypes.wintypes as wt + from PIL import Image + u = ctypes.windll.user32 + g = ctypes.windll.gdi32 + try: + u.SetProcessDPIAware() + except Exception: + pass + hwnd = u.FindWindowW(cls, None) + if not hwnd: + res = [] + + @ctypes.WINFUNCTYPE(ctypes.c_bool, wt.HWND, wt.LPARAM) + def _cb(h, _l): + n = u.GetWindowTextLengthW(h) + if n: + b = ctypes.create_unicode_buffer(n + 1) + u.GetWindowTextW(h, b, n + 1) + if b.value.startswith("EVE -"): + res.append(h) + return True + + u.EnumWindows(_cb, 0) + hwnd = res[0] if res else 0 + if not hwnd: + return None + r = wt.RECT() + u.GetClientRect(hwnd, ctypes.byref(r)) + w, h = r.right, r.bottom + if w <= 0 or h <= 0: + return None + hdc = u.GetDC(hwnd) + mdc = g.CreateCompatibleDC(hdc) + bmp = g.CreateCompatibleBitmap(hdc, w, h) + g.SelectObject(mdc, bmp) + u.PrintWindow(hwnd, mdc, 2) # PW_RENDERFULLCONTENT (works for DX windows) + + class BMIH(ctypes.Structure): + _fields_ = [("biSize", wt.DWORD), ("biWidth", ctypes.c_long), ("biHeight", ctypes.c_long), + ("biPlanes", wt.WORD), ("biBitCount", wt.WORD), ("biCompression", wt.DWORD), + ("biSizeImage", wt.DWORD), ("p1", ctypes.c_long), ("p2", ctypes.c_long), + ("p3", wt.DWORD), ("p4", wt.DWORD)] + bmi = BMIH() + bmi.biSize = ctypes.sizeof(BMIH); bmi.biWidth = w; bmi.biHeight = -h + bmi.biPlanes = 1; bmi.biBitCount = 32; bmi.biCompression = 0 + buf = ctypes.create_string_buffer(w * h * 4) + g.GetDIBits(mdc, bmp, 0, h, buf, ctypes.byref(bmi), 0) + img = Image.frombuffer("RGB", (w, h), buf, "raw", "BGRX", 0, 1) + g.DeleteObject(bmp); g.DeleteDC(mdc); u.ReleaseDC(hwnd, hdc) # avoid GDI leak + return img + + def grab_region(region): + """Crop a WINDOW-RELATIVE region from the EVE window capture (occlusion-proof). + Falls back to absolute-screen grab if the EVE window can't be found.""" + img = capture_window() + if img is not None: + l, t, ww, hh = region + return img.crop((l, t, l + ww, t + hh)) import mss from PIL import Image left, top, width, height = region with mss.mss() as sct: - raw = sct.grab({"left": left, "top": top, "width": width, - "height": height}) + raw = sct.grab({"left": left, "top": top, "width": width, "height": height}) return Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX") @@ -347,24 +411,13 @@ def _detect_readout(cp, img, mon_left=0, mon_top=0, save=True, scale=1): def auto_region(cp): - """Scan the whole screen for the ore-hold readout and save its location — - replaces the manual --snip. Just have the in-game Ore Hold window open.""" - import mss - from PIL import Image - try: - with mss.mss() as sct: - mon = sct.monitors[0] # full virtual desktop (all screens) - raw = sct.grab(mon) - img = Image.frombytes("RGB", raw.size, raw.bgra, "raw", "BGRX") - # crop the center band (where EVE sits) then upscale, so small m³ text is readable - W, Hh = img.size - cx0, cy0 = int(W * 0.22), 0 - crop = img.crop((cx0, cy0, int(W * 0.82), int(Hh * 0.97))) - up = crop.resize((crop.width * 2, crop.height * 2)) - except Exception as e: - print(f"[ocr] auto-detect error: {e}") + """Find the ore-hold 'X / Y m³' readout WITHIN the EVE window capture (clean, + occlusion-proof). Returns a WINDOW-RELATIVE region. Have the Ore Hold window open.""" + img = capture_window() + if img is None: return None - return _detect_readout(cp, up, mon["left"] + cx0, mon["top"] + cy0, scale=2) + up = img.resize((img.width * 2, img.height * 2)) # upscale so small m³ text reads + return _detect_readout(cp, up, 0, 0, scale=2) # window-relative (origin 0,0) def run_ocr(cp):