Попытка отправить щелчок мыши в игровое окно, Mac - PullRequest
3 голосов
/ 12 мая 2011

Итак, я пытался использовать CGPostMouseEvent и CGEventPostToPSN для отправки щелчка мышью в игру для Mac, и, к сожалению, они оказались очень неудачными.

Я надеялся, что кто-то сможет помочь мне думать об этом иначе или понять, чего мне не хватает. Google не сильно помог.

Мне кажется, это потому, что я пытаюсь отправить событие щелчка в игровое окно (openGL), а не в обычное окно.

Вот еще один пример того, что я пытаюсь отправить: CGEventRef CGEvent; NSEvent * customEvent; NSPoint расположение; location.x = 746; location.y = 509;

    customEvent = [NSEvent mouseEventWithType: NSLeftMouseDown
                                     location: location
                                modifierFlags: NSLeftMouseDownMask
                                    timestamp: time(NULL)
                                 windowNumber: windowID
                                      context: NULL
                                  eventNumber: 0
                                   clickCount: 1
                                     pressure: 0];

    CGEvent = [customEvent CGEvent];
    CGEventPostToPSN(&psn, CGEvent);

Интересно, что я могу нормально двигать мышь (CGDisplayMoveCursorToPoint (kCGDirectMainDisplay, clickPt);), я просто не могу отправлять клики: /

Любая помощь будет принята с благодарностью.

Редактировать: вот что странно: когда я перемещаю мышь с помощью CGDisplayMoveCursorToPoint, мне фактически приходится физически перемещать мышь вверх или вниз по волосам, прежде чем я смогу даже щелкнуть, что странно. Игра не принимает никаких вводных данных, если я не переместил их вверх / вниз (а затем указатель изменился).

Спасибо!

1 Ответ

7 голосов
/ 13 сентября 2011

Хорошо, что вы пытаетесь создать, это «бот» или «робот», который в основном посылает команды в игру упорядоченно.В основном это будет играть для вас, как вы афк.Это отлично подходит для игр, которые заставляют вас играть на добычу полезных ископаемых, товаров или чего-либо еще, что дает вам деньги для продвижения в игре.Что действительно скучно.Я успешно сделал это для популярной игры, хотя я не могу упомянуть игру, поскольку она нарушает пользовательские соглашения, которые все эти типы игр имеют против «ботов».Так что остерегайтесь того, что вы делаете, так как это может нарушить ваше пользовательское соглашение для многих MMPG.Но я публикую это здесь успешно, потому что у Mac меньше доступных ботов, ни одного, который я был в состоянии исследовать, по сравнению с ПК, который я нашел много.Таким образом, чтобы выровнять игровое поле .. вот код.Я рекомендую скомпилировать его как командную строку и выполнить макрос в AppleScript (если логика будет заключаться в том, как имитировать игровые клики, движения и клавиши отправки, в основном ваш ИИ.

1.- Сначала вынужно запустить класс, который получит ваш psn "серийный номер процесса", который есть во всех играх. В основном, в каком потоке он запущен. Вы можете узнать название процесса в утилите на Mac под названием "Activity Monitor". Это можетЭто также легко сделать в AppleScript. Как только у вас есть имя, этот класс найдет и вернет вам свой psn.

#import <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h>
#include <stdio.h>

@interface gamePSN : NSObject 
{
  ProcessSerialNumber gamePSN;
  ProcessInfoRec gameProcessInfo;
  pid_t gameUnixPID;    
}

- (ProcessSerialNumber) gamePSN;
- (ProcessInfoRec) gameProcessInfo;
- (pid_t) gameUnixPID;  
- (void) getPSN;
@end

@implementation gameSN

- (ProcessSerialNumber) gamePSN  { return gamePSN; }
- (ProcessInfoRec) gameProcessInfo { return gameProcessInfo; }
- (pid_t) gameUnixPID; { return gameUnixPID; }

- (void) getPSN
{
    auto OSErr osErr = noErr;
    auto OSErr otherErr = noErr;
    auto ProcessSerialNumber process;
    auto ProcessInfoRec procInfo;
    auto Str255 procName;     
    auto FSSpec appFSSpec;
    auto char cstrProcName[34];
    auto char one ='G';   // FIRST CHARCTER OF GAME PROCESS NAME THESE NEED TO BE CHANGED AS I PUT IN FAKES
    auto char two ='A';   // SECOND CHARACTER OF GAME PROCESS NAME THESE NEED TO BE CHANGED AS I PUT IN FAKES
    auto char three = 'M';  // THIRD  CHARACTER OF GAME PROCESS NAME THESE NEED TO BE CHANGED AS I PUT IN FAKES
    auto unsigned int size;

    process.highLongOfPSN = kNoProcess;
    process.lowLongOfPSN  = kNoProcess;
    procInfo.processInfoLength = sizeof(ProcessInfoRec);
    procInfo.processName = procName;
    procInfo.processAppSpec = &appFSSpec;

    while (procNotFound != (osErr = GetNextProcess(&process))) {

    if (noErr == (osErr = GetProcessInformation(&process, &procInfo))) {
        size = (unsigned int) procName[0];
        memcpy(cstrProcName, procName + 1, size);
        cstrProcName[size] = '\0';

        // NEEDS TO MATCH THE SIGNATURE OF THE GAME..FIRST THREE LETTERS
        // IF YOU CANT FIND IT WITH THE ACTIVITY MONITOR UTILITY OF APPLE MAC OS
        // THEN RUN THIS SAME CLASS WITH AN NSLOG AND IT WILL LIST ALL YOUR RUNNING PROCESSES.

        if (    (((char *) &procInfo.processSignature)[0]==one) && 
                (((char *) &procInfo.processSignature)[1]==two) && 
                (((char *) &procInfo.processSignature)[2]==three) && 
                (((char *) &procInfo.processSignature)[3]==two))
        {
            gamePSN = process;
            otherErr = GetProcessInformation(&gamePSN, &gameProcessInfo);
            otherErr = GetProcessPID(&process, &gameUnixPID);
        }

        }

    }
}

Как только вы получите этот номер процесса, легко отправлять ключевые события, а также мышьсобытия. Вот щелчок события мыши для отправки.

//  mouseClicks.h
//  ClickDep
//  Created by AnonymousPlayer on 9/9/11.


#import <Foundation/Foundation.h>

@interface mouseClicks : NSObject

- (void) PostMouseEvent:(CGMouseButton) button eventType:(CGEventType) type fromPoint:(const CGPoint) point;
- (void) LeftClick:(const CGPoint) point; 
- (void) RightClick:(const CGPoint) point;
- (void) doubleLeftClick:(const CGPoint) point;
- (void) doubleRightClick:(const CGPoint) point;

@end

/
//  mouseClicks.m
//  ClickDep
//  Created by AnonymousPlayer on 9/9/11.v


#import "mouseClicks.h"

@implementation mouseClicks

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here if you need any.
    }

    return self;
}

- (void) PostMouseEvent:(CGMouseButton) button eventType:(CGEventType) type fromPoint:(const CGPoint) point;
{
    CGEventRef theEvent = CGEventCreateMouseEvent(NULL, type, point, button);
    CGEventSetType(theEvent, type);
    CGEventPost(kCGHIDEventTap, theEvent);
    CFRelease(theEvent);
}

- (void) LeftClick:(const CGPoint) point;
{
    [self PostMouseEvent:kCGMouseButtonLeft eventType:kCGEventMouseMoved fromPoint:point];
    NSLog(@"Click!");
    [self PostMouseEvent:kCGMouseButtonLeft eventType:kCGEventLeftMouseDown fromPoint:point];
    sleep(2);
    [self PostMouseEvent:kCGMouseButtonLeft eventType:kCGEventLeftMouseUp fromPoint:point];
}

- (void) RightClick:(const CGPoint) point; 
{
    [self PostMouseEvent:kCGMouseButtonRight eventType:kCGEventMouseMoved fromPoint:point];
    NSLog(@"Click Right");
    [self PostMouseEvent:kCGMouseButtonRight eventType: kCGEventRightMouseDown fromPoint:point];
    sleep(2);
    [self PostMouseEvent:kCGMouseButtonRight eventType: kCGEventRightMouseUp fromPoint:point];
}

- (void) doubleLeftClick:(const CGPoint) point;
{ 
    [self PostMouseEvent:kCGMouseButtonRight eventType:kCGEventMouseMoved fromPoint:point];
    CGEventRef theEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, kCGMouseButtonLeft);  
    CGEventPost(kCGHIDEventTap, theEvent); 
    sleep(2);
    CGEventSetType(theEvent, kCGEventLeftMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 

    CGEventSetIntegerValueField(theEvent, kCGMouseEventClickState, 2);  

    CGEventSetType(theEvent, kCGEventLeftMouseDown);  
    CGEventPost(kCGHIDEventTap, theEvent);  
    sleep(2);
    CGEventSetType(theEvent, kCGEventLeftMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    CFRelease(theEvent); 
}

- (void) doubleRightClick:(const CGPoint) point;
{ 
    [self PostMouseEvent:kCGMouseButtonRight eventType:kCGEventMouseMoved fromPoint:point];
    CGEventRef theEvent = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, kCGMouseButtonRight);  
    CGEventPost(kCGHIDEventTap, theEvent); 
        sleep(2);
    CGEventSetType(theEvent, kCGEventRightMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 

    CGEventSetIntegerValueField(theEvent, kCGMouseEventClickState, 2);  

    CGEventSetType(theEvent, kCGEventRightMouseDown);  
    CGEventPost(kCGHIDEventTap, theEvent);
        sleep(2);
    CGEventSetType(theEvent, kCGEventRightMouseUp); 
    CGEventPost(kCGHIDEventTap, theEvent); 
    CFRelease(theEvent); 
} 
@end

Возможно, вам придется поиграть со сном, который представляет собой интервал времени между нажатием и отпусканием кнопки мыши. Я обнаружил, что иногда используя 1 секундуон не делает этого. Если поставить 2 секунды, он будет работать постоянно. Так что ваш основной ответ будет следующим:

int main(int argc, char *argv[])
{
    NSAutoreleasePool *pool    = [[NSAutoreleasePool alloc] init];
    NSUserDefaults *args    = [NSUserDefaults standardUserDefaults];

    // Grabs command line arguments -x, -y, -clicks, -button
    // and 1 for the click count and interval, 0 for button ie left.
    int x        = [args integerForKey:@"x"];
    int y        = [args integerForKey:@"y"];
    int clicks    =    [args integerForKey:@"clicks"];
    int button   =    [args integerForKey:@"button"];
    //int interval=    [args integerForKey:@"interval"];
    int resultcode;

   // PUT DEFAULT VALUES HERE WHEN SENT WITH EMPTY VALUES
    /*if (x==0) {
        x= 1728+66;
        y= 89+80;
        clicks=2;
        button=0;
    }
     */
    // The data structure CGPoint represents a point in a two-dimensional
    // coordinate system.  Here, X and Y distance from upper left, in pixels.
    CGPoint pt;
    pt.x    = x;
    pt.y    = y;



    // Check CGEventPostToPSN Posts a Quartz event into the event stream for a specific application.
    // only added the front lines plus  changed null in Create Events to kCGHIDEventTap

    gamePSN *gameData = [[gamePSN alloc] init];
    [gameData getPSN];
    ProcessSerialNumber psn = [gameData gamePSN]; 
    resultcode = SetFrontProcess(&psn);

    mouseClicks *mouseEvent =[[mouseClicks alloc] init];

    if (button == 0)
    {
        if (clicks==1) {
            [mouseEvent LeftClick:pt];
        } else {
            [mouseEvent doubleLeftClick:pt];
        }
    }   
    if (button == 1)
    {
        if (clicks==1) {
            [mouseEvent RightClick:pt];
        } else {
            [mouseEvent doubleRightClick:pt];
        }
    }   

    [gameData release];
    [mouseEvent release];

    [pool drain];
    return 0;
}

Надеюсь, что это полезно .... помните, что вы можете выполнить это в терминале или в AppleScript, отправив следующую команду.

do shell script "/...Path to Compiled Program.../ClickDep" & " -x " & someX & " -y " & someY & " -clicks 1 -button 1"

СЧАСТЛИВАЯ ИГРА !!!!! 1015 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...