From 228d611e14434a4e3f6dda7ec5c650aefd934d83 Mon Sep 17 00:00:00 2001 From: Aurelien Aptel Date: Fri, 1 Dec 2023 02:00:24 +0100 Subject: [PATCH 1/3] add autostarter --- miscs/autostarter/newgame-btn.png | Bin 0 -> 636 bytes miscs/autostarter/noitamp-btn.png | Bin 0 -> 5909 bytes miscs/autostarter/run.py | 118 ++++++++++++++++++++++++++++++ miscs/autostarter/world2-btn.png | Bin 0 -> 1205 bytes 4 files changed, 118 insertions(+) create mode 100644 miscs/autostarter/newgame-btn.png create mode 100644 miscs/autostarter/noitamp-btn.png create mode 100644 miscs/autostarter/run.py create mode 100644 miscs/autostarter/world2-btn.png diff --git a/miscs/autostarter/newgame-btn.png b/miscs/autostarter/newgame-btn.png new file mode 100644 index 0000000000000000000000000000000000000000..0f51330591b5ca7bdaf0927bfb83e15ba785c492 GIT binary patch literal 636 zcmeAS@N?(olHy`uVBq!ia0vp^p+GFg!3HEZT3(m|q!^2X+?^QKos)S91s;*b3=DjSL74G){)!Z!U~FbcL`iU7W`S>NNn%Q3Ng_~;fuUL{IVZCq zAU`v&q*%!+x>~71$;v=SsS-%m>VSC`rr5YfMo?*pVjwrR*3fTO70_iXJY5_^BHZ6j z-xze*fTwM8+bKAXG7BEBbv?ocJI$p zNz~k?r}^~h&9C7LeNG*UOm!*=HeN7$R^tQX((UzXzYBhQh(4~*$gN7m;JNm`?PA668Eibs@hjsSAN|1cUF2<#(Kw9@=Po1 zI9ihSB^~(`{P@86udGfRH$_Ym&G;6*>FZtLNFNV-$#eJjlvM`pNnao)*liuAp8b6- zbE&HRgkO(p`}dx|dGB9I+q1*3?44_^WKS`f|8iDK*lMVrwAENWrL=IDn&P?7_s^V+ ze0Zz>_m?_-zfZM_8*RR{?%Lrd^Ox^y>eKtvQ&aav0~HQjBcqnc2)7n_ILis5F(e;v1;p(Q$-s$WcFJ~QG`Cu)(N`3A9y`q&dyWC_sSMoi0 zedN>st}Sx!gkLO4TX1L2{Xf6@Up@Xjca4cs)&H%36hBDS r9xk6%MtpOx@Vr=-=3ri0)b&VO&--|@{i(+ppmgBr>gTe~DWM4fNX-hj literal 0 HcmV?d00001 diff --git a/miscs/autostarter/noitamp-btn.png b/miscs/autostarter/noitamp-btn.png new file mode 100644 index 0000000000000000000000000000000000000000..89d7205e3beebf8d4ff54592e186a0cd498e6860 GIT binary patch literal 5909 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 bL)S!zuzeVt_SD0FAJp0!`rs-xYs~)uK#OjL literal 0 HcmV?d00001 diff --git a/miscs/autostarter/run.py b/miscs/autostarter/run.py new file mode 100644 index 000000000..397008c9f --- /dev/null +++ b/miscs/autostarter/run.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python3 +# +# Install +# ------- +# +# 1. Install python if not already installed. +# This can be done by just running "python", it will open the windows store to install +# +# 2. Install dependencies +# > pip install pyautogui pygetwindow opencv-python +# + +import pyautogui +import pygetwindow as gw +import os +import time + +GIT_DIR = os.path.dirname(__file__) +NOITA_DIR = r'C:\Program Files (x86)\Steam\steamapps\common\Noita' + +CONFIG_PATH = GIT_DIR + r'\config_test.xml' +NOITA_BIN = NOITA_DIR + r'\noita.exe' + +def main(): + write_config(CONFIG_PATH) + + # start server instance + os.chdir(NOITA_DIR) + os.system('start "" noita.exe -windowed -config "%s"'%(CONFIG_PATH)) + os.chdir(GIT_DIR) + time.sleep(3) + + server_window = find_noita_window() + server_window.moveTo(0, 0) + time.sleep(0.5) + + noita_click(server_window, 'newgame-btn.png') + noita_click(server_window, 'noitamp-btn.png', confidence=0.5) + noita_click(server_window, 'world2-btn.png') + + # start client instance + os.chdir(NOITA_DIR) + os.system('start "" noita.exe -windowed -config "%s"'%(CONFIG_PATH)) + os.chdir(GIT_DIR) + time.sleep(3) + + client_window = find_noita_window(exclude=[server_window]) + client_window.moveTo(server_window.left+server_window.width+30, 0) + time.sleep(0.5) + + noita_click(client_window, 'newgame-btn.png') + noita_click(client_window, 'noitamp-btn.png', confidence=0.5) + noita_click(client_window, 'world2-btn.png') + + + time.sleep(60) + +def noita_click(window, img, confidence=0.8, sleep=0.5): + game = pyautogui.screenshot(region=(window.left, window.top, window.width, window.height)) + r = pyautogui.locate(img, game, confidence=confidence) + print("located btn at", r) + p = pyautogui.center(r) + print("center at", p) + print("abs", window.top+p.y, window.left+p.x) + pyautogui.moveTo(window.left+p.x, window.top+p.y) + pyautogui.click(window.left+p.x, window.top+p.y) + time.sleep(sleep) + +def find_noita_window(exclude=None): + winlist = gw.getWindowsWithTitle('Noita - Build') + if exclude: + for w in winlist: + if w not in exclude: + return w + return winlist[0] + +def write_config(path): + with open(path, "w+") as f: + print(""" + + + """, file=f) + +if __name__ == '__main__': + main() diff --git a/miscs/autostarter/world2-btn.png b/miscs/autostarter/world2-btn.png new file mode 100644 index 0000000000000000000000000000000000000000..3537b851d633fa47b346c1d0717fd38f6a991f84 GIT binary patch literal 1205 zcmeAS@N?(olHy`uVBq!ia0vp^w}4ojgAGXLW(RHrQjEnx?oJHr&dIz4a#+$GeH|GX zHuiJ>Nn{1`ISV`@iy0XB4ude`@%$AjK*9LTkcg7tyvzdM)RM%M#F9jy7z0DKQgTja zK|p?HUP-Z%Rdlsdg_4zlj#4F%tknVYj0`QX@{Nq43LwgX+}PT$n!@1>49xdET^vIy z;@-}Q_6`XYIc}RA_ep43;^diZo*6D;#;)@fRjN3eUR(}kadnw?&DsB(fW)4lc7x1P5sJ``aev1ar4xZh>R_Wm!{OWsnSv*pevKlk%_Mb`7~ z-!D7rK07lzyT4yXz1C>UflCo7YrA7}dfDFU)x{-qFO7&vEuLd?;>f+iIch?^b7Y>c z?>p-hyfNtg`5zh84o81gecPa4Q+a&f=4$+jc^ zv%f&qZWZsN)H&1g6<=Sy-FI}qT=}KCSF+)o4^%Xm>VeIE&^qn>^P3)t3yiL2{M_>C zWWn_J58vpTEm<7YrmLxKU$?RG=kns5pPP4f9erGDP&~PJiq6SWiC5;_bHqEZtrzRB zS$jum%eZVI z=kqro=WdNz7sE7ZmB7xJzP|^Zh2Jo)ds$$B5t-p{v&`9$(nII&Mp0^ye+V?!Vi! z_B`VWi!;hE@3(8udc34z=Y=iV`X?XkGc*e_Fp6nryd`*oZL|9gleG1B6O~()v_((n zIP5!lDO4_Dv20t5zo(B=`Z}dW09pF*9vZ4uQpNb%hGGs#xqZpbU5ks{$J@=-i=$`B+aTK zcl>I7xb1438E2VTkFfQ`t&bUUpKo%o{UUuUJ}70k$Kv}{E6eXKJW-h4a_)H7*l2?JC@C!V{_2#d&VqZrK!9L z?aV*k<-V;E+Z4Zhxx&{Mn*$A@{n@%Sor|J6gWeaN28ETX8h*_FTJt^(Xgj-TUcI_JaQm zzt^{#ziHePta(-NZ^ob8@-?kF{;TuP`fKNh*g05Uc;t{#eanL3)Y=Md`Be*S*}bjg z8p=HPc3k)sRWG!<{z2C>3rzvuewlRF(_gOtE8X;MJ)^+-y-Ve}=55totFw9fesS)d z&M)88IEkugp3O4X1ScWsE;gy9AyQZKyRRG)J@Zq((6xBZvdfn~vEOEITYL5Np}(L4 N#M9N!Wt~$(6984KD3t&J literal 0 HcmV?d00001 From 791323271fc4a77f6231f0679f4aaba25224eef9 Mon Sep 17 00:00:00 2001 From: Aurelien Aptel Date: Fri, 1 Dec 2023 16:00:47 +0100 Subject: [PATCH 2/3] use noita.exe cli flags instead of screenshots & clicking --- miscs/autostarter/run.py | 74 +++++++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 27 deletions(-) diff --git a/miscs/autostarter/run.py b/miscs/autostarter/run.py index 397008c9f..6551421d0 100644 --- a/miscs/autostarter/run.py +++ b/miscs/autostarter/run.py @@ -14,46 +14,66 @@ import pygetwindow as gw import os import time +import shutil +import argparse -GIT_DIR = os.path.dirname(__file__) -NOITA_DIR = r'C:\Program Files (x86)\Steam\steamapps\common\Noita' +GIT_DIR = os.path.dirname(__file__) CONFIG_PATH = GIT_DIR + r'\config_test.xml' -NOITA_BIN = NOITA_DIR + r'\noita.exe' -def main(): - write_config(CONFIG_PATH) +# default options +NOITA_DIR = r'C:\Program Files (x86)\Steam\steamapps\common\Noita' +SAVE_SLOT = 1 +GAME_MODE = 4 - # start server instance - os.chdir(NOITA_DIR) - os.system('start "" noita.exe -windowed -config "%s"'%(CONFIG_PATH)) - os.chdir(GIT_DIR) - time.sleep(3) +def main(): + ap = argparse.ArgumentParser(description="Start 2 instances of noita to test/debug NoitaMP") + ap.add_argument("--noita-dir", "-n", help="path to noita directory (default %s)"%NOITA_DIR, default=NOITA_DIR) + ap.add_argument("--slot", "-s", type=int, help="save slot to load on each instance (0-indexed, default %d)"%SAVE_SLOT, default=SAVE_SLOT) + ap.add_argument("--gamemode", "-g", type=int, help="NoitaMP game mode index in the New Game menu (0-indexed, default %d)"%GAME_MODE, default=GAME_MODE) + args = ap.parse_args() - server_window = find_noita_window() - server_window.moveTo(0, 0) - time.sleep(0.5) + noita_bin = args.noita_dir + r'\noita.exe' + noita2_bin = args.noita_dir + r'\noita2.exe' - noita_click(server_window, 'newgame-btn.png') - noita_click(server_window, 'noitamp-btn.png', confidence=0.5) - noita_click(server_window, 'world2-btn.png') + make_client_exe(noita_bin, noita2_bin) + write_config(CONFIG_PATH) - # start client instance - os.chdir(NOITA_DIR) - os.system('start "" noita.exe -windowed -config "%s"'%(CONFIG_PATH)) - os.chdir(GIT_DIR) - time.sleep(3) + server_window = start_exe(noita_bin, mode=args.gamemode, slot=args.slot, config=CONFIG_PATH) + client_window = start_exe(noita2_bin, mode=args.gamemode, slot=args.slot, config=CONFIG_PATH) - client_window = find_noita_window(exclude=[server_window]) + server_window.moveTo(0, 0) client_window.moveTo(server_window.left+server_window.width+30, 0) - time.sleep(0.5) - noita_click(client_window, 'newgame-btn.png') - noita_click(client_window, 'noitamp-btn.png', confidence=0.5) - noita_click(client_window, 'world2-btn.png') + time.sleep(60) +def start_exe(exe, mode, slot, config): + start = {x._hWnd: x for x in gw.getWindowsWithTitle('Noita - Build')} - time.sleep(60) + os.chdir(os.path.dirname(exe)) + fn = os.path.basename(exe) + os.system('start "" %s -no_logo_splashes -windowed -config "%s" -gamemode %d -save_slot %d'%(fn, config, mode, slot)) + os.chdir(GIT_DIR) + + print("waiting for %s window to pop up..."%fn) + while True: + now = gw.getWindowsWithTitle('Noita - Build') + if len(now) > len(start): + for x in now: + if x._hWnd not in start.keys(): + return x + time.sleep(0.2) + +def make_client_exe(original_exe, new_client_exe): + if os.path.exists(new_client_exe): + return + + shutil.copyfile(original_exe, new_client_exe) + with open(new_client_exe, "rb+") as f: + buf = f.read() + offset = buf.find(b'logger.txt') + f.seek(offset, 0) + f.write(b'logge2.txt') def noita_click(window, img, confidence=0.8, sleep=0.5): game = pyautogui.screenshot(region=(window.left, window.top, window.width, window.height)) From 93dfc20731a43991126e843bee275f95683911ae Mon Sep 17 00:00:00 2001 From: Aurelien Aptel Date: Fri, 1 Dec 2023 17:44:59 +0100 Subject: [PATCH 3/3] add --dev and --log on|off|merged --- miscs/autostarter/run.py | 67 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/miscs/autostarter/run.py b/miscs/autostarter/run.py index 6551421d0..4d4e1e7d0 100644 --- a/miscs/autostarter/run.py +++ b/miscs/autostarter/run.py @@ -16,7 +16,7 @@ import time import shutil import argparse - +import subprocess GIT_DIR = os.path.dirname(__file__) CONFIG_PATH = GIT_DIR + r'\config_test.xml' @@ -28,13 +28,19 @@ def main(): ap = argparse.ArgumentParser(description="Start 2 instances of noita to test/debug NoitaMP") + ap.add_argument("--dev", "-d", help="use noita_dev.exe", action="store_true", default=False) + ap.add_argument("--log", "-l", help="logging mode", choices=['off', 'on', 'merged'], default='off') ap.add_argument("--noita-dir", "-n", help="path to noita directory (default %s)"%NOITA_DIR, default=NOITA_DIR) ap.add_argument("--slot", "-s", type=int, help="save slot to load on each instance (0-indexed, default %d)"%SAVE_SLOT, default=SAVE_SLOT) ap.add_argument("--gamemode", "-g", type=int, help="NoitaMP game mode index in the New Game menu (0-indexed, default %d)"%GAME_MODE, default=GAME_MODE) args = ap.parse_args() - noita_bin = args.noita_dir + r'\noita.exe' - noita2_bin = args.noita_dir + r'\noita2.exe' + if args.dev: + noita_bin = args.noita_dir + r'\noita_dev.exe' + noita2_bin = args.noita_dir + r'\noita2_dev.exe' + else: + noita_bin = args.noita_dir + r'\noita.exe' + noita2_bin = args.noita_dir + r'\noita2.exe' make_client_exe(noita_bin, noita2_bin) write_config(CONFIG_PATH) @@ -45,7 +51,18 @@ def main(): server_window.moveTo(0, 0) client_window.moveTo(server_window.left+server_window.width+30, 0) - time.sleep(60) + if args.log == 'merged': + server_log = LogPoll(args.noita_dir + r'\logger.txt', prefix='\x1b[31m[SERVER]\x1b[0m ') + client_log = LogPoll(args.noita_dir + r'\logge2.txt', prefix='\x1b[32m[CLIENT]\x1b[0m ') + while True: + server_log.read_and_print() + client_log.read_and_print() + time.sleep(.5) + elif args.log == 'on': + start_log_console(args.noita_dir + r'\logger.txt', + args.noita_dir + r'\logge2.txt', + pos_y=server_window.top+server_window.height) + def start_exe(exe, mode, slot, config): start = {x._hWnd: x for x in gw.getWindowsWithTitle('Noita - Build')} @@ -57,7 +74,7 @@ def start_exe(exe, mode, slot, config): print("waiting for %s window to pop up..."%fn) while True: - now = gw.getWindowsWithTitle('Noita - Build') + now = gw.getWindowsWithTitle('Noita - ') if len(now) > len(start): for x in now: if x._hWnd not in start.keys(): @@ -134,5 +151,45 @@ def write_config(path): """, file=f) + +def start_log_console(log_client, log_server, pos_y=0): + log_dir = os.path.dirname(log_client) + log_client_fn = os.path.basename(log_client) + log_server_fn = os.path.basename(log_server) + subprocess.run(["wt.exe", "--pos", "0,%d"%pos_y, + "nt", "-d", log_dir, "powershell.exe", "-command", 'Get-Content -Path "%s" -Wait'%log_server_fn, ';', + "sp", "-V", "-d", log_dir, "powershell.exe", "-command", 'Get-Content -Path "%s" -Wait'%log_client_fn, + ]) + print("ok") + + +class LogPoll: + def __init__(self, path, prefix): + self._path = path + self._last_offset = 0 + self._prefix = prefix + self._need_prefix = False + + def read_and_print(self): + with open(self._path, "r") as f: + f.seek(self._last_offset, 0) + buf = f.read() + end = '' + if len(buf) > 0: + if buf[-1] == '\n': + buf = buf[:-1] + end = '\n' + nextpref = True + else: + nextpref = False + buf = buf.replace('\n', '\n'+self._prefix) + if self._need_prefix: + buf = self._prefix + buf + else: + self._need_prefix = nextpref + print(buf, end=end) + self._last_offset = f.tell() + + if __name__ == '__main__': main()