feat: add friend mouse feeding automation
No files matched your search
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,41 @@
|
|||||||
|
"""狂鼠之家好友矿鼠一键喂养循环。"""
|
||||||
|
import time
|
||||||
|
from .engine import WorkflowError
|
||||||
|
|
||||||
|
|
||||||
|
class FeedMiceRunner:
|
||||||
|
def __init__(self, desktop, matcher, flow, region_provider, log=print, timeout=12):
|
||||||
|
self.desktop,self.matcher,self.flow=desktop,matcher,flow; self.region_provider,self.log,self.timeout=region_provider,log,timeout
|
||||||
|
def observe(self):
|
||||||
|
shot=self.desktop.screenshot(); region=self.region_provider(shot); return shot,region,self.matcher.frame(shot,region)
|
||||||
|
def wait(self,*names):
|
||||||
|
end=time.monotonic()+self.timeout; previous=None; stable=0
|
||||||
|
while time.monotonic()<end:
|
||||||
|
shot,region,frame=self.observe(); found=next((n for n in names if self.matcher.matches(frame,self.flow['states'][n])),None)
|
||||||
|
stable=stable+1 if found and found==previous else (1 if found else 0); previous=found
|
||||||
|
if stable>=2:return found,shot,region,frame
|
||||||
|
time.sleep(.25)
|
||||||
|
raise WorkflowError('未识别到预期页面 '+ '/'.join(names)+',已停止。')
|
||||||
|
def click(self,point,obs):
|
||||||
|
_,shot,region,_=obs
|
||||||
|
if self.region_provider(shot)!=region:raise WorkflowError('识别后游戏窗口移动,已停止,请重新运行。')
|
||||||
|
self.desktop.click(point,region,shot.size,hold=.8)
|
||||||
|
def action(self,name,obs):self.click(self.flow['clicks'][name],obs);self.log('已执行:'+name)
|
||||||
|
def location(self,frame,key):
|
||||||
|
spec=self.flow[key]; score,loc=self.matcher.locate(frame,spec)
|
||||||
|
if score<spec.get('threshold',.86):return None
|
||||||
|
x,y,w,h=loc;return ((x+w/2)/562,(y+h/2)/1002)
|
||||||
|
def return_home(self,rat):
|
||||||
|
self.action('rat_back',rat);self.action('territory_back',self.wait('territory'));self.wait('home');self.log('已确认返回首页。')
|
||||||
|
def run(self,dry_run=False):
|
||||||
|
home=self.wait('home')
|
||||||
|
if dry_run:self.log('首页识别通过。计划:领地 → 狂鼠之家 → 好友首位 → 一键喂养循环 → 返回首页。未点击。');return 'preview'
|
||||||
|
self.action('territory',home);self.action('rat_house',self.wait('territory'));rat=self.wait('rat')
|
||||||
|
count=0
|
||||||
|
while count<self.flow['max_feeds']:
|
||||||
|
self.action('friends',rat); friends=self.wait('friends'); target=self.location(friends[3],'friend_button')
|
||||||
|
if not target:self.log('好友列表没有可喂狂鼠,结束。');self.action('friends_back',friends);self.return_home(self.wait('rat'));return 'fed' if count else 'no_friend'
|
||||||
|
self.click(target,friends); mine=self.wait('friend_mine'); one=self.location(mine[3],'onekey_button')
|
||||||
|
if not one:self.log('首位好友没有一键喂养,结束。');self.action('friend_home',mine);self.return_home(self.wait('rat'));return 'fed' if count else 'no_feed'
|
||||||
|
self.click(one,mine);self.log('已执行:一键喂养。');reward=self.wait('reward');self.action('dismiss_reward',reward);self.action('friend_home',self.wait('friend_mine'));rat=self.wait('rat');count+=1;self.log('已完成第 %s 位好友喂养。'%count)
|
||||||
|
raise WorkflowError('喂养次数超过安全上限,已停止。')
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import argparse,sys,time
|
||||||
|
from pathlib import Path
|
||||||
|
from automation.engine import Matcher,load_flow
|
||||||
|
from automation.feed_mice import FeedMiceRunner
|
||||||
|
from automation.offers import MacGameDesktop
|
||||||
|
ROOT=Path(__file__).resolve().parent
|
||||||
|
def main():
|
||||||
|
p=argparse.ArgumentParser(description='狂鼠之家:循环喂养好友矿鼠');p.add_argument('--dry-run',action='store_true');a=p.parse_args()
|
||||||
|
if sys.platform!='darwin':return 2
|
||||||
|
try:
|
||||||
|
d=MacGameDesktop();d.activate();print('3 秒后开始;请保持游戏在前台。',flush=True);time.sleep(3)
|
||||||
|
FeedMiceRunner(d,Matcher(ROOT/'assets'),load_flow(ROOT/'workflows/feed_mice.json'),d.region_for).run(a.dry_run);return 0
|
||||||
|
except Exception as e:print('流程停止:'+str(e),file=sys.stderr);return 1
|
||||||
|
if __name__=='__main__':raise SystemExit(main())
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"name":"喂养狂鼠","max_feeds":20,"states":{"home":[{"template":"home.png","search":[150,730,410,865]}],"territory":[{"template":"territory_rat_house.png","search":[15,440,220,570]}],"rat":[{"template":"rat_house_page.png","search":[315,80,550,235]}],"friends":[{"template":"feed_friends_title.png","search":[210,85,350,180]}],"friend_mine":[{"template":"feed_friend_home.png","search":[0,875,140,1002]}],"reward":[{"template":"feed_reward.png","search":[120,180,440,390],"threshold":0.8},{"template":"feed_dismiss.png","search":[145,600,420,730]}]},"friend_button":{"template":"feed_friend_button.png","search":[270,220,480,870]},"onekey_button":{"template":"feed_onekey.png","search":[210,770,355,930]},"clicks":{"territory":[0.68,0.94],"rat_house":[0.20,0.55],"friends":[0.72,0.94],"dismiss_reward":[0.50,0.67],"friend_home":[0.12,0.94],"friends_back":[0.70,0.94],"rat_back":[0.12,0.94],"territory_back":[0.68,0.94]}}
|
||||||