Semi-autonomes Platzieren von OpenRA Buildings

Der Quellcode im Anhang enthält einen Aimbot für das Echtzeitstrategiespiel OpenRA, der in der Lage ist, Kraftwerke auf der Map zu platzieren. Dazu wird über ein Mini-Screenshot und eine Pixelerkennung ein freier Bereich erkannt und darauf das Gebäude platziert. Leider funktioniert das Verfahren nur sehr unzuverlässig, so dass (wie im obigen Video auch zu sehen) es mitunter zu Aussetzern kommen kann. Ein praktischer Nutzen besteht deshalb nicht, allerdings ist die Idee spannend mit Hilfe von GUI Automatisierung einen Aimbot zu erstellen.

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.awt.Robot;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.text.NumberFormat;

class Aimbot implements ActionListener
{
  // java.awt.robot
  Robot robot = new Robot();

  // GUI
  JFrame frame = new JFrame("Aimbot");
  JPanel mainPanel = new JPanel();
  JButton button1 = new JButton("OpenRA");
  JButton button2 = new JButton("SinglePlayer");
  JButton button3 = new JButton("Basis");
  JButton button4 = new JButton("Kraftwerk Auftrag");
  JButton button5 = new JButton("Kraftwerk platzieren");
  JButton button6 = new JButton("Mouse move");
  JButton button7 = new JButton("7");
  JButton button8 = new JButton("8");
  JLabel label1 = new JLabel("Mausposition: ");
  JLabel label2 = new JLabel("....... Pixelsearch: ");
  JLabel label3 = new JLabel("Farbe (rgb): ");
  JLabel mousex = new JLabel("");
  JLabel mousey = new JLabel("");
  JLabel labelpixelsearch = new JLabel("");
  JLabel farbe = new JLabel("");

  // Magnifier
  int size = 200; // OpenRA Ausschnitt: size=200, zoom=1
  double zoom = 1;
  BufferedImage image;
  ImageIcon icon = new ImageIcon();
  JLabel labelmag = new JLabel(icon);

  void FokusAufOpenRAFenster()
  {
    robot.mouseMove(600, 400);
    leftClick();
    type("h"); // Bauhof auswählen
  }

  void FokusAufBotFenster()
  {
    robot.mouseMove(200, 500);
    leftClick();
  }

  void type(String s)
  {
    byte[] bytes = s.getBytes();
    for (byte b : bytes) {
      int code = b;
      // keycode only handles [A-Z] (which is ASCII decimal [65-90])
      if (code > 96 && code < 123)
        code = code - 32;
      robot.delay(40);
      robot.keyPress(code);
      robot.keyRelease(code);
    }
  }

  void leftClick()
  {
    robot.mousePress(InputEvent.BUTTON1_MASK);
    robot.delay(100);
    robot.mouseRelease(InputEvent.BUTTON1_MASK);
    robot.delay(100);
  }

  void rightClick()
  {
    robot.mousePress(InputEvent.BUTTON3_MASK);
    robot.delay(100);
    robot.mouseRelease(InputEvent.BUTTON3_MASK);
    robot.delay(100);
  }

  void typeEnter()
  {
    robot.delay(40);
    robot.keyPress(KeyEvent.VK_ENTER);
    robot.keyRelease(KeyEvent.VK_ENTER);
    robot.delay(1000);
  }

  void makroOpenRAStarten()
  {
    // Terminal Starten
    robot.mouseMove(30, 50);
    leftClick();
    type("terminal");
    typeEnter();

    // OpenRA Starten
    type("openra");
    typeEnter();
    robot.delay(4000);

    FokusAufBotFenster();
  }

  void makroSinglePlayerStarten()
  {
    FokusAufOpenRAFenster();
    robot.mouseMove(400, 320); // Button Singleplayer
    leftClick();
    robot.delay(500);
    leftClick(); // Button Skirmish
    robot.delay(500);

    robot.mouseMove(800, 430); // Button Startgame
    leftClick();
    robot.delay(500);

    FokusAufBotFenster();
  }

  void makroKraftwerkPlatzieren()
  {
    FokusAufOpenRAFenster();

    // Kraftwerk in Menü auswählen
    robot.mouseMove(900, 430);
    leftClick();

    // Kraftwerk positionieren
    boolean finished = false;
    for (int y = 200; y <= 600 && !finished; y = y + 100) {
      for (int x = 400; x <= 800; x = x + 50) {
        robot.mouseMove(x, y);
        robot.delay(200); 
        if (labelpixelsearch.getText().equals("true")) {
          leftClick(); // Kraftwerk platzieren
          finished = true;
          break;
        }
      }
    }
    
    // neuen Auftrag für Kraftwerk
    robot.mouseMove(900, 430);
    leftClick();
    
    FokusAufBotFenster();

  }

  boolean inRange(int i, int min, int max)
  {
    if (i > min && i < max)
      return true;
    else
      return false;
  }

  boolean pixelSearch()
  {
    // Positive Color
    // OpenRA weiß frei: 252 252 252 (rgb)
    int positveRed = 252;
    int positveGreen = 252;
    int positveBlue = 252;
    int positiveEqual = 0;

    // Negative Color
    // OpenRA rot belegt: 168 0 0 (rgb)
    int negativeRed = 168;
    int negativeGreen = 0;
    int negativeBlue = 0;
    int negativeEqual = 0;

    int tolerance = 10;

    int width = image.getWidth();
    int height = image.getHeight();

    for (int row = 0; row < height; row++) {
      for (int col = 0; col < width; col++) {
        int pix = image.getRGB(row, col);
        Color c = new Color(pix, true); // true for hasalpha

        // determine "inRangeCount"
        int positiveCount = 0;
        int negativeCount = 0;

        if (inRange(c.getRed(), positveRed - tolerance, positveRed + tolerance) == true) {
          positiveCount++;
        }
        if (inRange(c.getRed(), negativeRed - tolerance, negativeRed
            + tolerance) == true) {
          negativeCount++;
        }
        if (inRange(c.getGreen(), positveGreen - tolerance, positveGreen
            + tolerance) == true) {
          positiveCount++;
        }
        if (inRange(c.getGreen(), negativeGreen - tolerance, negativeGreen
            + tolerance) == true) {
          negativeCount++;
        }
        if (inRange(c.getBlue(), positveBlue - tolerance, positveBlue
            + tolerance) == true) {
          positiveCount++;
        }
        if (inRange(c.getBlue(), negativeBlue - tolerance, negativeBlue
            + tolerance) == true) {
          negativeCount++;
        }
        if (positiveCount == 3)
          positiveEqual++;
        if (negativeCount == 3)
          negativeEqual++;

      }
    }
    // System.out.println(positiveEqual+" "+negativeEqual);
    int erkannteFelder = positiveEqual + negativeEqual;
    // System.out.println(positiveEqual + " " + negativeEqual);
    if (erkannteFelder < 2000)
      return false;
    else {
      if ((1.0 * positiveEqual / erkannteFelder) > 0.9) {
        return true;
      } else
        return false;
    }

  }

  Color pixelcolorOnCursor()
  {
    // Pixelcolor on Image-center
    int pix = image.getRGB(image.getHeight() / 2, image.getWidth() / 2);
    Color c = new Color(pix, true); // true for hasalpha
    return c;
  }

  void screenMagnifier()
  // http://openbook.rheinwerk-verlag.de/java7/1507_10_009.html
  {
    try {
      Rectangle location = new Rectangle(MouseInfo.getPointerInfo()
          .getLocation(), new Dimension(size, size));
      location.translate(-size / 2, -size / 2);
      image = new Robot().createScreenCapture(location);
      int width = (int) (image.getWidth() * zoom);
      int height = (int) (image.getHeight() * zoom);
      icon.setImage(image.getScaledInstance(width, height, Image.SCALE_FAST));
      labelmag.repaint();
      labelpixelsearch.setText("" + pixelSearch());

      // Cursorfarbe bestimmen
      Color c = pixelcolorOnCursor();
      farbe.setText(c.getRed() + " " + c.getGreen() + " " + c.getBlue());

    } catch (AWTException ae) {

    }

  }

  public void actionPerformed(ActionEvent e)
  {
    Object source = e.getSource();
    if (source == button1) {
      new Thread() {
        public void run()
        {
          makroOpenRAStarten();
        }
      }.start();

      // JOptionPane.showMessageDialog(null, "Button1");
    }
    if (source == button2) {
      new Thread() {
        public void run()
        {
          makroSinglePlayerStarten();
        }
      }.start();
    }
    if (source == button5) {
      new Thread() {
        public void run()
        {
          makroKraftwerkPlatzieren();
        }
      }.start();
    }
    if (source == button6) {
      new Thread() {
        @Override
        // override: braucht man das oder nicht?
        public void run()
        {
          robot.mouseMove(900, 430);
          robot.delay(1000);
          robot.mouseMove(800, 430);
          robot.delay(1000);
          robot.mouseMove(700, 430);
          robot.delay(1000);
        }
      }.start();

    }
    if (source == button7) {
      new Thread() {
        public void run()
        {

        }
      }.start();
    }

  }

  Aimbot() throws AWTException {
    // robot init
    robot.setAutoWaitForIdle(true);
    // robot.setAutoDelay(1000);

    // formular
    frame.setSize(250, 500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
    mainPanel.setLayout(new FlowLayout());
    frame.setContentPane(mainPanel);

    mainPanel.add(label1);
    mainPanel.add(mousex);
    mainPanel.add(mousey);
    mainPanel.add(label3);
    mainPanel.add(farbe);
    mainPanel.add(label2);
    mainPanel.add(labelpixelsearch);

    mainPanel.add(labelmag);
    screenMagnifier();

    mainPanel.add(button1);
    button1.addActionListener(this);
    mainPanel.add(button2);
    button2.addActionListener(this);
    mainPanel.add(button3);
    button3.addActionListener(this);
    mainPanel.add(button4);
    button4.addActionListener(this);
    mainPanel.add(button5);
    button5.addActionListener(this);
    mainPanel.add(button6);
    button6.addActionListener(this);
    mainPanel.add(button7);
    button7.addActionListener(this);
    mainPanel.add(button8);
    button7.addActionListener(this);

    // frame.pack();
    frame.setVisible(true);

    // Timer Intervall 100 = 0,1 Sekunde
    new Timer(100, new ActionListener() {
      public void actionPerformed(ActionEvent e)
      {
        Point location = MouseInfo.getPointerInfo().getLocation();
        mousex.setText("" + location.x);
        mousey.setText("" + location.y);
        screenMagnifier();
      }
    }).start();

  }

}

class class1
{
  public static void main(String[] args) throws AWTException
  {
    Aimbot myAimbot = new Aimbot();
  }

}

]]>

3756
2015-04-28 15:02:49
2015-04-28 13:02:49
open
open
semi-autonomes-platzieren-von-openra-buildings
publish
0
0
post

0

_edit_last

geo_public

_publicize_pending

Bug: Aimbot für OpenRA hat delay-Probleme
https://aa5new.wordpress.com/2015/04/28/bug-aimbot-fur-openra-hat-delay-probleme/
Tue, 28 Apr 2015 13:03:44 +0000
aa5new
https://aa5new.wordpress.com/?p=3758

<![CDATA[https://www.youtube.com/watch?v=Mp9BWPvErPQ

Leider funktioniert der neu entwickelte Aimbot für OpenRA der mittels "java.awt.robot" über das GUI Fenster Befehle absendet nicht zuverlässig. Zwar kann er bereits Screenshots anfertigen, doch leider scheint diese Funktion nur im manuellen Modus zu funktionieren. Wenn der Mauscurser hingegen automatisch bewegt wird, funktioniert die Aktualisierung der Anzeige nicht mehr. Was die Ursachen sind ist derzeit unklar, vermutlich hat es etwas mit der Methode "waitforidle" in der "java.awt.robot" Klasse zu tun.

Mal ganz abgesehen davon gibt es noch weitere Probleme. Und zwar soll der Aimbot später einmal alleine leveln können. Damit ist gemeint, dass er seinen Zustand verbessern soll, und zwar dadurch dass er seinen Punktestand erhöht, seinen Einflussbereich auf der Map vergrößert, seine Gegner dominiert usw. Nur, eine Unterfunktion um zu "leveln" ist derzeit noch gar nicht implementiert. Es fehlt hier an grundlegenden Konzepten. Vermutlich müsste als erstes einmal eine menschliche Strategie als Software implementiert werden, was nicht nur aufwendig ist, sondern auch weitere Fehlerquellen eröffnet.

Advertisements

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s