initial commit

This commit is contained in:
Radek Davidek 2025-12-04 16:18:59 +01:00
commit 5450f0e92f
23 changed files with 1776 additions and 0 deletions

50
.gitignore vendored Executable file
View File

@ -0,0 +1,50 @@
### Eclipse
.classpath
.project
.settings/
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.mvn
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
mvnw
mvnw.cmd
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
### VS Code ###
.vscode/
### Log4j2 ###
logs
*.log
# Ignore Mac DS_Store files
.DS_Store
dependency-reduced-pom.xml
cert.pem

View File

@ -0,0 +1,12 @@
#Pokémon GO Automatizace - Nastavení
#Thu Dec 04 16:03:55 CET 2025
autoklik.count=500
window.width=807
transfer.delay=0
window.height=743
autoklik.x=2380
autoklik.y=1124
transfer.count=30
window.x=930
autoklik.interval=100
window.y=22

BIN
pgo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

74
pom.xml Normal file
View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.pokemongo</groupId>
<artifactId>pgo-automat</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Java Robot pro automatizaci myši a klávesnice -->
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>5.13.0</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>5.13.0</version>
</dependency>
<!-- OpenCV pro rozpoznávání obrazu -->
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.7.0-0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
<!-- Maven Shade Plugin - alternativa pro vytvoření Fat JAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.pokemongo.PokemonGoGUI</mainClass>
</transformer>
</transformers>
<finalName>pgo-automat-gui</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,64 @@
package com.pokemongo;
import java.awt.event.KeyEvent;
import java.awt.KeyboardFocusManager;
import java.util.HashSet;
import java.util.Set;
import javax.swing.JLabel;
/**
* Globální hotkey listener pro detekci CTRL+ALT+Z kombinace
* Funguje i když není okno fokusované
*/
public class GlobalHotkey extends JLabel {
private static GlobalHotkey instance;
private GlobalKeyListener globalKeyListener;
public GlobalHotkey(Runnable onHotkey) {
this.globalKeyListener = new GlobalKeyListener(onHotkey);
// Registrace globálního key listeneru
KeyboardFocusManager.getCurrentKeyboardFocusManager()
.addKeyEventDispatcher(globalKeyListener);
}
public static GlobalHotkey create(Runnable onHotkey) {
if (instance == null) {
instance = new GlobalHotkey(onHotkey);
}
return instance;
}
/**
* Interní třída pro globální naslouchání na klávesnici
*/
private static class GlobalKeyListener implements java.awt.KeyEventDispatcher {
private Runnable callback;
private Set<Integer> pressedKeys = new HashSet<>();
public GlobalKeyListener(Runnable callback) {
this.callback = callback;
}
@Override
public boolean dispatchKeyEvent(KeyEvent e) {
if (e.getID() == KeyEvent.KEY_PRESSED) {
pressedKeys.add(e.getKeyCode());
// Detekce CTRL+ALT+X
if (e.getKeyCode() == KeyEvent.VK_X &&
e.isControlDown() && e.isAltDown()) {
System.out.println("🔌 Globální hotkey detekován: CTRL+ALT+X");
if (callback != null) {
callback.run();
}
return true; // Konzumovat event
}
} else if (e.getID() == KeyEvent.KEY_RELEASED) {
pressedKeys.remove(e.getKeyCode());
}
return false; // Nepropagovat ostatní eventy
}
}
}

View File

@ -0,0 +1,651 @@
package com.pokemongo;
import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.event.InputEvent;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
/**
* Automatizační nástroj pro Pokémon GO.
* Najde běžící aplikaci, označí všechny Pokémony a stiskne tlačítko Transfer.
*/
public class PokemonGoAutomation {
private Robot robot;
private Rectangle windowBounds;
private BufferedImage t1Template; // TRANSFER button template
private BufferedImage t2Template; // Confirmation button template
private BufferedImage pok1Template; // Pokemon detection template
private BufferedImage includeTemplate; // Include button template
private static final int DELAY_BETWEEN_CLICKS = 200; // ms
private static final int DELAY_AFTER_ACTION = 500; // ms
private int transferredPokemonCount = 0; // Počet transfernutých pokémonů
public PokemonGoAutomation() throws AWTException {
this.robot = new Robot();
this.robot.setAutoDelay(50);
this.robot.setAutoWaitForIdle(true);
loadButtonTemplates();
}
/**
* Vrátí počet dosud transfernutých pokémonů
*/
public int getTransferredCount() {
return transferredPokemonCount;
}
/**
* Resetuje počítadlo transfernutých pokémonů
*/
public void resetTransferredCount() {
transferredPokemonCount = 0;
}
/**
* Pořídí screenshot oblasti okna
*/
private BufferedImage captureScreen(Rectangle area) {
return robot.createScreenCapture(area);
}
/**
* Načte templaty pro tlačítka TRANSFER (t1.png) a confirmation (t2.png)
*/
private void loadButtonTemplates() {
try {
String t1Paths = "/t1.png";
t1Template = ImageIO.read(getClass().getResourceAsStream(t1Paths));
System.out.println("✅ Template TRANSFER načten z: " + t1Paths);
String t2Paths = "/t2.png";
t2Template = ImageIO.read(getClass().getResourceAsStream(t2Paths));
System.out.println("✅ Template Potvrzení načten z: " + t2Paths);
String pok1Paths = "/pok1.png";
pok1Template = ImageIO.read(getClass().getResourceAsStream(pok1Paths));
System.out.println("✅ Template Pokémon načten z: " + pok1Paths);
String includePaths = "/include.png";
includeTemplate = ImageIO.read(getClass().getResourceAsStream(includePaths));
System.out.println("✅ Template INCLUDE načten z: " + includePaths);
if (t1Template == null) {
System.out.println("⚠️ Template t1.png nebyl nalezen");
}
if (t2Template == null) {
System.out.println("⚠️ Template t2.png nebyl nalezen");
}
if (pok1Template == null) {
System.out.println("⚠️ Template pok1.png nebyl nalezen");
}
if (includeTemplate == null) {
System.out.println("⚠️ Template include.png nebyl nalezen");
}
} catch (IOException e) {
System.err.println("⚠️ Chyba při načítání templates: " + e.getMessage());
}
}
/**
* Porovnává template s oblastí v obrázku - jednoduché pixelové porovnání s
* optimalizací
*/
private double templateMatch(BufferedImage screenshot, int startX, int startY, BufferedImage template, int tolerance) {
if (template == null)
return 0.0;
int tWidth = template.getWidth();
int tHeight = template.getHeight();
// Kontrola hranic
if (startX + tWidth > screenshot.getWidth() || startY + tHeight > screenshot.getHeight()) {
return 0.0;
}
if (startX < 0 || startY < 0) {
return 0.0;
}
int matchingPixels = 0;
int totalPixels = tWidth * tHeight;
int requiredMatch = (int) (totalPixels * 0.75); // 75% shody
for (int y = 0; y < tHeight; y++) {
for (int x = 0; x < tWidth; x++) {
int templateRGB = template.getRGB(x, y);
int screenRGB = screenshot.getRGB(startX + x, startY + y);
// Rozdělit RGB hodnoty
int tR = (templateRGB >> 16) & 0xFF;
int tG = (templateRGB >> 8) & 0xFF;
int tB = templateRGB & 0xFF;
int sR = (screenRGB >> 16) & 0xFF;
int sG = (screenRGB >> 8) & 0xFF;
int sB = screenRGB & 0xFF;
// Porovnat barvy - zvýšená tolerance pro lepší detekci
int rDiff = Math.abs(tR - sR);
int gDiff = Math.abs(tG - sG);
int bDiff = Math.abs(tB - sB);
if (rDiff < tolerance && gDiff < tolerance && bDiff < tolerance) {
matchingPixels++;
// Early exit - pokud jsme nedosáhli minima, skončit
if (matchingPixels < requiredMatch / 2 && (y * tWidth + x) > (totalPixels / 2)) {
return 0.0;
}
}
}
}
// Vrátit procentuální shodu (0.0-1.0)
return (double) matchingPixels / totalPixels;
}
/**
* Detekuje pozice Pokémonů pomocí template matchingu s pok1.png
* Hledá v oblasti od vrchu obrazovky do 75% výšky
* Může najít 9 Pokémonů
*/
private List<Point> detectPokemonsByTemplateMatching() {
List<Point> positions = new ArrayList<>();
System.out.println("\n=== Detekce Pokémonů pomocí template matchingu (pok1.png) ===");
if (pok1Template == null) {
System.out.println("⚠️ Template pok1.png není dostupný");
return positions;
}
BufferedImage screenshot = captureScreen(windowBounds);
int tWidth = pok1Template.getWidth();
int tHeight = pok1Template.getHeight();
System.out.println("Template velikost: " + tWidth + "x" + tHeight);
// Grid parametry - 3x3 (9 Pokémonů) - pevné pozice podle layoutu aplikace
int gridStartY = (int) (windowBounds.height * 0.15);
int gridEndY = (int) (windowBounds.height * 0.75);
int gridHeight = gridEndY - gridStartY;
int gridMargin = (int) (windowBounds.width * 0.05);
int gridStartX = gridMargin;
int gridWidth = windowBounds.width - (2 * gridMargin);
int columns = 3;
int rows = 3; // 3x3 grid = 9 Pokémonů
int columnWidth = gridWidth / columns;
int rowHeight = gridHeight / rows;
System.out.println("Hledám Pokémony v gridu 3x3 (9 pozic)");
// Pro každou buňku v gridu hledat template
for (int row = 0; row < rows; row++) {
for (int col = 0; col < columns; col++) {
int cellX = gridStartX + (col * columnWidth);
int cellY = gridStartY + (row * rowHeight);
double bestScore = 0.0;
int bestX = cellX + columnWidth / 2;
int bestY = cellY + rowHeight / 2;
// Skenovat buňku s jemností
for (int sy = cellY; sy < cellY + rowHeight - tHeight; sy += 3) {
for (int sx = cellX; sx < cellX + columnWidth - tWidth; sx += 3) {
double score = templateMatch(screenshot, sx, sy, pok1Template, 115); // Zvýšená tolerance
if (score > bestScore) {
bestScore = score;
bestX = sx + tWidth / 2;
bestY = sy + tHeight / 2;
}
}
}
// Pokud jsme našli match (skóre > 75%), považovat za Pokémona
if (bestScore > 0.98) {
int x = windowBounds.x + bestX;
int y = windowBounds.y + bestY;
positions.add(new Point(x, y));
System.out.println(" Detekován Pokémon na [" + row + "," + col + "] -> (" + x + ", " + y
+ ") skóre=" + String.format("%.1f", bestScore * 100) + "%");
}
}
}
System.out.println("Celkem detekováno: " + positions.size() + " Pokémonů");
System.out.println("=================================\n");
return positions;
}
/**
* Najde a vrátí pozici transferu tlačítka bez kliknutí
*/
private Point findTransferButtonPosition() {
System.out.println("Hledám tlačítko TRANSFER pomocí template matchingu (t1.png)...");
BufferedImage screenshot = captureScreen(windowBounds);
int tWidth = t1Template.getWidth();
int tHeight = t1Template.getHeight();
// Template je celý řádek - zkusíme matchovat od 75% do 95% (kde by měl být
// TRANSFER řádek)
int searchStartY = (int) (windowBounds.height * 0.75);
int searchEndY = (int) (windowBounds.height * 0.95);
double bestScore = 0.0;
int bestX = 0;
int bestY = 0;
// Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení
for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) {
// Skenovat také X pozice pro nalezení středu shody
for (int x = 0; x <= windowBounds.width - tWidth; x += 30) {
double score = templateMatch(screenshot, x, y, t1Template, 90);
if (score > bestScore) {
bestScore = score;
bestX = x;
bestY = y;
}
}
}
if (bestScore > 0.92) {
Point bestMatch = new Point(
windowBounds.x + bestX + (tWidth / 2),
windowBounds.y + bestY + (tHeight / 2));
System.out.println("✅ Nalezeno TRANSFER tlačítko (template match) na: " + bestMatch + " (shoda: "
+ String.format("%.1f", bestScore * 100) + "%)");
return bestMatch;
}
System.out.println("Template nenalezen");
return null;
}
/**
* Najde a vrátí pozici potvrzovacího tlačítka bez kliknutí
*/
private Point findConfirmTransferButtonPosition() {
System.out.println("Hledám potvrzovací TRANSFER tlačítko pomocí template matchingu (t2.png)...");
BufferedImage screenshot = captureScreen(windowBounds);
int tWidth = t2Template.getWidth();
int tHeight = t2Template.getHeight();
// Dialog je obvykle v horní polovině po TRANSFER kliknutí
int searchStartY = (int) (windowBounds.height * 0.40);
int searchEndY = (int) (windowBounds.height * 0.75);
double bestScore = 0.0;
int bestX = 0;
int bestY = 0;
// Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení
for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) {
// Skenovat také X pozice pro nalezení středu shody
for (int x = 0; x <= windowBounds.width - tWidth; x += 30) {
double score = templateMatch(screenshot, x, y, t2Template, 90);
if (score > bestScore) {
bestScore = score;
bestX = x;
bestY = y;
}
}
}
if (bestScore > 0.85) {
Point bestMatch = new Point(
windowBounds.x + bestX + (tWidth / 2),
windowBounds.y + bestY + (tHeight / 2));
System.out.println("✅ Nalezeno potvrzovací tlačítko (template match) na: " + bestMatch + " (shoda: "
+ String.format("%.1f", bestScore * 100) + "%)");
return bestMatch;
}
System.out.println("Template nenalezen");
return null;
}
private Point findIncludeButtonPosition() {
System.out.println("Hledám tlačítko INCLUDE pomocí template matchingu (include.png)...");
BufferedImage screenshot = captureScreen(windowBounds);
int tWidth = includeTemplate.getWidth();
int tHeight = includeTemplate.getHeight();
// Dialog je obvykle v horní polovině po TRANSFER kliknutí
int searchStartY = (int) (windowBounds.height * 0.40);
int searchEndY = (int) (windowBounds.height * 0.75);
double bestScore = 0.0;
int bestX = 0;
int bestY = 0;
// Skenovat Y-ové pozice s větším krokem - 15px místo 5px pro zrychlení
for (int y = searchStartY; y <= searchEndY - tHeight; y += 15) {
// Skenovat také X pozice pro nalezení středu shody
for (int x = 0; x <= windowBounds.width - tWidth; x += 30) {
double score = templateMatch(screenshot, x, y, includeTemplate, 90);
if (score > bestScore) {
bestScore = score;
bestX = x;
bestY = y;
}
}
}
if (bestScore > 0.92) {
Point bestMatch = new Point(
windowBounds.x + bestX + (tWidth / 2),
windowBounds.y + bestY + (tHeight / 2));
System.out.println("✅ Nalezeno tlačítko INCLUDE (template match) na: " + bestMatch + " (shoda: "
+ String.format("%.1f", bestScore * 100) + "%)");
return bestMatch;
}
System.out.println("Template nenalezen");
return null;
}
/**
* Najde okno s názvem obsahujícím "Pokémon" nebo "Pokemon"
*/
public boolean findPokemonGoWindow() {
try {
// Pro Linux - hledání okna pomocí xdotool
// Nejdříve najít ID okna, pak získat jeho geometrii
Process searchProcess = Runtime.getRuntime().exec(
new String[] { "bash", "-c", "xdotool search --name \"Lenovo|L78032\" | head -1" });
java.io.BufferedReader searchReader = new java.io.BufferedReader(
new java.io.InputStreamReader(searchProcess.getInputStream()));
String windowId = searchReader.readLine();
searchProcess.waitFor();
if (windowId != null && !windowId.trim().isEmpty()) {
System.out.println("Nalezeno okno s ID: " + windowId);
// Získat geometrii okna
Process geomProcess = Runtime.getRuntime().exec(
new String[] { "bash", "-c", "xdotool getwindowgeometry " + windowId.trim() });
java.io.BufferedReader geomReader = new java.io.BufferedReader(
new java.io.InputStreamReader(geomProcess.getInputStream()));
String line;
int x = 0, y = 0, width = 0, height = 0;
while ((line = geomReader.readLine()) != null) {
System.out.println("xdotool výstup: " + line);
if (line.contains("Position:")) {
String[] parts = line.split("Position: ")[1].split(",");
x = Integer.parseInt(parts[0].trim());
y = Integer.parseInt(parts[1].trim().split(" ")[0]);
} else if (line.contains("Geometry:")) {
String[] parts = line.split("Geometry: ")[1].split("x");
width = Integer.parseInt(parts[0].trim());
height = Integer.parseInt(parts[1].trim());
}
}
geomProcess.waitFor();
if (width > 0 && height > 0) {
windowBounds = new Rectangle(x, y, width, height);
System.out.println("Nalezeno okno: " + windowBounds);
return true;
}
}
// Fallback - použití celé obrazovky
System.out.println("Okno nenalezeno, použiji celou obrazovku");
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
windowBounds = gd.getDefaultConfiguration().getBounds();
return true;
} catch (Exception e) {
System.err.println("Chyba při hledání okna: " + e.getMessage());
e.printStackTrace();
// Použití celé obrazovky jako záložní varianta
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
windowBounds = gd.getDefaultConfiguration().getBounds();
return true;
}
}
/**
* Aktivuje okno aplikace
*/
public void activateWindow() {
try {
// Kliknutí na horní panel okna (title bar) pro aktivaci
// Title bar je obvykle 30-40px vysoký v horní části okna
int centerX = windowBounds.x + windowBounds.width / 2;
int titleBarY = windowBounds.y + 15; // 15px od vrcholu okna = horní panel
System.out.println("Aktivuji okno kliknutím na title bar: (" + centerX + ", " + titleBarY + ")");
robot.mouseMove(centerX, titleBarY);
robot.delay(200);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(DELAY_AFTER_ACTION);
System.out.println("Okno aktivováno");
} catch (Exception e) {
System.err.println("Chyba při aktivaci okna: " + e.getMessage());
}
}
/**
* Stiskne tlačítko Transfer na spodní části obrazovky
*/
public void clickTransferButton() {
// Použít detekci tlačítka
Point buttonPos = findTransferButtonPosition();
if (buttonPos == null) {
System.err.println("Tlačítko TRANSFER nebylo nalezeno!");
return;
}
robot.mouseMove(buttonPos.x, buttonPos.y);
robot.delay(DELAY_AFTER_ACTION);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println("Tlačítko TRANSFER stisknuto!");
robot.delay(DELAY_AFTER_ACTION);
}
/**
* Potvrdí transfer (pokud je potřeba potvrzovací dialog)
*/
public void clickConfirmTransferButton() {
System.out.println("Potvrzuji transfer - hledám t2.png (confirmation button)...");
robot.delay(100); // Počkat na zobrazení dialogu
// Najít zelené TRANSFER tlačítko v potvrzovacím dialogu
Point buttonPos = findConfirmTransferButtonPosition();
if (buttonPos == null) {
System.out.println("Potvrzovací tlačítko nebylo nalezeno, přeskočím potvrzení.");
return;
}
robot.mouseMove(buttonPos.x, buttonPos.y);
robot.delay(DELAY_BETWEEN_CLICKS);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println("Transfer finálně potvrzen!");
robot.delay(DELAY_AFTER_ACTION);
}
public void clickIncludeButton() {
System.out.println("Potvrzuji transfer - hledám include.png (confirmation button)...");
robot.delay(100); // Počkat na zobrazení dialogu
// Najít zelené INCLUDE tlačítko v potvrzovacím dialogu
Point buttonPos = findIncludeButtonPosition();
if (buttonPos == null) {
System.out.println("INCLUDE tlačítko nebylo nalezeno, přeskočím potvrzení.");
return;
}
robot.mouseMove(buttonPos.x, buttonPos.y);
robot.delay(DELAY_BETWEEN_CLICKS);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
System.out.println("Transfer finálně potvrzen!");
robot.delay(DELAY_AFTER_ACTION);
}
/**
* Spustí Transfer automatizaci s konkrétním počtem pokémonů
*
* @param totalPokemonCount Celkový počet pokémonů k transferu
* @param delaySeconds Čekání mezi iteracemi (v sekundách)
*/
public void runWithCount(int totalPokemonCount, int delaySeconds) {
System.out.println("Spouštím Transfer automatizaci - Počet pokémonů: " + totalPokemonCount + ", Čekání: "
+ delaySeconds + "s");
if (!findPokemonGoWindow()) {
System.err.println("Nepodařilo se najít okno Pokémon GO!");
return;
}
activateWindow();
System.out.println("Čekám 1 sekundu před začátkem...");
robot.delay(1000);
int transferredCount = 0;
// Transferovat dokud nedosáhneme požadovaného počtu
while (transferredCount < totalPokemonCount) {
// Kontrola přerušení
if (Thread.currentThread().isInterrupted()) {
System.out.println("\n⚠ Automatizace byla přerušena!");
return;
}
int pokemonThisRound = Math.min(9, totalPokemonCount - transferredCount);
System.out.println("\n=== Iterace " + (transferredCount / 9 + 1) + " - Transferuji maximálně " + pokemonThisRound
+ " pokémonů ===");
// Vybrat pokémony a získat skutečný počet vybraných
int actualTransferredCount = selectAllPokemonCount(pokemonThisRound);
System.out.println("Čekám na TRANSFER...");
clickTransferButton();
System.out.println("Čekám na INCLUDE dialog...");
robot.delay(100);
clickIncludeButton();
System.out.println("Čekám na potvrzovací dialog...");
robot.delay(100);
clickConfirmTransferButton();
transferredCount += actualTransferredCount;
transferredPokemonCount += actualTransferredCount;
System.out.println("Transferováno v této iteraci: " + actualTransferredCount + " pokémonů (celkem: " + transferredCount + ")");
// Pokud ještě zbývá co transferovat, počkat
if (transferredCount < totalPokemonCount) {
System.out.println("Přestávka: " + delaySeconds + " sekund...");
// Čekat s kontrolou přerušení
long endTime = System.currentTimeMillis() + (delaySeconds * 1000L);
while (System.currentTimeMillis() < endTime) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("\n⚠ Automatizace byla přerušena během přestávky!");
return;
}
robot.delay(100);
}
}
}
System.out.println("\n✅ Transfer automatizace dokončena! Transferováno: " + transferredCount + " pokémonů");
}
/**
* Označí konkrétní počet pokémonů
* @return Skutečný počet vybraných pokémonů
*/
private int selectAllPokemonCount(int count) {
System.out.println("Začínám označovat " + count + " pokémonů (pouze template matching)...");
List<Point> positions = detectPokemonsByTemplateMatching();
int maxPokemon = Math.min(count, positions.size());
System.out.println("Budu označovat " + maxPokemon + " pokémonů...");
for (int i = 0; i < maxPokemon; i++) {
Point pos = positions.get(i);
System.out.println("Klikám na Pokémona " + (i + 1) + "/" + maxPokemon + " na pozici: " + pos);
robot.mouseMove(pos.x, pos.y);
if (i == 0) {
robot.delay(500);
System.out.println(" -> Dlouhé podržení (aktivace multi-select)");
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(800);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.delay(DELAY_AFTER_ACTION);
} else {
System.out.println(" -> Normální klik");
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
robot.delay(DELAY_BETWEEN_CLICKS);
}
System.out.println("Označeno " + maxPokemon + " pokémonů!");
System.out.println("Čekám před kliknutím na TRANSFER...");
robot.delay(800);
return maxPokemon;
}
public static void main(String[] args) {
System.out.println("=== Pokémon GO Automatizační Nástroj ===");
System.out.println("Ujistěte se, že je aplikace Pokémon GO spuštěná...");
}
}

View File

@ -0,0 +1,830 @@
package com.pokemongo;
import javax.swing.*;
import javax.swing.KeyStroke;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.io.*;
import java.util.Properties;
/**
* Jednoduchá GUI aplikace pro Pokémon GO automatizaci
* S kartami pro jednotlivé automatizace
*/
public class PokemonGoGUI extends JFrame {
private JButton stopButton;
private JTextArea logArea;
private JLabel statusLabel;
private volatile boolean isRunning = false;
private volatile boolean shouldStop = false;
private PokemonGoAutomation automation;
private Thread automationThread;
private int totalTransferredCount = 0; // Celkový počet transfernutých pokémonů
private volatile boolean autoClickRunning = false;
private GlobalHotkey globalHotkey;
private static final String CONFIG_FILE = "pgo-automat-settings.properties";
private static final String VERSION = "1.0.2";
private Properties settings;
private JSpinner countSpinner;
private JSpinner delaySpinner;
private static final Font TITLE_FONT = new Font("Segoe UI", Font.BOLD, 18);
private static final Font HEADER_FONT = new Font("Segoe UI", Font.BOLD, 12);
private static final Font BODY_FONT = new Font("Segoe UI", Font.PLAIN, 11);
private static final Font SMALL_FONT = new Font("Segoe UI", Font.PLAIN, 10);
private static final Color PANEL_BACKGROUND = new Color(248, 248, 252);
private static final Color CARD_BACKGROUND = Color.WHITE;
private static final Color CARD_BORDER_COLOR = new Color(210, 210, 210);
private static final Color PRIMARY_GREEN = new Color(76, 175, 80);
private static final Color PRIMARY_RED = new Color(244, 67, 54);
private static final Color ACCENT_BLUE = new Color(33, 150, 243);
private static final Color LOG_BORDER_COLOR = new Color(200, 200, 200);
private static final Color STATUS_DEFAULT = new Color(33, 150, 243);
private static final int CARD_MAX_WIDTH = 760;
public PokemonGoGUI() {
setTitle("Pokémon GO Automatizace v" + VERSION);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Načtení uložených nastavení
loadSettings();
// Obnovení velikosti a pozice okna
int width = Integer.parseInt(settings.getProperty("window.width", "900"));
int height = Integer.parseInt(settings.getProperty("window.height", "680"));
int x = Integer.parseInt(settings.getProperty("window.x", "-1"));
int y = Integer.parseInt(settings.getProperty("window.y", "-1"));
setSize(width, height);
if (x >= 0 && y >= 0) {
setLocation(x, y);
} else {
setLocationRelativeTo(null);
}
setResizable(true);
setBackground(PANEL_BACKGROUND);
// Uložení nastavení při zavření okna
addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
saveSettings();
}
});
// Hlavní panel
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
mainPanel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
mainPanel.setBackground(PANEL_BACKGROUND);
// Horní panel se stavem
JLabel stateLabel = new JLabel("Stav:");
stateLabel.setFont(HEADER_FONT);
stateLabel.setForeground(new Color(70, 70, 70));
statusLabel = new JLabel("Připraven k spuštění");
statusLabel.setFont(BODY_FONT);
statusLabel.setForeground(STATUS_DEFAULT);
JLabel versionLabel = new JLabel("verze " + VERSION);
versionLabel.setFont(SMALL_FONT);
versionLabel.setForeground(new Color(120, 120, 120));
stopButton = new JButton("⏹ ZASTAVIT (CTRL+ALT+X)");
stopButton.setPreferredSize(new Dimension(150, 30));
styleButton(stopButton, PRIMARY_RED, Color.WHITE, SMALL_FONT);
stopButton.setEnabled(false);
stopButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stopAutomation();
}
});
JPanel stopPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
stopPanel.setOpaque(false);
stopPanel.add(stopButton);
JLabel titleLabel = new JLabel("Pokémon GO Automatizace");
titleLabel.setFont(TITLE_FONT);
titleLabel.setForeground(new Color(30, 30, 30));
JPanel titleRow = new JPanel(new BorderLayout());
titleRow.setBackground(PANEL_BACKGROUND);
titleRow.add(titleLabel, BorderLayout.WEST);
titleRow.add(stopPanel, BorderLayout.EAST);
JPanel statusRow = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0));
statusRow.setBackground(PANEL_BACKGROUND);
statusRow.add(stateLabel);
statusRow.add(statusLabel);
statusRow.add(versionLabel);
JPanel headerPanel = new JPanel();
headerPanel.setLayout(new BoxLayout(headerPanel, BoxLayout.Y_AXIS));
headerPanel.setBackground(PANEL_BACKGROUND);
headerPanel.add(titleRow);
headerPanel.add(Box.createVerticalStrut(6));
headerPanel.add(statusRow);
// Panel s kartami automatizací
JPanel cardsContainer = new JPanel(new GridBagLayout());
cardsContainer.setBackground(PANEL_BACKGROUND);
cardsContainer.setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
gbc.anchor = GridBagConstraints.NORTH;
gbc.insets = new Insets(0, 0, 12, 0);
// Karta 1: Transfer automatizace
JPanel transferCard = createAutomationCard(
"🔄 TRANSFER AUTOMATIZACE",
"Hledá Pokémony, označí je a stiskne Transfer",
null
);
// Najít START tlačítko - je v EAST pozici BorderLayoutu
JButton startBtnTransfer = findStartButton(transferCard);
if (startBtnTransfer != null) {
startBtnTransfer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startTransferAutomation(transferCard);
}
});
}
gbc.gridy = 0;
cardsContainer.add(transferCard, gbc);
gbc.gridy++;
gbc.insets = new Insets(0, 0, 12, 0);
// Karta 2: Autoklik
JPanel autoClickCard = createAutomationCard(
"🖱️ AUTOKLIK",
"Automaticky klikuje na zadanou pozici",
null
);
// Najít START tlačítko
JButton startBtnAutoClick = findStartButton(autoClickCard);
if (startBtnAutoClick != null) {
startBtnAutoClick.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
startAutoClick(autoClickCard);
}
});
}
gbc.gridy++;
gbc.insets = new Insets(0, 0, 0, 0);
cardsContainer.add(autoClickCard, gbc);
gbc.gridy++;
gbc.weighty = 1.0;
JPanel spacer = new JPanel();
spacer.setOpaque(false);
cardsContainer.add(spacer, gbc);
JPanel automationPanel = new JPanel(new BorderLayout());
automationPanel.setBackground(PANEL_BACKGROUND);
automationPanel.add(cardsContainer, BorderLayout.NORTH);
JScrollPane automationScrollPane = new JScrollPane(automationPanel);
automationScrollPane.setBorder(null);
automationScrollPane.setBackground(PANEL_BACKGROUND);
automationScrollPane.getViewport().setBackground(PANEL_BACKGROUND);
// Log area
logArea = new JTextArea();
logArea.setEditable(false);
logArea.setFont(new Font("Consolas", Font.PLAIN, 11));
logArea.setBackground(new Color(248, 248, 248));
logArea.setForeground(new Color(45, 45, 45));
logArea.setLineWrap(true);
logArea.setWrapStyleWord(true);
logArea.setMargin(new Insets(5, 5, 5, 5));
JScrollPane logScrollPane = new JScrollPane(logArea);
logScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
logScrollPane.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createLineBorder(LOG_BORDER_COLOR),
"Log",
0,
0,
HEADER_FONT,
new Color(85, 85, 85)
));
logScrollPane.getViewport().setBackground(new Color(247, 247, 247));
JButton clearLogButton = new JButton("🗑 Vyčistit log");
clearLogButton.setPreferredSize(new Dimension(140, 28));
styleButton(clearLogButton, ACCENT_BLUE, Color.WHITE, SMALL_FONT);
clearLogButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
logArea.setText("");
}
});
JPanel logButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 5));
logButtonPanel.setBackground(PANEL_BACKGROUND);
logButtonPanel.add(clearLogButton);
JPanel logPanel = new JPanel(new BorderLayout(5, 5));
logPanel.setBackground(new Color(247, 247, 247));
logPanel.add(logScrollPane, BorderLayout.CENTER);
logPanel.add(logButtonPanel, BorderLayout.SOUTH);
// Splitter mezi kartami a logem
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, automationScrollPane, logPanel);
splitPane.setDividerSize(6);
splitPane.setResizeWeight(0.6);
splitPane.setContinuousLayout(true);
splitPane.setBorder(null);
splitPane.setBackground(PANEL_BACKGROUND);
// Přidání do hlavního panelu
mainPanel.add(headerPanel, BorderLayout.NORTH);
mainPanel.add(splitPane, BorderLayout.CENTER);
add(mainPanel);
// Klávesová zkratka: Ctrl+Alt+Z pro zastavení
KeyStroke hotkey = KeyStroke.getKeyStroke(KeyEvent.VK_X, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK);
getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(hotkey, "stopAutomationAction");
getRootPane().getActionMap().put("stopAutomationAction", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (isRunning) {
stopAutomation();
}
}
});
// Globální hotkey pro ESC (bonus, když okno není fokusované)
globalHotkey = new GlobalHotkey(new Runnable() {
@Override
public void run() {
if (isRunning) {
stopAutomation();
}
}
});
mainPanel.add(globalHotkey, BorderLayout.SOUTH);
// Přesměrování System.out a System.err do GUI
redirectSystemStreams();
logArea.append("=== Pokémon GO Automatizace ===\n\n");
logArea.append("Vyberte jednu z automatizací a klikněte na tlačítko START.\n");
logArea.append("Ujistěte se, že je aplikace Pokémon GO spuštěná.\n");
logArea.append("Pro zastavení stiskněte Ctrl+Alt+X nebo klikněte ZASTAVIT.\n\n");
}
/**
* Vytvoří kartu automatizace s nastavením
*/
private JPanel createAutomationCard(String title, String description, ActionListener startAction) {
JPanel card = new JPanel(new BorderLayout(12, 12));
card.setBackground(CARD_BACKGROUND);
card.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(CARD_BORDER_COLOR, 1),
BorderFactory.createEmptyBorder(8, 8, 8, 8)
));
card.setMaximumSize(new Dimension(CARD_MAX_WIDTH, 160));
card.setPreferredSize(new Dimension(CARD_MAX_WIDTH, 160));
card.setAlignmentX(Component.CENTER_ALIGNMENT);
JPanel infoPanel = new JPanel();
infoPanel.setLayout(new BoxLayout(infoPanel, BoxLayout.Y_AXIS));
infoPanel.setBackground(CARD_BACKGROUND);
infoPanel.setOpaque(true);
infoPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
JLabel titleLabel = new JLabel(title);
titleLabel.setFont(HEADER_FONT);
titleLabel.setForeground(new Color(28, 28, 28));
JLabel descLabel = new JLabel("<html><body style='width:210px'>" + description + "</body></html>");
descLabel.setFont(SMALL_FONT);
descLabel.setForeground(new Color(115, 115, 115));
infoPanel.add(titleLabel);
infoPanel.add(Box.createVerticalStrut(3));
infoPanel.add(descLabel);
infoPanel.add(Box.createVerticalGlue());
JPanel centerPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 12, 6));
centerPanel.setBackground(CARD_BACKGROUND);
centerPanel.setOpaque(true);
if (title.contains("TRANSFER")) {
countSpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("transfer.count", "9")),
1, 999, 1
));
countSpinner.setPreferredSize(new Dimension(64, 26));
delaySpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("transfer.delay", "2")),
0, 60, 1
));
delaySpinner.setPreferredSize(new Dimension(64, 26));
card.putClientProperty("countSpinner", countSpinner);
card.putClientProperty("delaySpinner", delaySpinner);
centerPanel.add(createFieldPanel("Počet:", countSpinner));
centerPanel.add(createFieldPanel("Čekání (s):", delaySpinner));
} else if (title.contains("AUTOKLIK")) {
JSpinner xSpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("autoklik.x", "960")),
0, 9999, 1
));
xSpinner.setPreferredSize(new Dimension(70, 26));
card.putClientProperty("xSpinner", xSpinner);
JSpinner ySpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("autoklik.y", "540")),
0, 9999, 1
));
ySpinner.setPreferredSize(new Dimension(70, 26));
card.putClientProperty("ySpinner", ySpinner);
JSpinner intervalSpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("autoklik.interval", "100")),
10, 10000, 10
));
intervalSpinner.setPreferredSize(new Dimension(70, 26));
card.putClientProperty("intervalSpinner", intervalSpinner);
JSpinner clickCountSpinner = new JSpinner(new SpinnerNumberModel(
Integer.parseInt(settings.getProperty("autoklik.count", "10")),
1, 10000, 1
));
clickCountSpinner.setPreferredSize(new Dimension(70, 26));
card.putClientProperty("clickCountSpinner", clickCountSpinner);
centerPanel.add(createFieldPanel("X:", xSpinner));
centerPanel.add(createFieldPanel("Y:", ySpinner));
centerPanel.add(createFieldPanel("Interval (ms):", intervalSpinner));
centerPanel.add(createFieldPanel("Počet kliknutí:", clickCountSpinner));
JButton pickPositionBtn = new JButton("Nastavit");
pickPositionBtn.setPreferredSize(new Dimension(80, 26));
styleButton(pickPositionBtn, ACCENT_BLUE, Color.WHITE, SMALL_FONT);
pickPositionBtn.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
PositionPicker picker = new PositionPicker(null);
new Thread(new Runnable() {
@Override
public void run() {
picker.setVisible(true);
while (picker.isVisible()) {
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
break;
}
}
if (picker.isPositionSelected()) {
Point pos = picker.getSelectedPosition();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
xSpinner.setValue(pos.x);
ySpinner.setValue(pos.y);
logArea.append("✅ (" + pos.x + ", " + pos.y + ")\n");
}
});
}
}
}).start();
}
});
centerPanel.add(createFieldPanel("Pozice:", pickPositionBtn));
}
// Pravý panel - START tlačítko
JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 0));
rightPanel.setBackground(CARD_BACKGROUND);
rightPanel.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
JButton startBtn = new JButton("▶ START");
startBtn.setPreferredSize(new Dimension(90, 32));
styleButton(startBtn, PRIMARY_GREEN, Color.WHITE, SMALL_FONT);
startBtn.addActionListener(startAction);
rightPanel.add(startBtn);
// Komponování karty: info nahoře, nastavení uprostřed, tlačítko dole
card.add(infoPanel, BorderLayout.NORTH);
card.add(centerPanel, BorderLayout.CENTER);
card.add(rightPanel, BorderLayout.SOUTH);
return card;
}
private JPanel createFieldPanel(String labelText, JComponent field) {
JLabel label = new JLabel(labelText);
label.setFont(BODY_FONT);
label.setForeground(new Color(96, 96, 96));
field.setFont(BODY_FONT);
if (field instanceof JSpinner) {
((JSpinner) field).setBorder(BorderFactory.createLineBorder(CARD_BORDER_COLOR));
field.setBackground(new Color(252, 252, 252));
}
JPanel wrapper = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 2));
wrapper.setBackground(CARD_BACKGROUND);
wrapper.add(label);
wrapper.add(field);
return wrapper;
}
private void styleButton(JButton button, Color background, Color foreground, Font font) {
button.setFont(font);
button.setBackground(background);
button.setForeground(foreground);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createEmptyBorder(4, 10, 4, 10));
}
private JButton findStartButton(Container container) {
for (Component comp : container.getComponents()) {
if (comp instanceof JButton) {
JButton button = (JButton) comp;
if ("▶ START".equals(button.getText())) {
return button;
}
}
if (comp instanceof Container) {
JButton nested = findStartButton((Container) comp);
if (nested != null) {
return nested;
}
}
}
return null;
}
/**
* Přesměruje System.out a System.err do log area
*/
private void redirectSystemStreams() {
System.setOut(new java.io.PrintStream(System.out) {
@Override
public void println(String x) {
super.println(x);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
logArea.append(x + "\n");
logArea.setCaretPosition(logArea.getDocument().getLength());
}
});
}
});
System.setErr(new java.io.PrintStream(System.err) {
@Override
public void println(String x) {
super.println(x);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
logArea.append("[CHYBA] " + x + "\n");
logArea.setCaretPosition(logArea.getDocument().getLength());
}
});
}
});
}
/**
* Spustí Transfer automatizaci
*/
private void startTransferAutomation(JPanel transferCard) {
if (isRunning) {
JOptionPane.showMessageDialog(this, "Automatizace již běží!", "Upozornění", JOptionPane.WARNING_MESSAGE);
return;
}
// Získat počet pokémonů a čekání z GUI
JSpinner countSpinner = (JSpinner) transferCard.getClientProperty("countSpinner");
JSpinner delaySpinner = (JSpinner) transferCard.getClientProperty("delaySpinner");
int pokemonCount = (Integer) countSpinner.getValue();
int delaySeconds = (Integer) delaySpinner.getValue();
stopButton.setEnabled(true);
statusLabel.setText("Transfer automatizace běží...");
statusLabel.setForeground(new Color(255, 152, 0));
isRunning = true;
logArea.append("\n========================================\n");
logArea.append("SPOUŠTĚNÍ TRANSFER AUTOMATIZACE\n");
logArea.append("Počet pokémonů: " + pokemonCount + ", Čekání: " + delaySeconds + "s\n");
logArea.append("========================================\n\n");
shouldStop = false;
automationThread = new Thread(new Runnable() {
@Override
public void run() {
try {
automation = new PokemonGoAutomation();
automation.resetTransferredCount();
// Spustit vlákno pro aktualizaci statusu
Thread statusUpdateThread = new Thread(new Runnable() {
@Override
public void run() {
while (isRunning && !shouldStop && !Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(500); // Aktualizovat každých 500ms
final int transferred = automation.getTransferredCount();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (isRunning) {
statusLabel.setText("Transfer běží... Transferováno: " + transferred + "/" + pokemonCount);
}
}
});
} catch (InterruptedException e) {
break;
}
}
}
});
statusUpdateThread.setDaemon(true);
statusUpdateThread.start();
if (!shouldStop) {
automation.runWithCount(pokemonCount, delaySeconds);
totalTransferredCount += automation.getTransferredCount();
}
if (!shouldStop) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Automatizace dokončena! Celkem transferováno: " + totalTransferredCount);
statusLabel.setForeground(new Color(76, 175, 80));
logArea.append("\n✅ Transfer automatizace úspěšně dokončena! Transferováno: " + automation.getTransferredCount() + " pokémonů\n");
}
});
}
} catch (Exception e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Chyba!");
statusLabel.setForeground(new Color(244, 67, 54));
logArea.append("\n❌ Chyba: " + e.getMessage() + "\n");
e.printStackTrace();
}
});
} finally {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
isRunning = false;
stopButton.setEnabled(false);
}
});
}
}
});
automationThread.start();
}
/**
* Spustí autoklik
*/
private void startAutoClick(JPanel autoClickCard) {
if (isRunning) {
JOptionPane.showMessageDialog(this, "Automatizace již běží!", "Upozornění", JOptionPane.WARNING_MESSAGE);
return;
}
// Načtení nastavení
JSpinner xSpinner = (JSpinner) autoClickCard.getClientProperty("xSpinner");
JSpinner ySpinner = (JSpinner) autoClickCard.getClientProperty("ySpinner");
JSpinner intervalSpinner = (JSpinner) autoClickCard.getClientProperty("intervalSpinner");
JSpinner clickCountSpinner = (JSpinner) autoClickCard.getClientProperty("clickCountSpinner");
int x = (Integer) xSpinner.getValue();
int y = (Integer) ySpinner.getValue();
int interval = (Integer) intervalSpinner.getValue();
int clickCount = (Integer) clickCountSpinner.getValue();
// Uložení nastavení
settings.setProperty("autoklik.x", String.valueOf(x));
settings.setProperty("autoklik.y", String.valueOf(y));
settings.setProperty("autoklik.interval", String.valueOf(interval));
settings.setProperty("autoklik.count", String.valueOf(clickCount));
saveSettings();
stopButton.setEnabled(true);
statusLabel.setText("Autoklik běží... (" + x + ", " + y + ")");
statusLabel.setForeground(new Color(255, 152, 0));
isRunning = true;
autoClickRunning = true;
shouldStop = false;
logArea.append("\n========================================\n");
logArea.append("SPOUŠTĚNÍ AUTOKLIKERU\n");
logArea.append("Pozice: (" + x + ", " + y + ")\n");
logArea.append("Interval: " + interval + "ms, Počet kliknutí: " + clickCount + "\n");
logArea.append("========================================\n\n");
automationThread = new Thread(new Runnable() {
@Override
public void run() {
try {
java.awt.Robot robot = new java.awt.Robot();
logArea.append("Spouštím autoklik...\n");
for (int i = 0; i < clickCount && autoClickRunning && !shouldStop; i++) {
// Přesunutí kurzoru na pozici
robot.mouseMove(x, y);
Thread.sleep(10);
// Klik
robot.mousePress(java.awt.event.InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(java.awt.event.InputEvent.BUTTON1_DOWN_MASK);
// Čekání mezi kliknutími
if (i < clickCount - 1 && !shouldStop) {
Thread.sleep(interval);
}
// Update progress každých 10 kliknutí
if ((i + 1) % 10 == 0 && !shouldStop) {
int progress = i + 1;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
logArea.append(" Kliknutí: " + progress + "/" + clickCount + "\n");
}
});
}
}
if (!shouldStop) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Autoklik úspěšně dokončen!");
statusLabel.setForeground(new Color(76, 175, 80));
logArea.append("\n✅ Autoklik úspěšně dokončen! Celkem kliknutí: " + clickCount + "\n");
}
});
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
if (!shouldStop) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
statusLabel.setText("Chyba!");
statusLabel.setForeground(new Color(244, 67, 54));
logArea.append("\n❌ Chyba: " + e.getMessage() + "\n");
e.printStackTrace();
}
});
}
} finally {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
isRunning = false;
autoClickRunning = false;
stopButton.setEnabled(false);
}
});
}
}
});
automationThread.start();
}
/**
* Zastaví automatizaci
*/
private void stopAutomation() {
shouldStop = true;
autoClickRunning = false;
isRunning = false;
stopButton.setEnabled(false);
if (automationThread != null && automationThread.isAlive()) {
automationThread.interrupt();
// Čekej max 2 sekundy na ukončení
try {
automationThread.join(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
logArea.append("\n⚠ Automatizace byla přerušena uživatelem\n");
statusLabel.setText("Přerušeno");
statusLabel.setForeground(new Color(244, 67, 54));
}
});
}
/**
* Načte uložená nastavení ze souboru
*/
private void loadSettings() {
settings = new Properties();
File configFile = new File(CONFIG_FILE);
if (configFile.exists()) {
try (java.io.FileInputStream fis = new java.io.FileInputStream(configFile)) {
settings.load(fis);
} catch (IOException e) {
System.err.println("Chyba při načítání nastavení: " + e.getMessage());
}
}
// Výchozí hodnoty, pokud nastavení neexistují
if (!settings.containsKey("transfer.count")) {
settings.setProperty("transfer.count", "9");
}
if (!settings.containsKey("transfer.delay")) {
settings.setProperty("transfer.delay", "2");
}
if (!settings.containsKey("window.width")) {
settings.setProperty("window.width", "700");
}
if (!settings.containsKey("window.height")) {
settings.setProperty("window.height", "600");
}
if (!settings.containsKey("window.x")) {
settings.setProperty("window.x", "-1");
}
if (!settings.containsKey("window.y")) {
settings.setProperty("window.y", "-1");
}
}
/**
* Uloží aktuální nastavení do souboru
*/
private void saveSettings() {
// Uložení hodnot z spinnerů
if (countSpinner != null) {
settings.setProperty("transfer.count", countSpinner.getValue().toString());
}
if (delaySpinner != null) {
settings.setProperty("transfer.delay", delaySpinner.getValue().toString());
}
// Uložení velikosti a pozice okna
settings.setProperty("window.width", String.valueOf(getWidth()));
settings.setProperty("window.height", String.valueOf(getHeight()));
settings.setProperty("window.x", String.valueOf(getX()));
settings.setProperty("window.y", String.valueOf(getY()));
try (java.io.FileOutputStream fos = new java.io.FileOutputStream(CONFIG_FILE)) {
settings.store(fos, "Pokémon GO Automatizace - Nastavení");
} catch (IOException e) {
System.err.println("Chyba při ukládání nastavení: " + e.getMessage());
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
PokemonGoGUI frame = new PokemonGoGUI();
frame.setVisible(true);
}
});
}
}

View File

@ -0,0 +1,95 @@
package com.pokemongo;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
public class PositionPicker extends JWindow {
private Point selectedPosition = null;
private boolean positionSelected = false;
private PositionPickerListener listener = null;
public interface PositionPickerListener {
void onPositionSelected(Point position);
void onCancelled();
}
public PositionPicker(PositionPickerListener listener) {
this.listener = listener;
GraphicsDevice gd = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice();
Rectangle bounds = gd.getDefaultConfiguration().getBounds();
setBounds(bounds);
System.out.println("PositionPicker vytvořen: " + bounds);
setFocusable(true);
setBackground(new Color(0, 0, 0, 0));
// Přidáme panel pro vykreslování
JPanel panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Lehké šedé pozadí
g2d.setColor(new Color(100, 100, 100, 10));
g2d.fillRect(0, 0, getWidth(), getHeight());
// Instrukce
g2d.setColor(new Color(0, 0, 0, 200));
g2d.fillRect(10, 10, 400, 60);
g2d.setColor(new Color(255, 255, 0, 255));
g2d.setFont(new Font("Monospaced", Font.BOLD, 12));
g2d.drawString("VYBERTE POZICI - Klikněte na místo kde chcete klikat", 20, 30);
g2d.drawString("ESC: Zrušit", 20, 50);
}
};
panel.setOpaque(false);
panel.setBackground(new Color(0, 0, 0, 0));
setContentPane(panel);
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
selectedPosition = new Point(e.getX(), e.getY());
positionSelected = true;
System.out.println("✅ Pozice vybrána: " + selectedPosition);
if (listener != null) {
listener.onPositionSelected(selectedPosition);
}
dispose();
}
});
panel.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
System.out.println("ESC - Výběr zrušen");
positionSelected = false;
if (listener != null) {
listener.onCancelled();
}
dispose();
}
}
});
panel.setFocusable(true);
panel.requestFocus();
}
public Point getSelectedPosition() {
return selectedPosition;
}
public boolean isPositionSelected() {
return positionSelected;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
src/main/resources/pok1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
src/main/resources/t1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
src/main/resources/t2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB